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