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