import gdb-1999-10-11 snapshot
[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 "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 PARAMS ((char *, int, CORE_ADDR, CORE_ADDR,
655                                     CORE_ADDR));
656
657 struct find_sect_args
658   {
659     CORE_ADDR text_start;
660     CORE_ADDR data_start;
661     CORE_ADDR bss_start;
662   };
663
664 static void find_sect PARAMS ((bfd *, asection *, void *));
665
666 static void
667 find_sect (abfd, sect, obj)
668      bfd *abfd;
669      asection *sect;
670      PTR obj;
671 {
672   struct find_sect_args *args = (struct find_sect_args *) obj;
673
674   if (bfd_get_section_flags (abfd, sect) & (SEC_CODE & SEC_READONLY))
675     args->text_start = bfd_get_section_vma (abfd, sect);
676   else if (bfd_get_section_flags (abfd, sect) & SEC_ALLOC)
677     {
678       if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
679         {
680           /* Exclude .ctor and .dtor sections which have SEC_CODE set but not
681              SEC_DATA.  */
682           if (bfd_get_section_flags (abfd, sect) & SEC_DATA)
683             args->data_start = bfd_get_section_vma (abfd, sect);
684         }
685       else
686         args->bss_start = bfd_get_section_vma (abfd, sect);
687     }
688 }
689
690 static void
691 vx_add_symbols (name, from_tty, text_addr, data_addr, bss_addr)
692      char *name;
693      int from_tty;
694      CORE_ADDR text_addr;
695      CORE_ADDR data_addr;
696      CORE_ADDR bss_addr;
697 {
698   struct section_offsets *offs;
699   struct objfile *objfile;
700   struct find_sect_args ss;
701
702   /* It might be nice to suppress the breakpoint_re_set which happens here
703      because we are going to do one again after the objfile_relocate.  */
704   objfile = symbol_file_add (name, from_tty, NULL, 0, 0);
705
706   /* This is a (slightly cheesy) way of superceding the old symbols.  A less
707      cheesy way would be to find the objfile with the same name and
708      free_objfile it.  */
709   objfile_to_front (objfile);
710
711   offs = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
712   memcpy (offs, objfile->section_offsets, SIZEOF_SECTION_OFFSETS);
713
714   ss.text_start = 0;
715   ss.data_start = 0;
716   ss.bss_start = 0;
717   bfd_map_over_sections (objfile->obfd, find_sect, &ss);
718
719   /* Both COFF and b.out frontends use these SECT_OFF_* values.  */
720   ANOFFSET (offs, SECT_OFF_TEXT) = text_addr - ss.text_start;
721   ANOFFSET (offs, SECT_OFF_DATA) = data_addr - ss.data_start;
722   ANOFFSET (offs, SECT_OFF_BSS) = bss_addr - ss.bss_start;
723   objfile_relocate (objfile, offs);
724 }
725
726 /* This function allows the addition of incrementally linked object files.  */
727
728 static void
729 vx_load_command (arg_string, from_tty)
730      char *arg_string;
731      int from_tty;
732 {
733   CORE_ADDR text_addr;
734   CORE_ADDR data_addr;
735   CORE_ADDR bss_addr;
736
737   if (arg_string == 0)
738     error ("The load command takes a file name");
739
740   arg_string = tilde_expand (arg_string);
741   make_cleanup (free, arg_string);
742
743   dont_repeat ();
744
745   /* Refuse to load the module if a debugged task is running.  Doing so
746      can have a number of unpleasant consequences to the running task.  */
747
748   if (inferior_pid != 0 && target_has_execution)
749     {
750       if (query ("You may not load a module while the target task is running.\n\
751 Kill the target task? "))
752         target_kill ();
753       else
754         error ("Load cancelled.");
755     }
756
757   QUIT;
758   immediate_quit++;
759   if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
760     error ("Load failed on target machine");
761   immediate_quit--;
762
763   vx_add_symbols (arg_string, from_tty, text_addr, data_addr, bss_addr);
764
765   /* Getting new symbols may change our opinion about what is
766      frameless.  */
767   reinit_frame_cache ();
768 }
769
770 /* Single step the target program at the source or machine level.
771    Takes an error exit if rpc fails.
772    Returns -1 if remote single-step operation fails, else 0.  */
773
774 static int
775 net_step ()
776 {
777   enum clnt_stat status;
778   int step_status;
779   SOURCE_STEP source_step;
780
781   source_step.taskId = inferior_pid;
782
783   if (step_range_end)
784     {
785       source_step.startAddr = step_range_start;
786       source_step.endAddr = step_range_end;
787     }
788   else
789     {
790       source_step.startAddr = 0;
791       source_step.endAddr = 0;
792     }
793
794   status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
795                           xdr_int, &step_status);
796
797   if (status == RPC_SUCCESS)
798     return step_status;
799   else
800     error (rpcerr);
801 }
802
803 /* Emulate ptrace using RPC calls to the VxWorks target system.
804    Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise.  */
805
806 static int
807 net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
808      enum ptracereq request;
809      Rptrace *pPtraceIn;
810      Ptrace_return *pPtraceOut;
811 {
812   enum clnt_stat status;
813
814   status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
815                           pPtraceOut);
816
817   if (status != RPC_SUCCESS)
818     return -1;
819
820   return 0;
821 }
822
823 /* Query the target for the name of the file from which VxWorks was
824    booted.  pBootFile is the address of a pointer to the buffer to
825    receive the file name; if the pointer pointed to by pBootFile is 
826    NULL, memory for the buffer will be allocated by XDR.
827    Returns -1 if rpc failed, 0 otherwise.  */
828
829 static int
830 net_get_boot_file (pBootFile)
831      char **pBootFile;
832 {
833   enum clnt_stat status;
834
835   status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
836                           xdr_wrapstring, pBootFile);
837   return (status == RPC_SUCCESS) ? 0 : -1;
838 }
839
840 /* Fetch a list of loaded object modules from the VxWorks target.
841    Returns -1 if rpc failed, 0 otherwise
842    There's no way to check if the returned loadTable is correct.
843    VxWorks doesn't check it.  */
844
845 static int
846 net_get_symbols (pLoadTable)
847      ldtabl *pLoadTable;        /* return pointer to ldtabl here */
848 {
849   enum clnt_stat status;
850
851   memset ((char *) pLoadTable, '\0', sizeof (struct ldtabl));
852
853   status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
854   return (status == RPC_SUCCESS) ? 0 : -1;
855 }
856
857 /* Look up a symbol in the VxWorks target's symbol table.
858    Returns status of symbol read on target side (0=success, -1=fail)
859    Returns -1 and complain()s if rpc fails.  */
860
861 struct complaint cant_contact_target =
862 {"Lost contact with VxWorks target", 0, 0};
863
864 static int
865 vx_lookup_symbol (name, pAddr)
866      char *name;                /* symbol name */
867      CORE_ADDR *pAddr;
868 {
869   enum clnt_stat status;
870   SYMBOL_ADDR symbolAddr;
871
872   *pAddr = 0;
873   memset ((char *) &symbolAddr, '\0', sizeof (symbolAddr));
874
875   status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
876                           xdr_SYMBOL_ADDR, &symbolAddr);
877   if (status != RPC_SUCCESS)
878     {
879       complain (&cant_contact_target);
880       return -1;
881     }
882
883   *pAddr = symbolAddr.addr;
884   return symbolAddr.status;
885 }
886
887 /* Check to see if the VxWorks target has a floating point coprocessor.
888    Returns 1 if target has floating point processor, 0 otherwise.
889    Calls error() if rpc fails.  */
890
891 static int
892 net_check_for_fp ()
893 {
894   enum clnt_stat status;
895   bool_t fp = 0;                /* true if fp processor is present on target board */
896
897   status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
898   if (status != RPC_SUCCESS)
899     error (rpcerr);
900
901   return (int) fp;
902 }
903
904 /* Establish an RPC connection with the VxWorks target system.
905    Calls error () if unable to establish connection.  */
906
907 static void
908 net_connect (host)
909      char *host;
910 {
911   struct sockaddr_in destAddr;
912   struct hostent *destHost;
913   unsigned long addr;
914
915   /* Get the internet address for the given host.  Allow a numeric
916      IP address or a hostname.  */
917
918   addr = inet_addr (host);
919   if (addr == -1)
920     {
921       destHost = (struct hostent *) gethostbyname (host);
922       if (destHost == NULL)
923         /* FIXME: Probably should include hostname here in quotes.
924            For example if the user types "target vxworks vx960 " it should
925            say "Invalid host `vx960 '." not just "Invalid hostname".  */
926         error ("Invalid hostname.  Couldn't find remote host address.");
927       addr = *(unsigned long *) destHost->h_addr;
928     }
929
930   memset (&destAddr, '\0', sizeof (destAddr));
931
932   destAddr.sin_addr.s_addr = addr;
933   destAddr.sin_family = AF_INET;
934   destAddr.sin_port = 0;        /* set to actual port that remote
935                                    ptrace is listening on.  */
936
937   /* Create a tcp client transport on which to issue
938      calls to the remote ptrace server.  */
939
940   ptraceSock = RPC_ANYSOCK;
941   pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
942   /* FIXME, here is where we deal with different version numbers of the
943      proto */
944
945   if (pClient == NULL)
946     {
947       clnt_pcreateerror ("\tnet_connect");
948       error ("Couldn't connect to remote target.");
949     }
950 }
951 \f
952 /* Sleep for the specified number of milliseconds 
953  * (assumed to be less than 1000).
954  * If select () is interrupted, returns immediately;
955  * takes an error exit if select () fails for some other reason.
956  */
957
958 static void
959 sleep_ms (ms)
960      long ms;
961 {
962   struct timeval select_timeout;
963   int status;
964
965   select_timeout.tv_sec = 0;
966   select_timeout.tv_usec = ms * 1000;
967
968   status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0,
969                    &select_timeout);
970
971   if (status < 0 && errno != EINTR)
972     perror_with_name ("select");
973 }
974
975 static int
976 vx_wait (pid_to_wait_for, status)
977      int pid_to_wait_for;
978      struct target_waitstatus *status;
979 {
980   register int pid;
981   RDB_EVENT rdbEvent;
982   int quit_failed;
983
984   do
985     {
986       /* If CTRL-C is hit during this loop,
987          suspend the inferior process.  */
988
989       quit_failed = 0;
990       if (quit_flag)
991         {
992           quit_failed = (net_quit () == -1);
993           quit_flag = 0;
994         }
995
996       /* If a net_quit () or net_wait () call has failed,
997          allow the user to break the connection with the target.
998          We can't simply error () out of this loop, since the 
999          data structures representing the state of the inferior
1000          are in an inconsistent state.  */
1001
1002       if (quit_failed || net_wait (&rdbEvent) == -1)
1003         {
1004           terminal_ours ();
1005           if (query ("Can't %s.  Disconnect from target system? ",
1006                      (quit_failed) ? "suspend remote task"
1007                      : "get status of remote task"))
1008             {
1009               target_mourn_inferior ();
1010               error ("Use the \"target\" command to reconnect.");
1011             }
1012           else
1013             {
1014               terminal_inferior ();
1015               continue;
1016             }
1017         }
1018
1019       pid = rdbEvent.taskId;
1020       if (pid == 0)
1021         {
1022           sleep_ms (200);       /* FIXME Don't kill the network too badly */
1023         }
1024       else if (pid != inferior_pid)
1025         internal_error ("Bad pid for debugged task: %s\n",
1026                         local_hex_string ((unsigned long) pid));
1027     }
1028   while (pid == 0);
1029
1030   /* The mostly likely kind.  */
1031   status->kind = TARGET_WAITKIND_STOPPED;
1032
1033   switch (rdbEvent.eventType)
1034     {
1035     case EVENT_EXIT:
1036       status->kind = TARGET_WAITKIND_EXITED;
1037       /* FIXME is it possible to distinguish between a
1038          normal vs abnormal exit in VxWorks? */
1039       status->value.integer = 0;
1040       break;
1041
1042     case EVENT_START:
1043       /* Task was just started. */
1044       status->value.sig = TARGET_SIGNAL_TRAP;
1045       break;
1046
1047     case EVENT_STOP:
1048       status->value.sig = TARGET_SIGNAL_TRAP;
1049       /* XXX was it stopped by a signal?  act accordingly */
1050       break;
1051
1052     case EVENT_BREAK:           /* Breakpoint was hit. */
1053       status->value.sig = TARGET_SIGNAL_TRAP;
1054       break;
1055
1056     case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */
1057       status->value.sig = TARGET_SIGNAL_INT;
1058       break;
1059
1060     case EVENT_BUS_ERR: /* Task made evil nasty reference. */
1061       status->value.sig = TARGET_SIGNAL_BUS;
1062       break;
1063
1064     case EVENT_ZERO_DIV:        /* Division by zero */
1065       status->value.sig = TARGET_SIGNAL_FPE;
1066       break;
1067
1068     case EVENT_SIGNAL:
1069 #ifdef I80960
1070       status->value.sig = i960_fault_to_signal (rdbEvent.sigType);
1071 #else
1072       /* Back in the old days, before enum target_signal, this code used
1073          to add NSIG to the signal number and claim that PRINT_RANDOM_SIGNAL
1074          would take care of it.  But PRINT_RANDOM_SIGNAL has never been
1075          defined except on the i960, so I don't really know what we are
1076          supposed to do on other architectures.  */
1077       status->value.sig = TARGET_SIGNAL_UNKNOWN;
1078 #endif
1079       break;
1080     }                           /* switch */
1081   return pid;
1082 }
1083 \f
1084 static int
1085 symbol_stub (arg)
1086      char *arg;
1087 {
1088   symbol_file_command (arg, 0);
1089   return 1;
1090 }
1091
1092 static int
1093 add_symbol_stub (arg)
1094      char *arg;
1095 {
1096   struct ldfile *pLoadFile = (struct ldfile *) arg;
1097
1098   printf_unfiltered ("\t%s: ", pLoadFile->name);
1099   vx_add_symbols (pLoadFile->name, 0, pLoadFile->txt_addr,
1100                   pLoadFile->data_addr, pLoadFile->bss_addr);
1101   printf_unfiltered ("ok\n");
1102   return 1;
1103 }
1104 /* Target command for VxWorks target systems.
1105
1106    Used in vxgdb.  Takes the name of a remote target machine
1107    running vxWorks and connects to it to initialize remote network
1108    debugging.  */
1109
1110 static void
1111 vx_open (args, from_tty)
1112      char *args;
1113      int from_tty;
1114 {
1115   extern int close ();
1116   char *bootFile;
1117   extern char *source_path;
1118   struct ldtabl loadTable;
1119   struct ldfile *pLoadFile;
1120   int i;
1121   extern CLIENT *pClient;
1122   int symbols_added = 0;
1123
1124   if (!args)
1125     error_no_arg ("target machine name");
1126
1127   target_preopen (from_tty);
1128
1129   unpush_target (&vx_ops);
1130   printf_unfiltered ("Attaching remote machine across net...\n");
1131   gdb_flush (gdb_stdout);
1132
1133   /* Allow the user to kill the connect attempt by typing ^C.
1134      Wait until the call to target_has_fp () completes before
1135      disallowing an immediate quit, since even if net_connect ()
1136      is successful, the remote debug server might be hung.  */
1137
1138   immediate_quit++;
1139
1140   net_connect (args);
1141   target_has_fp = net_check_for_fp ();
1142   printf_filtered ("Connected to %s.\n", args);
1143
1144   immediate_quit--;
1145
1146   push_target (&vx_ops);
1147
1148   /* Save a copy of the target host's name.  */
1149   vx_host = savestring (args, strlen (args));
1150
1151   /* Find out the name of the file from which the target was booted
1152      and load its symbol table.  */
1153
1154   printf_filtered ("Looking in Unix path for all loaded modules:\n");
1155   bootFile = NULL;
1156   if (!net_get_boot_file (&bootFile))
1157     {
1158       if (*bootFile)
1159         {
1160           printf_filtered ("\t%s: ", bootFile);
1161           /* This assumes that the kernel is never relocated.  Hope that is an
1162              accurate assumption.  */
1163           if (catch_errors
1164               (symbol_stub,
1165                bootFile,
1166                "Error while reading symbols from boot file:\n",
1167                RETURN_MASK_ALL))
1168             puts_filtered ("ok\n");
1169         }
1170       else if (from_tty)
1171         printf_unfiltered ("VxWorks kernel symbols not loaded.\n");
1172     }
1173   else
1174     error ("Can't retrieve boot file name from target machine.");
1175
1176   clnt_freeres (pClient, xdr_wrapstring, &bootFile);
1177
1178   if (net_get_symbols (&loadTable) != 0)
1179     error ("Can't read loaded modules from target machine");
1180
1181   i = 0 - 1;
1182   while (++i < loadTable.tbl_size)
1183     {
1184       QUIT;                     /* FIXME, avoids clnt_freeres below:  mem leak */
1185       pLoadFile = &loadTable.tbl_ent[i];
1186 #ifdef WRS_ORIG
1187       {
1188         register int desc;
1189         struct cleanup *old_chain;
1190         char *fullname = NULL;
1191
1192         desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
1193         if (desc < 0)
1194           perror_with_name (pLoadFile->name);
1195         old_chain = make_cleanup (close, desc);
1196         add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
1197                           pLoadFile->bss_addr);
1198         do_cleanups (old_chain);
1199       }
1200 #else
1201       /* FIXME: Is there something better to search than the PATH? (probably
1202          not the source path, since source might be in different directories
1203          than objects.  */
1204
1205       if (catch_errors (add_symbol_stub, (char *) pLoadFile, (char *) 0,
1206                         RETURN_MASK_ALL))
1207         symbols_added = 1;
1208 #endif
1209     }
1210   printf_filtered ("Done.\n");
1211
1212   clnt_freeres (pClient, xdr_ldtabl, &loadTable);
1213
1214   /* Getting new symbols may change our opinion about what is
1215      frameless.  */
1216   if (symbols_added)
1217     reinit_frame_cache ();
1218 }
1219 \f
1220 /* Takes a task started up outside of gdb and ``attaches'' to it.
1221    This stops it cold in its tracks and allows us to start tracing it.  */
1222
1223 static void
1224 vx_attach (args, from_tty)
1225      char *args;
1226      int from_tty;
1227 {
1228   unsigned long pid;
1229   char *cptr = 0;
1230   Rptrace ptrace_in;
1231   Ptrace_return ptrace_out;
1232   int status;
1233
1234   if (!args)
1235     error_no_arg ("process-id to attach");
1236
1237   pid = strtoul (args, &cptr, 0);
1238   if ((cptr == args) || (*cptr != '\0'))
1239     error ("Invalid process-id -- give a single number in decimal or 0xhex");
1240
1241   if (from_tty)
1242     printf_unfiltered ("Attaching pid %s.\n",
1243                        local_hex_string ((unsigned long) pid));
1244
1245   memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
1246   memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
1247   ptrace_in.pid = pid;
1248
1249   status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
1250   if (status == -1)
1251     error (rpcerr);
1252   if (ptrace_out.status == -1)
1253     {
1254       errno = ptrace_out.errno_num;
1255       perror_with_name ("Attaching remote process");
1256     }
1257
1258   /* It worked... */
1259
1260   inferior_pid = pid;
1261   push_target (&vx_run_ops);
1262
1263   if (vx_running)
1264     free (vx_running);
1265   vx_running = 0;
1266 }
1267
1268 /* detach_command --
1269    takes a program previously attached to and detaches it.
1270    The program resumes execution and will no longer stop
1271    on signals, etc.  We better not have left any breakpoints
1272    in the program or it'll die when it hits one.  For this
1273    to work, it may be necessary for the process to have been
1274    previously attached.  It *might* work if the program was
1275    started via the normal ptrace (PTRACE_TRACEME).  */
1276
1277 static void
1278 vx_detach (args, from_tty)
1279      char *args;
1280      int from_tty;
1281 {
1282   Rptrace ptrace_in;
1283   Ptrace_return ptrace_out;
1284   int signal = 0;
1285   int status;
1286
1287   if (args)
1288     error ("Argument given to VxWorks \"detach\".");
1289
1290   if (from_tty)
1291     printf_unfiltered ("Detaching pid %s.\n",
1292                        local_hex_string ((unsigned long) inferior_pid));
1293
1294   if (args)                     /* FIXME, should be possible to leave suspended */
1295     signal = atoi (args);
1296
1297   memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
1298   memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
1299   ptrace_in.pid = inferior_pid;
1300
1301   status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
1302   if (status == -1)
1303     error (rpcerr);
1304   if (ptrace_out.status == -1)
1305     {
1306       errno = ptrace_out.errno_num;
1307       perror_with_name ("Detaching VxWorks process");
1308     }
1309
1310   inferior_pid = 0;
1311   pop_target ();                /* go back to non-executing VxWorks connection */
1312 }
1313
1314 /* vx_kill -- takes a running task and wipes it out.  */
1315
1316 static void
1317 vx_kill ()
1318 {
1319   Rptrace ptrace_in;
1320   Ptrace_return ptrace_out;
1321   int status;
1322
1323   printf_unfiltered ("Killing pid %s.\n", local_hex_string ((unsigned long) inferior_pid));
1324
1325   memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
1326   memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
1327   ptrace_in.pid = inferior_pid;
1328
1329   status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
1330   if (status == -1)
1331     warning (rpcerr);
1332   else if (ptrace_out.status == -1)
1333     {
1334       errno = ptrace_out.errno_num;
1335       perror_with_name ("Killing VxWorks process");
1336     }
1337
1338   /* If it gives good status, the process is *gone*, no events remain.
1339      If the kill failed, assume the process is gone anyhow.  */
1340   inferior_pid = 0;
1341   pop_target ();                /* go back to non-executing VxWorks connection */
1342 }
1343
1344 /* Clean up from the VxWorks process target as it goes away.  */
1345
1346 static void
1347 vx_proc_close (quitting)
1348      int quitting;
1349 {
1350   inferior_pid = 0;             /* No longer have a process.  */
1351   if (vx_running)
1352     free (vx_running);
1353   vx_running = 0;
1354 }
1355 \f
1356 /* Make an RPC call to the VxWorks target.
1357    Returns RPC status.  */
1358
1359 static enum clnt_stat
1360 net_clnt_call (procNum, inProc, in, outProc, out)
1361      enum ptracereq procNum;
1362      xdrproc_t inProc;
1363      char *in;
1364      xdrproc_t outProc;
1365      char *out;
1366 {
1367   enum clnt_stat status;
1368
1369   status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
1370
1371   if (status != RPC_SUCCESS)
1372     clnt_perrno (status);
1373
1374   return status;
1375 }
1376
1377 /* Clean up before losing control.  */
1378
1379 static void
1380 vx_close (quitting)
1381      int quitting;
1382 {
1383   if (pClient)
1384     clnt_destroy (pClient);     /* The net connection */
1385   pClient = 0;
1386
1387   if (vx_host)
1388     free (vx_host);             /* The hostname */
1389   vx_host = 0;
1390 }
1391
1392 /* A vxprocess target should be started via "run" not "target".  */
1393 /*ARGSUSED */
1394 static void
1395 vx_proc_open (name, from_tty)
1396      char *name;
1397      int from_tty;
1398 {
1399   error ("Use the \"run\" command to start a VxWorks process.");
1400 }
1401
1402 static void
1403 init_vx_ops ()
1404 {
1405   vx_ops.to_shortname = "vxworks";
1406   vx_ops.to_longname = "VxWorks target memory via RPC over TCP/IP";
1407   vx_ops.to_doc = "Use VxWorks target memory.  \n\
1408 Specify the name of the machine to connect to.";
1409   vx_ops.to_open = vx_open;
1410   vx_ops.to_close = vx_close;
1411   vx_ops.to_attach = vx_attach;
1412   vx_ops.to_xfer_memory = vx_xfer_memory;
1413   vx_ops.to_files_info = vx_files_info;
1414   vx_ops.to_load = vx_load_command;
1415   vx_ops.to_lookup_symbol = vx_lookup_symbol;
1416   vx_ops.to_create_inferior = vx_create_inferior;
1417   vx_ops.to_stratum = core_stratum;
1418   vx_ops.to_has_all_memory = 1;
1419   vx_ops.to_has_memory = 1;
1420   vx_ops.to_magic = OPS_MAGIC;  /* Always the last thing */
1421 };
1422
1423 static void
1424 init_vx_run_ops ()
1425 {
1426   vx_run_ops.to_shortname = "vxprocess";
1427   vx_run_ops.to_longname = "VxWorks process";
1428   vx_run_ops.to_doc = "VxWorks process; started by the \"run\" command.";
1429   vx_run_ops.to_open = vx_proc_open;
1430   vx_run_ops.to_close = vx_proc_close;
1431   vx_run_ops.to_detach = vx_detach;
1432   vx_run_ops.to_resume = vx_resume;
1433   vx_run_ops.to_wait = vx_wait;
1434   vx_run_ops.to_fetch_registers = vx_read_register;
1435   vx_run_ops.to_store_registers = vx_write_register;
1436   vx_run_ops.to_prepare_to_store = vx_prepare_to_store;
1437   vx_run_ops.to_xfer_memory = vx_xfer_memory;
1438   vx_run_ops.to_files_info = vx_run_files_info;
1439   vx_run_ops.to_insert_breakpoint = vx_insert_breakpoint;
1440   vx_run_ops.to_remove_breakpoint = vx_remove_breakpoint;
1441   vx_run_ops.to_kill = vx_kill;
1442   vx_run_ops.to_load = vx_load_command;
1443   vx_run_ops.to_lookup_symbol = vx_lookup_symbol;
1444   vx_run_ops.to_mourn_inferior = vx_mourn_inferior;
1445   vx_run_ops.to_stratum = process_stratum;
1446   vx_run_ops.to_has_memory = 1;
1447   vx_run_ops.to_has_stack = 1;
1448   vx_run_ops.to_has_registers = 1;
1449   vx_run_ops.to_has_execution = 1;
1450   vx_run_ops.to_magic = OPS_MAGIC;
1451 }
1452 \f
1453 void
1454 _initialize_vx ()
1455 {
1456   init_vx_ops ();
1457   add_target (&vx_ops);
1458   init_vx_run_ops ();
1459   add_target (&vx_run_ops);
1460
1461   add_show_from_set
1462     (add_set_cmd ("vxworks-timeout", class_support, var_uinteger,
1463                   (char *) &rpcTimeout.tv_sec,
1464                   "Set seconds to wait for rpc calls to return.\n\
1465 Set the number of seconds to wait for rpc calls to return.", &setlist),
1466      &showlist);
1467 }