OSDN Git Service

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