]> Git Repo - binutils.git/blob - gdb/remote-vx.c
* udip2soc.c (UDIConnect): replace union wait with int.
[binutils.git] / gdb / remote-vx.c
1 /* Memory-access and commands for remote VxWorks processes, for GDB.
2    Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3    Contributed by Wind River Systems and Cygnus Support.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "defs.h"
22 #include "frame.h"
23 #include "inferior.h"
24 #include "wait.h"
25 #include "target.h"
26 #include "gdbcore.h"
27 #include "command.h"
28 #include "symtab.h"
29 #include "complaints.h"
30
31 #include <string.h>
32 #include <errno.h>
33 #include <signal.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #define malloc bogon_malloc     /* Sun claims "char *malloc()" not void * */
38 #define free bogon_free         /* Sun claims "int free()" not void */
39 #define realloc bogon_realloc   /* Sun claims "char *realloc()", not void * */
40 #include <rpc/rpc.h>
41 #undef malloc
42 #undef free
43 #undef realloc
44 #include <sys/time.h>           /* UTek's <rpc/rpc.h> doesn't #incl this */
45 #include <netdb.h>
46 #include "vx-share/ptrace.h"
47 #include "vx-share/xdr_ptrace.h"
48 #include "vx-share/xdr_ld.h"
49 #include "vx-share/xdr_rdb.h"
50 #include "vx-share/dbgRpcLib.h"
51
52 #include <symtab.h>
53
54 extern void symbol_file_command ();
55 extern int stop_soon_quietly;           /* for wait_for_inferior */
56
57 static int net_ptrace_clnt_call ();     /* Forward decl */
58 static enum clnt_stat net_clnt_call (); /* Forward decl */
59 extern struct target_ops vx_ops, vx_run_ops;    /* Forward declaration */
60
61 /* Saved name of target host and called function for "info files".
62    Both malloc'd.  */
63
64 static char *vx_host;
65 static char *vx_running;                /* Called function */
66
67 /* Nonzero means target that is being debugged remotely has a floating
68    point processor.  */
69
70 static int target_has_fp;
71
72 /* Default error message when the network is forking up.  */
73
74 static const char rpcerr[] = "network target debugging:  rpc error";
75
76 CLIENT *pClient;         /* client used in net debugging */
77 static int ptraceSock = RPC_ANYSOCK;
78
79 enum clnt_stat net_clnt_call();
80 static void parse_args ();
81
82 static struct timeval rpcTimeout = { 10, 0 };
83
84 static char *skip_white_space ();
85 static char *find_white_space ();
86  
87 /* Tell the VxWorks target system to download a file.
88    The load addresses of the text, data, and bss segments are
89    stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively).
90    Returns 0 for success, -1 for failure.  */
91
92 static int
93 net_load (filename, pTextAddr, pDataAddr, pBssAddr)
94     char *filename;
95     CORE_ADDR *pTextAddr;
96     CORE_ADDR *pDataAddr;
97     CORE_ADDR *pBssAddr;
98     {
99     enum clnt_stat status;
100     struct ldfile ldstruct;
101     struct timeval load_timeout;
102  
103     bzero ((char *) &ldstruct, sizeof (ldstruct));
104
105     /* We invoke clnt_call () here directly, instead of through
106        net_clnt_call (), because we need to set a large timeout value.
107        The load on the target side can take quite a while, easily
108        more than 10 seconds.  The user can kill this call by typing
109        CTRL-C if there really is a problem with the load.  
110
111        Do not change the tv_sec value without checking -- select() imposes
112        a limit of 10**8 on it for no good reason that I can see...  */
113
114     load_timeout.tv_sec = 99999999;   /* A large number, effectively inf. */
115     load_timeout.tv_usec = 0;
116  
117     status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
118                         &ldstruct, load_timeout);
119
120     if (status == RPC_SUCCESS)
121       {
122         if (*ldstruct.name == 0)        /* load failed on VxWorks side */
123           return -1;
124         *pTextAddr = ldstruct.txt_addr;
125         *pDataAddr = ldstruct.data_addr;
126         *pBssAddr = ldstruct.bss_addr;
127         return 0;
128       }
129     else
130         return -1;
131     }
132       
133 /* returns 0 if successful, errno if RPC failed or VxWorks complains. */
134
135 static int
136 net_break (addr, procnum)
137     int addr;
138     u_long procnum;
139     {
140     enum clnt_stat status;
141     int break_status;
142     Rptrace ptrace_in;  /* XXX This is stupid.  It doesn't need to be a ptrace
143                            structure.  How about something smaller? */
144
145     bzero ((char *) &ptrace_in, sizeof (ptrace_in));
146     break_status = 0;
147
148     ptrace_in.addr = addr;
149     ptrace_in.pid = inferior_pid;
150
151     status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
152                             &break_status);
153
154     if (status != RPC_SUCCESS)
155         return errno;
156
157     if (break_status == -1)
158       return ENOMEM;
159     return break_status;        /* probably (FIXME) zero */
160     }
161  
162 /* returns 0 if successful, errno otherwise */
163
164 static int
165 vx_insert_breakpoint (addr)
166     int addr;
167     {
168     return net_break (addr, VX_BREAK_ADD);
169     }
170
171 /* returns 0 if successful, errno otherwise */
172
173 static int
174 vx_remove_breakpoint (addr)
175     int addr;
176     {
177     return net_break (addr, VX_BREAK_DELETE);
178     }
179
180 /* Start an inferior process and sets inferior_pid to its pid.
181    EXEC_FILE is the file to run.
182    ALLARGS is a string containing the arguments to the program.
183    ENV is the environment vector to pass.
184    Returns process id.  Errors reported with error().
185    On VxWorks, we ignore exec_file.  */
186  
187 static void
188 vx_create_inferior (exec_file, args, env)
189      char *exec_file;
190      char *args;
191      char **env;
192 {
193   enum clnt_stat status;
194   arg_array passArgs;
195   TASK_START taskStart;
196
197   bzero ((char *) &passArgs, sizeof (passArgs));
198   bzero ((char *) &taskStart, sizeof (taskStart));
199
200   /* parse arguments, put them in passArgs */
201
202   parse_args (args, &passArgs);
203
204   if (passArgs.arg_array_len == 0)
205     error ("You must specify a function name to run, and arguments if any");
206
207   status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
208                           xdr_TASK_START, &taskStart);
209
210   if ((status != RPC_SUCCESS) || (taskStart.status == -1))
211     error ("Can't create process on remote target machine");
212
213   /* Save the name of the running function */
214   vx_running = savestring (passArgs.arg_array_val[0],
215                            strlen (passArgs.arg_array_val[0]));
216
217 #ifdef CREATE_INFERIOR_HOOK
218   CREATE_INFERIOR_HOOK (pid);
219 #endif  
220
221   push_target (&vx_run_ops);
222   inferior_pid = taskStart.pid;
223
224   /* We will get a trace trap after one instruction.
225      Insert breakpoints and continue.  */
226
227   init_wait_for_inferior ();
228
229   /* Set up the "saved terminal modes" of the inferior
230      based on what modes we are starting it with.  */
231   target_terminal_init ();
232
233   /* Install inferior's terminal modes.  */
234   target_terminal_inferior ();
235
236   stop_soon_quietly = 1;
237   wait_for_inferior ();         /* Get the task spawn event */
238   stop_soon_quietly = 0;
239
240   /* insert_step_breakpoint ();  FIXME, do we need this?  */
241   proceed(-1, -1, 0);
242 }
243
244 /* Fill ARGSTRUCT in argc/argv form with the arguments from the
245    argument string ARGSTRING.  */
246
247 static void
248 parse_args (arg_string, arg_struct)
249      register char *arg_string;
250      arg_array *arg_struct;
251 {
252   register int arg_count = 0;   /* number of arguments */
253   register int arg_index = 0;
254   register char *p0;
255  
256   bzero ((char *) arg_struct, sizeof (arg_array));
257  
258   /* first count how many arguments there are */
259
260   p0 = arg_string;
261   while (*p0 != '\0')
262     {
263       if (*(p0 = skip_white_space (p0)) == '\0')
264         break;
265       p0 = find_white_space (p0);
266       arg_count++;
267     }
268
269   arg_struct->arg_array_len = arg_count;
270   arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
271                                                  * sizeof (char *));
272
273   /* now copy argument strings into arg_struct.  */
274
275   while (*(arg_string = skip_white_space (arg_string)))
276     {
277       p0 = find_white_space (arg_string);
278       arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
279                                                            p0 - arg_string);
280       arg_string = p0;
281     }
282
283   arg_struct->arg_array_val[arg_count] = NULL;
284 }
285
286 /* Advance a string pointer across whitespace and return a pointer
287    to the first non-white character.  */
288
289 static char *
290 skip_white_space (p)
291      register char *p;
292 {
293   while (*p == ' ' || *p == '\t')
294     p++;
295   return p;
296 }
297     
298 /* Search for the first unquoted whitespace character in a string.
299    Returns a pointer to the character, or to the null terminator
300    if no whitespace is found.  */
301
302 static char *
303 find_white_space (p)
304      register char *p;
305 {
306   register int c;
307
308   while ((c = *p) != ' ' && c != '\t' && c)
309     {
310       if (c == '\'' || c == '"')
311         {
312           while (*++p != c && *p)
313             {
314               if (*p == '\\')
315                 p++;
316             }
317           if (!*p)
318             break;
319         }
320       p++;
321     }
322   return p;
323 }
324     
325 /* Poll the VxWorks target system for an event related
326    to the debugged task.
327    Returns -1 if remote wait failed, task status otherwise.  */
328
329 static int
330 net_wait (pEvent)
331     RDB_EVENT *pEvent;
332 {
333     int pid;
334     enum clnt_stat status;
335
336     bzero ((char *) pEvent, sizeof (RDB_EVENT));
337
338     pid = inferior_pid;
339     status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, pEvent);
340
341     return (status == RPC_SUCCESS)? pEvent->status: -1;
342 }
343     
344 /* Suspend the remote task.
345    Returns -1 if suspend fails on target system, 0 otherwise.  */
346
347 static int
348 net_quit ()
349 {
350     int pid;
351     int quit_status;
352     enum clnt_stat status;
353
354     quit_status = 0;
355
356     /* don't let rdbTask suspend itself by passing a pid of 0 */
357
358     if ((pid = inferior_pid) == 0)
359         return -1;
360
361     status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
362                             &quit_status);
363
364     return (status == RPC_SUCCESS)? quit_status: -1;
365 }
366
367 /* Read a register or registers from the remote system.  */
368
369 static void
370 vx_read_register (regno)
371      int regno;
372 {
373   int status;
374   Rptrace ptrace_in;
375   Ptrace_return ptrace_out;
376   C_bytes in_data;
377   C_bytes out_data;
378   extern char registers[];
379
380   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
381   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
382
383   /* FIXME, eventually only get the ones we need.  */
384   registers_fetched ();
385   
386   ptrace_in.pid = inferior_pid;
387   ptrace_out.info.more_data = (caddr_t) &out_data;
388 #ifndef I80960
389   out_data.len   = 18 * REGISTER_RAW_SIZE (0);          /* FIXME m68k hack */
390 #else
391   out_data.len = (16 + 16 + 3) * REGISTER_RAW_SIZE (0);
392 #endif
393   out_data.bytes = (caddr_t) registers;
394   
395   status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
396   if (status)
397     error (rpcerr);
398   if (ptrace_out.status == -1)
399     {
400       errno = ptrace_out.errno;
401       perror_with_name ("net_ptrace_clnt_call(PTRACE_GETREGS)");
402     }
403   
404 #ifdef I80960
405
406   {
407     /* If the target has floating point registers, fetch them.
408        Otherwise, zero the floating point register values in
409        registers[] for good measure, even though we might not
410        need to.  */
411     /* @@ Can't use this -- the rdb library for the 960 target
412        doesn't support setting or retrieving FP regs.  KR  */
413 #if 0
414     struct fp_status inferior_fp_registers;
415
416     if (target_has_fp)
417       {
418         ptrace_in.pid = inferior_pid;
419         ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
420         status = net_ptrace_clnt_call (PTRACE_GETFPREGS,
421                                        &ptrace_in, &ptrace_out);
422         if (status)
423           error (rpcerr);
424         if (ptrace_out.status == -1)
425           {
426             errno = ptrace_out.errno;
427             perror_with_name ("net_ptrace_clnt_call(PTRACE_GETFPREGS)");
428           }
429
430         bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
431                REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
432       }
433     else
434       {
435         bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
436                REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
437       }
438 #endif
439   }
440 #else  /* not 960, thus must be 68000:  FIXME!  */
441
442   if (target_has_fp)
443     {
444       ptrace_in.pid = inferior_pid;
445       ptrace_out.info.more_data = (caddr_t) &out_data;
446       out_data.len   =  8 * REGISTER_RAW_SIZE (FP0_REGNUM)      /* FIXME */
447                      + (3 * sizeof (REGISTER_TYPE));
448       out_data.bytes = (caddr_t) &registers[REGISTER_BYTE (FP0_REGNUM)];
449   
450       status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
451       if (status)
452         error (rpcerr);
453       if (ptrace_out.status == -1)
454         {
455           errno = ptrace_out.errno;
456           perror_with_name ("net_ptrace_clnt_call(PTRACE_GETFPREGS)");
457         }
458     }
459   else
460     {
461       bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
462              8 * REGISTER_RAW_SIZE (FP0_REGNUM));
463       bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
464              3 * sizeof (REGISTER_TYPE));
465     }
466 #endif  /* various architectures */
467 }
468
469 /* Prepare to store registers.  Since we will store all of them,
470    read out their current values now.  */
471
472 static void
473 vx_prepare_to_store ()
474 {
475   /* Fetch all registers, if any of them are not yet fetched.  */
476   read_register_bytes (0, NULL, REGISTER_BYTES);
477 }
478
479
480 /* Store our register values back into the inferior.
481    If REGNO is -1, do this for all registers.
482    Otherwise, REGNO specifies which register (so we can save time).  */
483    /* FIXME, look at REGNO to save time here */
484
485 static void
486 vx_write_register (regno)
487      int regno;
488 {
489   C_bytes in_data;
490   C_bytes out_data;
491   extern char registers[];
492   int status;
493   Rptrace ptrace_in;
494   Ptrace_return ptrace_out;
495
496   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
497   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
498
499   ptrace_in.pid = inferior_pid;
500   ptrace_in.info.ttype     = DATA;
501   ptrace_in.info.more_data = (caddr_t) &in_data;
502
503   in_data.bytes = registers;
504
505 #ifdef I80960
506
507   in_data.len = (16 + 16 + 3) * sizeof (REGISTER_TYPE);
508
509 #else  /* not 960 -- assume m68k -- FIXME */
510
511   in_data.len = 18 * sizeof (REGISTER_TYPE);
512
513 #endif  /* Different register sets */
514
515   /* XXX change second param to be a proc number */
516   status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
517   if (status)
518       error (rpcerr);
519   if (ptrace_out.status == -1)
520     {
521       errno = ptrace_out.errno;
522       perror_with_name ("net_ptrace_clnt_call(PTRACE_SETREGS)");
523     }
524
525   /* Store floating point registers if the target has them.  */
526
527   if (target_has_fp)
528     {
529       ptrace_in.pid = inferior_pid;
530       ptrace_in.info.ttype     = DATA;
531       ptrace_in.info.more_data = (caddr_t) &in_data;
532
533
534 #ifdef I80960
535 #if 0 /* @@ Not supported by target.  */
536       in_data.bytes = &registers[REGISTER_BYTE (FP0_REGNUM)];
537       in_data.len = 4 * REGISTER_RAW_SIZE (FP0_REGNUM);
538 #endif
539 #else  /* not 960 -- assume m68k -- FIXME */
540
541       in_data.bytes = &registers[REGISTER_BYTE (FP0_REGNUM)];
542       in_data.len = (8 * REGISTER_RAW_SIZE (FP0_REGNUM)
543                       + (3 * sizeof (REGISTER_TYPE)));
544
545 #endif  /* Different register sets */
546
547       status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in, &ptrace_out);
548       if (status)
549           error (rpcerr);
550       if (ptrace_out.status == -1)
551         {
552           errno = ptrace_out.errno;
553           perror_with_name ("net_ptrace_clnt_call(PTRACE_SETFPREGS)");
554         }
555     }
556 }
557
558 /* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
559    to debugger memory starting at MYADDR.  WRITE is true if writing to the
560    inferior.
561    Result is the number of bytes written or read (zero if error).  The
562    protocol allows us to return a negative count, indicating that we can't
563    handle the current address but can handle one N bytes further, but
564    vxworks doesn't give us that information.  */
565
566 static int
567 vx_xfer_memory (memaddr, myaddr, len, write, target)
568      CORE_ADDR memaddr;
569      char *myaddr;
570      int len;
571      int write;
572      struct target_ops *target;                 /* ignored */
573 {
574   int status;
575   Rptrace ptrace_in;
576   Ptrace_return ptrace_out;
577   C_bytes data;
578
579   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
580   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
581
582   ptrace_in.pid = inferior_pid;         /* XXX pid unnecessary for READDATA */
583   ptrace_in.addr = (int) memaddr;       /* Where from */
584   ptrace_in.data = len;                 /* How many bytes */
585
586   if (write)
587     {
588       ptrace_in.info.ttype     = DATA;
589       ptrace_in.info.more_data = (caddr_t) &data;
590
591       data.bytes = (caddr_t) myaddr;    /* Where from */
592       data.len   = len;                 /* How many bytes (again, for XDR) */
593
594       /* XXX change second param to be a proc number */
595       status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in, &ptrace_out);
596     }
597   else
598     {
599       ptrace_out.info.more_data = (caddr_t) &data;
600       data.bytes = myaddr;              /* Where to */
601       data.len   = len;                 /* How many (again, for XDR) */
602
603       /* XXX change second param to be a proc number */
604       status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
605     }
606
607   if (status)
608       error (rpcerr);
609   if (ptrace_out.status == -1)
610     {
611       return 0;         /* No bytes moved */
612     }
613   return len;           /* Moved *all* the bytes */
614 }
615
616 static void
617 vx_files_info ()
618 {
619   printf ("\tAttached to host `%s'", vx_host);
620   printf (", which has %sfloating point", target_has_fp? "": "no ");
621   printf (".\n");
622 }
623
624 static void
625 vx_run_files_info ()
626 {
627   printf ("\tRunning %s VxWorks process %s", 
628           vx_running? "child": "attached",
629           local_hex_string(inferior_pid));
630   if (vx_running)
631     printf (", function `%s'", vx_running);
632   printf(".\n");
633 }
634
635 static void
636 vx_resume (step, siggnal)
637      int step;
638      int siggnal;
639 {
640   int status;
641   Rptrace ptrace_in;
642   Ptrace_return ptrace_out;
643
644   if (siggnal != 0 && siggnal != stop_signal)
645     error ("Cannot send signals to VxWorks processes");
646
647   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
648   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
649
650   ptrace_in.pid = inferior_pid;
651   ptrace_in.addr = 1;   /* Target side insists on this, or it panics.  */
652
653   /* XXX change second param to be a proc number */
654   status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
655                                  &ptrace_in, &ptrace_out);
656   if (status)
657       error (rpcerr);
658   if (ptrace_out.status == -1)
659     {
660       errno = ptrace_out.errno;
661       perror_with_name ("Resuming remote process");
662     }
663 }
664
665 static void
666 vx_mourn_inferior ()
667 {
668   pop_target ();                /* Pop back to no-child state */
669   generic_mourn_inferior ();
670 }
671
672 \f
673 /* This function allows the addition of incrementally linked object files.  */
674
675 static void
676 vx_load_command (arg_string, from_tty)
677      char* arg_string;
678      int from_tty;
679 {
680   CORE_ADDR text_addr;
681   CORE_ADDR data_addr;
682   CORE_ADDR bss_addr;
683   
684   if (arg_string == 0)
685     error ("The load command takes a file name");
686
687   arg_string = tilde_expand (arg_string);
688   make_cleanup (free, arg_string);
689
690   dont_repeat ();
691
692   QUIT;
693   immediate_quit++;
694   if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
695     error ("Load failed on target machine");
696   immediate_quit--;
697
698   /* FIXME, for now we ignore data_addr and bss_addr.  */
699   symbol_file_add (arg_string, from_tty, text_addr, 0, 0, 0);
700 }
701
702 #ifdef FIXME  /* Not ready for prime time */
703 /* Single step the target program at the source or machine level.
704    Takes an error exit if rpc fails.
705    Returns -1 if remote single-step operation fails, else 0.  */
706
707 static int
708 net_step ()
709 {
710   enum clnt_stat status;
711   int step_status;
712   SOURCE_STEP source_step;
713
714   source_step.taskId = inferior_pid;
715
716   if (step_range_end)
717     {
718       source_step.startAddr = step_range_start;
719       source_step.endAddr = step_range_end;
720     }
721   else
722     {
723       source_step.startAddr = 0;
724       source_step.endAddr = 0;
725     }
726
727   status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
728                           xdr_int, &step_status);
729
730   if (status == RPC_SUCCESS)
731     return step_status;
732   else 
733     error (rpcerr);
734 }
735 #endif
736
737 /* Emulate ptrace using RPC calls to the VxWorks target system.
738    Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise.  */
739
740 static int
741 net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
742     enum ptracereq request;
743     Rptrace *pPtraceIn;
744     Ptrace_return *pPtraceOut;
745 {
746   enum clnt_stat status;
747
748   status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
749                           pPtraceOut);
750
751   if (status != RPC_SUCCESS)
752       return -1;
753
754   return 0;
755 }
756
757 /* Query the target for the name of the file from which VxWorks was
758    booted.  pBootFile is the address of a pointer to the buffer to
759    receive the file name; if the pointer pointed to by pBootFile is 
760    NULL, memory for the buffer will be allocated by XDR.
761    Returns -1 if rpc failed, 0 otherwise.  */
762
763 static int
764 net_get_boot_file (pBootFile)
765      char **pBootFile;
766 {
767   enum clnt_stat status;
768
769   status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
770                           xdr_wrapstring, pBootFile);
771   return (status == RPC_SUCCESS) ? 0 : -1;
772 }
773
774 /* Fetch a list of loaded object modules from the VxWorks target.
775    Returns -1 if rpc failed, 0 otherwise
776    There's no way to check if the returned loadTable is correct.
777    VxWorks doesn't check it.  */
778
779 static int
780 net_get_symbols (pLoadTable)
781      ldtabl *pLoadTable;                /* return pointer to ldtabl here */
782 {
783   enum clnt_stat status;
784
785   bzero ((char *) pLoadTable, sizeof (struct ldtabl));
786
787   status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
788   return (status == RPC_SUCCESS) ? 0 : -1;
789 }
790
791 /* Look up a symbol in the VxWorks target's symbol table.
792    Returns status of symbol read on target side (0=success, -1=fail)
793    Returns -1 and complain()s if rpc fails.  */
794
795 struct complaint cant_contact_target =
796   {"Lost contact with VxWorks target", 0, 0};
797
798 static int
799 vx_lookup_symbol (name, pAddr)
800      char *name;                /* symbol name */
801      CORE_ADDR *pAddr;
802 {
803   enum clnt_stat status;
804   SYMBOL_ADDR symbolAddr;
805
806   *pAddr = 0;
807   bzero ((char *) &symbolAddr, sizeof (symbolAddr));
808
809   status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
810                           xdr_SYMBOL_ADDR, &symbolAddr);
811   if (status != RPC_SUCCESS) {
812       complain (&cant_contact_target);
813       return -1;
814   }
815
816   *pAddr = symbolAddr.addr;
817   return symbolAddr.status;
818 }
819
820 /* Check to see if the VxWorks target has a floating point coprocessor.
821    Returns 1 if target has floating point processor, 0 otherwise.
822    Calls error() if rpc fails.  */
823
824 static int
825 net_check_for_fp ()
826 {
827   enum clnt_stat status;
828   bool_t fp = 0;        /* true if fp processor is present on target board */
829
830   status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
831   if (status != RPC_SUCCESS)
832       error (rpcerr);
833
834    return (int) fp;
835 }
836
837 /* Establish an RPC connection with the VxWorks target system.
838    Calls error () if unable to establish connection.  */
839
840 static void
841 net_connect (host)
842      char *host;
843 {
844   struct sockaddr_in destAddr;
845   struct hostent *destHost;
846   unsigned long addr;
847   
848   /* Get the internet address for the given host.  Allow a numeric
849      IP address or a hostname.  */
850
851   addr = inet_addr (host);
852   if (addr == -1)
853     {
854       destHost = (struct hostent *) gethostbyname (host);
855       if (destHost == NULL)
856         error ("Invalid hostname.  Couldn't find remote host address.");
857       addr = * (unsigned long *) destHost->h_addr;
858     }
859
860   bzero (&destAddr, sizeof (destAddr));
861
862   destAddr.sin_addr.s_addr = addr;
863   destAddr.sin_family      = AF_INET;
864   destAddr.sin_port        = 0; /* set to actual port that remote
865                                    ptrace is listening on.  */
866
867   /* Create a tcp client transport on which to issue
868      calls to the remote ptrace server.  */
869
870   ptraceSock = RPC_ANYSOCK;
871   pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
872   /* FIXME, here is where we deal with different version numbers of the proto */
873   
874   if (pClient == NULL)
875     {
876       clnt_pcreateerror ("\tnet_connect");
877       error ("Couldn't connect to remote target.");
878     }
879 }
880 \f
881 /* Sleep for the specified number of milliseconds 
882  * (assumed to be less than 1000).
883  * If select () is interrupted, returns immediately;
884  * takes an error exit if select () fails for some other reason.
885  */
886
887 static void
888 sleep_ms (ms)
889      long ms;
890 {
891   struct timeval select_timeout;
892   int status;
893
894   select_timeout.tv_sec = 0;
895   select_timeout.tv_usec = ms * 1000;
896
897   status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
898
899   if (status < 0 && errno != EINTR)
900     perror_with_name ("select");
901 }
902
903 /* Wait for control to return from inferior to debugger.
904    If inferior gets a signal, we may decide to start it up again
905    instead of returning.  That is why there is a loop in this function.
906    When this function actually returns it means the inferior
907    should be left stopped and GDB should read more commands.  */
908
909 /* For network debugging with VxWorks.
910  * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
911  * so vx_wait() receives this information directly from
912  * VxWorks instead of trying to figure out what happenned via a wait() call.
913  */
914
915 static int
916 vx_wait (status)
917      int *status;
918 {
919   register int pid;
920   WAITTYPE w;
921   RDB_EVENT rdbEvent;
922   int quit_failed;
923
924   do
925     {
926       /* If CTRL-C is hit during this loop,
927          suspend the inferior process.  */
928
929       quit_failed = 0;
930       if (quit_flag)
931         {
932           quit_failed = (net_quit () == -1);
933           quit_flag = 0;
934         }
935
936       /* If a net_quit () or net_wait () call has failed,
937          allow the user to break the connection with the target.
938          We can't simply error () out of this loop, since the 
939          data structures representing the state of the inferior
940          are in an inconsistent state.  */
941
942       if (quit_failed || net_wait (&rdbEvent) == -1)
943         {
944           terminal_ours ();
945           if (query ("Can't %s.  Disconnect from target system? ",
946                      (quit_failed) ? "suspend remote task"
947                                    : "get status of remote task"))
948             {
949               target_mourn_inferior();
950               error ("Use the \"target\" command to reconnect.");
951             }
952           else
953             {
954               terminal_inferior ();
955               continue;
956             }
957         }
958       
959       pid = rdbEvent.taskId;
960       if (pid == 0)
961         {
962           sleep_ms (200);       /* FIXME Don't kill the network too badly */
963         }
964       else if (pid != inferior_pid)
965         fatal ("Bad pid for debugged task: %s\n", local_hex_string(pid));
966     } while (pid == 0);
967
968   /* FIXME, eventually do more then SIGTRAP on everything...  */
969   switch (rdbEvent.eventType)
970     {
971     case EVENT_EXIT:
972       WSETEXIT (w, 0);
973       /* FIXME is it possible to distinguish between a
974          XXX   normal vs abnormal exit in VxWorks? */
975       break;
976
977     case EVENT_START:           /* Task was just started. */
978       WSETSTOP (w, SIGTRAP);
979       break;
980
981     case EVENT_STOP:
982       WSETSTOP (w, SIGTRAP);
983       /* XXX was it stopped by a signal?  act accordingly */
984       break;
985
986     case EVENT_BREAK:           /* Breakpoint was hit. */
987       WSETSTOP (w, SIGTRAP);
988       break;
989
990     case EVENT_SUSPEND:         /* Task was suspended, probably by ^C. */
991       WSETSTOP (w, SIGINT);
992       break;
993
994     case EVENT_BUS_ERR:         /* Task made evil nasty reference. */
995       WSETSTOP (w, SIGBUS);
996       break;
997
998     case EVENT_ZERO_DIV:        /* Division by zero */
999       WSETSTOP (w, SIGFPE);     /* Like Unix, call it a float exception. */
1000       break;
1001
1002     case EVENT_SIGNAL:
1003       /* The target is not running Unix, and its
1004          faults/traces do not map nicely into Unix signals.
1005          Make sure they do not get confused with Unix signals
1006          by numbering them with values higher than the highest
1007          legal Unix signal.  code in the arch-dependent PRINT_RANDOM_SIGNAL
1008          routine will interpret the value for wait_for_inferior.  */
1009       WSETSTOP (w, rdbEvent.sigType + NSIG);
1010       break;
1011     } /* switch */
1012   *status = *(int *)&w;         /* Grumble union wait crap Grumble */
1013   return pid;
1014 }
1015 \f
1016 static int
1017 symbol_stub (arg)
1018      char *arg;
1019 {
1020   symbol_file_command (arg, 0);
1021   return 1;
1022 }
1023
1024 static int
1025 add_symbol_stub (arg)
1026      char *arg;
1027 {
1028   struct ldfile *pLoadFile = (struct ldfile *)arg;
1029
1030   printf("\t%s: ", pLoadFile->name);
1031   symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0, 0, 0);
1032   printf ("ok\n");
1033   return 1;
1034 }
1035 /* Target command for VxWorks target systems.
1036
1037    Used in vxgdb.  Takes the name of a remote target machine
1038    running vxWorks and connects to it to initialize remote network
1039    debugging.  */
1040
1041 static void
1042 vx_open (args, from_tty)
1043      char *args;
1044      int from_tty;
1045 {
1046   extern int close ();
1047   char *bootFile;
1048   extern char *source_path;
1049   struct ldtabl loadTable;
1050   struct ldfile *pLoadFile;
1051   int i;
1052   extern CLIENT *pClient;
1053
1054   if (!args)
1055     error_no_arg ("target machine name");
1056
1057   target_preopen (from_tty);
1058   
1059   unpush_target (&vx_ops);
1060   printf ("Attaching remote machine across net...\n");
1061   fflush (stdout);
1062
1063   /* Allow the user to kill the connect attempt by typing ^C.
1064      Wait until the call to target_has_fp () completes before
1065      disallowing an immediate quit, since even if net_connect ()
1066      is successful, the remote debug server might be hung.  */
1067
1068   immediate_quit++;
1069
1070   net_connect (args);
1071   target_has_fp = net_check_for_fp ();
1072   printf_filtered ("Connected to %s.\n", args);
1073
1074   immediate_quit--;
1075
1076   push_target (&vx_ops);
1077
1078   /* Save a copy of the target host's name.  */
1079   vx_host = savestring (args, strlen (args));
1080
1081   /* Find out the name of the file from which the target was booted
1082      and load its symbol table.  */
1083
1084   printf_filtered ("Looking in Unix path for all loaded modules:\n");
1085   bootFile = NULL;
1086   if (!net_get_boot_file (&bootFile))
1087     {
1088       if (*bootFile) {
1089         printf_filtered ("\t%s: ", bootFile);
1090         if (catch_errors (symbol_stub, bootFile,
1091                 "Error while reading symbols from boot file:\n"))
1092           puts_filtered ("ok\n");
1093       } else if (from_tty)
1094         printf ("VxWorks kernel symbols not loaded.\n");
1095     }
1096   else
1097     error ("Can't retrieve boot file name from target machine.");
1098
1099   clnt_freeres (pClient, xdr_wrapstring, &bootFile);
1100
1101   if (net_get_symbols (&loadTable) != 0)
1102     error ("Can't read loaded modules from target machine");
1103
1104   i = 0-1;
1105   while (++i < loadTable.tbl_size)
1106     {
1107       QUIT;     /* FIXME, avoids clnt_freeres below:  mem leak */
1108       pLoadFile = &loadTable.tbl_ent [i];
1109 #ifdef WRS_ORIG
1110   {
1111     register int desc;
1112     struct cleanup *old_chain;
1113     char *fullname = NULL;
1114
1115     desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
1116     if (desc < 0)
1117         perror_with_name (pLoadFile->name);
1118     old_chain = make_cleanup (close, desc);
1119     add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
1120                       pLoadFile->bss_addr);
1121     do_cleanups (old_chain);
1122   }
1123 #else
1124       /* Botches, FIXME:
1125          (1)  Searches the PATH, not the source path.
1126          (2)  data and bss are assumed to be at the usual offsets from text.  */
1127       catch_errors (add_symbol_stub, (char *)pLoadFile, (char *)0);
1128 #endif
1129     }
1130   printf_filtered ("Done.\n");
1131
1132   clnt_freeres (pClient, xdr_ldtabl, &loadTable);
1133 }
1134 \f
1135 /* Takes a task started up outside of gdb and ``attaches'' to it.
1136    This stops it cold in its tracks and allows us to start tracing it.  */
1137
1138 static void
1139 vx_attach (args, from_tty)
1140      char *args;
1141      int from_tty;
1142 {
1143   int pid;
1144   char *cptr = 0;
1145   Rptrace ptrace_in;
1146   Ptrace_return ptrace_out;
1147   int status;
1148
1149   if (!args)
1150     error_no_arg ("process-id to attach");
1151
1152   pid = strtol (args, &cptr, 0);
1153   if ((cptr == args) || (*cptr != '\0'))
1154     error ("Invalid process-id -- give a single number in decimal or 0xhex");
1155
1156   if (from_tty)
1157       printf ("Attaching pid %s.\n", local_hex_string(pid));
1158
1159   bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
1160   bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1161   ptrace_in.pid = pid;
1162
1163   status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
1164   if (status == -1)
1165     error (rpcerr);
1166   if (ptrace_out.status == -1)
1167     {
1168       errno = ptrace_out.errno;
1169       perror_with_name ("Attaching remote process");
1170     }
1171
1172   /* It worked... */
1173   push_target (&vx_run_ops);
1174   inferior_pid = pid;
1175   vx_running = 0;
1176 }
1177
1178
1179 /* detach_command --
1180    takes a program previously attached to and detaches it.
1181    The program resumes execution and will no longer stop
1182    on signals, etc.  We better not have left any breakpoints
1183    in the program or it'll die when it hits one.  For this
1184    to work, it may be necessary for the process to have been
1185    previously attached.  It *might* work if the program was
1186    started via the normal ptrace (PTRACE_TRACEME).  */
1187
1188 static void
1189 vx_detach (args, from_tty)
1190      char *args;
1191      int from_tty;
1192 {
1193   Rptrace ptrace_in;
1194   Ptrace_return ptrace_out;
1195   int signal = 0;
1196   int status;
1197
1198   if (args)
1199     error ("Argument given to VxWorks \"detach\".");
1200
1201   if (from_tty)
1202       printf ("Detaching pid %s.\n", local_hex_string(inferior_pid));
1203
1204   if (args)             /* FIXME, should be possible to leave suspended */
1205     signal = atoi (args);
1206   
1207   bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
1208   bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1209   ptrace_in.pid = inferior_pid;
1210
1211   status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
1212   if (status == -1)
1213     error (rpcerr);
1214   if (ptrace_out.status == -1)
1215     {
1216       errno = ptrace_out.errno;
1217       perror_with_name ("Detaching VxWorks process");
1218     }
1219
1220   inferior_pid = 0;
1221   pop_target ();        /* go back to non-executing VxWorks connection */
1222 }
1223
1224 /* vx_kill -- takes a running task and wipes it out.  */
1225
1226 static void
1227 vx_kill ()
1228 {
1229   Rptrace ptrace_in;
1230   Ptrace_return ptrace_out;
1231   int status;
1232
1233   printf ("Killing pid %s.\n", local_hex_string(inferior_pid));
1234
1235   bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
1236   bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1237   ptrace_in.pid = inferior_pid;
1238
1239   status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
1240   if (status == -1)
1241     warning (rpcerr);
1242   else if (ptrace_out.status == -1)
1243     {
1244       errno = ptrace_out.errno;
1245       perror_with_name ("Killing VxWorks process");
1246     }
1247
1248   /* If it gives good status, the process is *gone*, no events remain.
1249      If the kill failed, assume the process is gone anyhow.  */
1250   inferior_pid = 0;
1251   pop_target ();        /* go back to non-executing VxWorks connection */
1252 }
1253
1254 /* Clean up from the VxWorks process target as it goes away.  */
1255
1256 static void
1257 vx_proc_close (quitting)
1258      int quitting;
1259 {
1260   inferior_pid = 0;             /* No longer have a process.  */
1261   if (vx_running)
1262     free (vx_running);
1263   vx_running = 0;
1264 }
1265 \f
1266 /* Make an RPC call to the VxWorks target.
1267    Returns RPC status.  */
1268
1269 static enum clnt_stat
1270 net_clnt_call (procNum, inProc, in, outProc, out)
1271     enum ptracereq procNum;
1272     xdrproc_t inProc;
1273     char *in;
1274     xdrproc_t outProc;
1275     char *out;
1276 {
1277   enum clnt_stat status;
1278   
1279   status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
1280
1281   if (status != RPC_SUCCESS)
1282       clnt_perrno (status);
1283
1284   return status;
1285 }
1286
1287 /* Clean up before losing control.  */
1288
1289 static void
1290 vx_close (quitting)
1291      int quitting;
1292 {
1293   if (pClient)
1294     clnt_destroy (pClient);     /* The net connection */
1295   pClient = 0;
1296
1297   if (vx_host)
1298     free (vx_host);             /* The hostname */
1299   vx_host = 0;
1300 }
1301
1302 /* A vxprocess target should be started via "run" not "target".  */
1303 /*ARGSUSED*/
1304 static void
1305 vx_proc_open (name, from_tty)
1306      char *name;
1307      int from_tty;
1308 {
1309   error ("Use the \"run\" command to start a VxWorks process.");
1310 }
1311
1312 /* Target ops structure for accessing memory and such over the net */
1313
1314 struct target_ops vx_ops = {
1315         "vxworks", "VxWorks target memory via RPC over TCP/IP",
1316         "Use VxWorks target memory.  \n\
1317 Specify the name of the machine to connect to.",
1318         vx_open, vx_close, vx_attach, 0, /* vx_detach, */
1319         0, 0, /* resume, wait */
1320         0, 0, /* read_reg, write_reg */
1321         0, /* prep_to_store, */
1322         vx_xfer_memory, vx_files_info,
1323         0, 0, /* insert_breakpoint, remove_breakpoint */
1324         0, 0, 0, 0, 0,  /* terminal stuff */
1325         0, /* vx_kill, */
1326         vx_load_command,
1327         vx_lookup_symbol,
1328         vx_create_inferior, 0,  /* mourn_inferior */
1329         0, /* can_run */
1330         0, /* notice_signals */
1331         core_stratum, 0, /* next */
1332         1, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
1333         0, 0,                   /* Section pointers */
1334         OPS_MAGIC,              /* Always the last thing */
1335 };
1336
1337 /* Target ops structure for accessing VxWorks child processes over the net */
1338
1339 struct target_ops vx_run_ops = {
1340         "vxprocess", "VxWorks process",
1341         "VxWorks process, started by the \"run\" command.",
1342         vx_proc_open, vx_proc_close, 0, vx_detach, /* vx_attach */
1343         vx_resume, vx_wait,
1344         vx_read_register, vx_write_register,
1345         vx_prepare_to_store,
1346         vx_xfer_memory, vx_run_files_info,
1347         vx_insert_breakpoint, vx_remove_breakpoint,
1348         0, 0, 0, 0, 0,  /* terminal stuff */
1349         vx_kill,
1350         vx_load_command,
1351         vx_lookup_symbol,
1352         0, vx_mourn_inferior,
1353         0,  /* can_run */
1354         0, /* notice_signals */
1355         process_stratum, 0, /* next */
1356         0, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
1357                         /* all_mem is off to avoid spurious msg in "i files" */
1358         0, 0,                   /* Section pointers */
1359         OPS_MAGIC,              /* Always the last thing */
1360 };
1361 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
1362 \f
1363 void
1364 _initialize_vx ()
1365 {
1366   add_target (&vx_ops);
1367   add_target (&vx_run_ops);
1368 }
This page took 0.103359 seconds and 4 git commands to generate.