]> Git Repo - binutils.git/blob - gdb/remote-vx.c
This commit was generated by cvs2svn to track changes on a CVS vendor
[binutils.git] / gdb / remote-vx.c
1 /* Memory-access and commands for remote VxWorks processes, for GDB.
2    Copyright (C) 1990-1991  Free Software Foundation, Inc.
3    Contributed by Wind River Systems and Cygnus Support.
4
5 This file is part of GDB.
6
7 GDB 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 1, or (at your option)
10 any later version.
11
12 GDB 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 GDB; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "defs.h"
22 #include "param.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 "symfile.h"            /* for struct complaint */
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <signal.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/time.h>
39 #include <sys/socket.h>
40 #define free bogon_free         /* Sun claims "int free()" not void */
41 #include <rpc/rpc.h>
42 #undef free
43 #include <sys/time.h>           /* UTek's <rpc/rpc.h> doesn't #incl this */
44 #include <netdb.h>
45 #include <ptrace.h>
46 #include "xdr_ptrace.h"
47 #include "xdr_ld.h"
48 #include "xdr_rdb.h"
49 #include "dbgRpcLib.h"
50
51 /* get rid of value.h if possible */
52 #include <value.h>
53 #include <symtab.h>
54  
55 extern value call_function_by_hand ();
56 extern void symbol_file_command ();
57 extern void add_syms_addr_command ();
58 extern int stop_soon_quietly;           /* for wait_for_inferior */
59
60 static int net_ptrace_clnt_call ();     /* Forward decl */
61 static enum clnt_stat net_clnt_call (); /* Forward decl */
62 extern struct target_ops vx_ops, vx_run_ops;    /* Forward declaration */
63
64 /* Saved name of target host and called function for "info files".
65    Both malloc'd.  */
66
67 static char *vx_host;
68 static char *vx_running;                /* Called function */
69
70 /* Nonzero means target that is being debugged remotely has a floating
71    point processor.  */
72
73 static int target_has_fp;
74
75 /* Default error message when the network is forking up.  */
76
77 static const char rpcerr[] = "network target debugging:  rpc error";
78
79 CLIENT *pClient;         /* client used in net debugging */
80 static int ptraceSock = RPC_ANYSOCK;
81
82 enum clnt_stat net_clnt_call();
83 static void parse_args ();
84
85 static struct timeval rpcTimeout = { 10, 0 };
86
87 static char *skip_white_space ();
88 static char *find_white_space ();
89  
90 /* Tell the VxWorks target system to download a file.
91    The load addresses of the text, data, and bss segments are
92    stored in pTextAddr, pDataAddr, and *pBssAddr (respectively).
93    Returns 0 for success, -1 for failure.  */
94
95 static int
96 net_load (filename, pTextAddr, pDataAddr, pBssAddr)
97     char *filename;
98     CORE_ADDR *pTextAddr;
99     CORE_ADDR *pDataAddr;
100     CORE_ADDR *pBssAddr;
101     {
102     enum clnt_stat status;
103     struct ldfile ldstruct;
104     struct timeval load_timeout;
105  
106     bzero ((char *) &ldstruct, sizeof (ldstruct));
107
108     /* We invoke clnt_call () here directly, instead of through
109        net_clnt_call (), because we need to set a large timeout value.
110        The load on the target side can take quite a while, easily
111        more than 10 seconds.  The user can kill this call by typing
112        CTRL-C if there really is a problem with the load.  
113        
114        Do not change the tv_sec value without checking -- select() imposes
115        a limit of 10**8 on it for no good reason that I can see...  */
116
117     load_timeout.tv_sec = 99999999;   /* A large number, effectively inf. */
118     load_timeout.tv_usec = 0;
119  
120     status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
121                         &ldstruct, load_timeout);
122
123     if (status == RPC_SUCCESS)
124       {
125         if (*ldstruct.name == NULL)     /* load failed on VxWorks side */
126           return -1;
127         *pTextAddr = ldstruct.txt_addr;
128         *pDataAddr = ldstruct.data_addr;
129         *pBssAddr = ldstruct.bss_addr;
130         return 0;
131       }
132     else
133         return -1;
134     }
135       
136 /* returns 0 if successful, errno if RPC failed or VxWorks complains. */
137
138 static int
139 net_break (addr, procnum)
140     int addr;
141     u_long procnum;
142     {
143     enum clnt_stat status;
144     int break_status;
145     Rptrace ptrace_in;  /* XXX This is stupid.  It doesn't need to be a ptrace
146                            structure.  How about something smaller? */
147
148     bzero ((char *) &ptrace_in, sizeof (ptrace_in));
149     break_status = 0;
150
151     ptrace_in.addr = addr;
152     ptrace_in.pid = inferior_pid;
153
154     status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
155                             &break_status);
156
157     if (status != RPC_SUCCESS)
158         return errno;
159
160     if (break_status == -1)
161       return ENOMEM;
162     return break_status;        /* probably (FIXME) zero */
163     }
164  
165 /* returns 0 if successful, errno otherwise */
166
167 int
168 vx_insert_breakpoint (addr)
169     int addr;
170     {
171     return net_break (addr, VX_BREAK_ADD);
172     }
173
174 /* returns 0 if successful, errno otherwise */
175
176 int
177 vx_remove_breakpoint (addr)
178     int addr;
179     {
180     return net_break (addr, VX_BREAK_DELETE);
181     }
182
183 /* Call a function on the VxWorks target system.
184    ARGS is a vector of values of arguments (NARGS of them).
185    FUNCTION is a value, the function to be called.
186    Returns a struct value * representing what the function returned.
187    May fail to return, if a breakpoint or signal is hit
188    during the execution of the function.  */
189
190 #ifdef FIXME
191 /* FIXME, function calls are really fried.  GO back to manual method. */
192 value
193 vx_call_function (function, nargs, args)
194      value function;
195      int nargs;
196      value *args;
197 {
198   register CORE_ADDR sp;
199   register int i;
200   CORE_ADDR start_sp;
201   static REGISTER_TYPE dummy[] = CALL_DUMMY;
202   REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
203   CORE_ADDR old_sp;
204   struct type *value_type;
205   unsigned char struct_return;
206   CORE_ADDR struct_addr;
207   struct inferior_status inf_status;
208   struct cleanup *old_chain;
209   CORE_ADDR funaddr;
210   int using_gcc;
211
212   save_inferior_status (&inf_status, 1);
213   old_chain = make_cleanup (restore_inferior_status, &inf_status);
214
215   /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
216      (and POP_FRAME for restoring them).  (At least on most machines)
217      they are saved on the stack in the inferior.  */
218   PUSH_DUMMY_FRAME;
219
220   old_sp = sp = read_register (SP_REGNUM);
221
222 #if 1 INNER_THAN 2              /* Stack grows down */
223   sp -= sizeof dummy;
224   start_sp = sp;
225 #else                           /* Stack grows up */
226   start_sp = sp;
227   sp += sizeof dummy;
228 #endif
229
230   funaddr = find_function_addr (function, &value_type);
231
232   {
233     struct block *b = block_for_pc (funaddr);
234     /* If compiled without -g, assume GCC.  */
235     using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
236   }
237
238   /* Are we returning a value using a structure return or a normal
239      value return? */
240
241   struct_return = using_struct_return (function, funaddr, value_type,
242                                        using_gcc);
243
244   /* Create a call sequence customized for this function
245      and the number of arguments for it.  */
246   bcopy (dummy, dummy1, sizeof dummy);
247   FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
248                   value_type, using_gcc);
249
250 #if CALL_DUMMY_LOCATION == ON_STACK
251   write_memory (start_sp, dummy1, sizeof dummy);
252
253 #else /* Not on stack.  */
254 #if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
255   /* Convex Unix prohibits executing in the stack segment. */
256   /* Hope there is empty room at the top of the text segment. */
257   {
258     static checked = 0;
259     if (!checked)
260       for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
261         if (read_memory_integer (start_sp, 1) != 0)
262           error ("text segment full -- no place to put call");
263     checked = 1;
264     sp = old_sp;
265     start_sp = text_end - sizeof dummy;
266     write_memory (start_sp, dummy1, sizeof dummy);
267   }
268 #else /* After text_end.  */
269   {
270     int errcode;
271     sp = old_sp;
272     start_sp = text_end;
273     errcode = target_write_memory (start_sp, dummy1, sizeof dummy);
274     if (errcode != 0)
275       error ("Cannot write text segment -- call_function failed");
276   }
277 #endif /* After text_end.  */
278 #endif /* Not on stack.  */
279
280 #ifdef STACK_ALIGN
281   /* If stack grows down, we must leave a hole at the top. */
282   {
283     int len = 0;
284
285     /* Reserve space for the return structure to be written on the
286        stack, if necessary */
287
288     if (struct_return)
289       len += TYPE_LENGTH (value_type);
290     
291     for (i = nargs - 1; i >= 0; i--)
292       len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
293 #ifdef CALL_DUMMY_STACK_ADJUST
294     len += CALL_DUMMY_STACK_ADJUST;
295 #endif
296 #if 1 INNER_THAN 2
297     sp -= STACK_ALIGN (len) - len;
298 #else
299     sp += STACK_ALIGN (len) - len;
300 #endif
301   }
302 #endif /* STACK_ALIGN */
303
304     /* Reserve space for the return structure to be written on the
305        stack, if necessary */
306
307     if (struct_return)
308       {
309 #if 1 INNER_THAN 2
310         sp -= TYPE_LENGTH (value_type);
311         struct_addr = sp;
312 #else
313         struct_addr = sp;
314         sp += TYPE_LENGTH (value_type);
315 #endif
316       }
317
318 #if defined (REG_STRUCT_HAS_ADDR)
319   {
320     /* This is a machine like the sparc, where we need to pass a pointer
321        to the structure, not the structure itself.  */
322     if (REG_STRUCT_HAS_ADDR (using_gcc))
323       for (i = nargs - 1; i >= 0; i--)
324         if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
325           {
326             CORE_ADDR addr;
327 #if !(1 INNER_THAN 2)
328             /* The stack grows up, so the address of the thing we push
329                is the stack pointer before we push it.  */
330             addr = sp;
331 #endif
332             /* Push the structure.  */
333             sp = value_push (sp, args[i]);
334 #if 1 INNER_THAN 2
335             /* The stack grows down, so the address of the thing we push
336                is the stack pointer after we push it.  */
337             addr = sp;
338 #endif
339             /* The value we're going to pass is the address of the thing
340                we just pushed.  */
341             args[i] = value_from_long (builtin_type_long, (LONGEST) addr);
342           }
343   }
344 #endif /* REG_STRUCT_HAS_ADDR.  */
345
346 #ifdef PUSH_ARGUMENTS
347   PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
348 #else /* !PUSH_ARGUMENTS */
349   for (i = nargs - 1; i >= 0; i--)
350     sp = value_arg_push (sp, args[i]);
351 #endif /* !PUSH_ARGUMENTS */
352
353 #ifdef CALL_DUMMY_STACK_ADJUST
354 #if 1 INNER_THAN 2
355   sp -= CALL_DUMMY_STACK_ADJUST;
356 #else
357   sp += CALL_DUMMY_STACK_ADJUST;
358 #endif
359 #endif /* CALL_DUMMY_STACK_ADJUST */
360
361   /* Store the address at which the structure is supposed to be
362      written.  Note that this (and the code which reserved the space
363      above) assumes that gcc was used to compile this function.  Since
364      it doesn't cost us anything but space and if the function is pcc
365      it will ignore this value, we will make that assumption.
366
367      Also note that on some machines (like the sparc) pcc uses a 
368      convention like gcc's.  */
369
370   if (struct_return)
371     STORE_STRUCT_RETURN (struct_addr, sp);
372
373   /* Write the stack pointer.  This is here because the statements above
374      might fool with it.  On SPARC, this write also stores the register
375      window into the right place in the new stack frame, which otherwise
376      wouldn't happen.  (See write_inferior_registers in sparc-xdep.c.)  */
377   write_register (SP_REGNUM, sp);
378
379   /* Figure out the value returned by the function.  */
380   {
381     char retbuf[REGISTER_BYTES];
382
383     /* Execute the stack dummy routine, calling FUNCTION.
384        When it is done, discard the empty frame
385        after storing the contents of all regs into retbuf.  */
386     run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
387
388     do_cleanups (old_chain);
389
390     return value_being_returned (value_type, retbuf, struct_return);
391   }
392 }
393 /* should return a value of some sort */
394  
395 value
396 vx_call_function (funcAddr, nargs, args, valueType)
397     char *funcAddr;
398     int nargs;
399     value *args;
400     struct type * valueType;
401 {
402     int i;
403     func_call funcInfo;
404     arg_value *argValue;
405     enum clnt_stat status;
406     register int len;
407     arg_value funcReturn;
408     value gdbValue;
409
410     argValue = (arg_value *) xmalloc (nargs * sizeof (arg_value));
411
412     bzero (argValue, nargs * sizeof (arg_value));
413     bzero (&funcReturn, sizeof (funcReturn));
414
415     for (i = nargs - 1; i >= 0; i--)
416         {
417         len = TYPE_LENGTH (VALUE_TYPE (args [i]));
418
419         switch (TYPE_CODE (VALUE_TYPE (args[i])))
420             {
421             /* XXX put other types here.  Where's CHAR, etc??? */
422
423             case TYPE_CODE_FLT:
424                 argValue[i].type = T_FLOAT;
425                 break;
426             case TYPE_CODE_INT:
427             case TYPE_CODE_PTR:
428             case TYPE_CODE_ENUM:
429             case TYPE_CODE_FUNC:
430                 argValue[i].type = T_INT;
431                 break;
432
433             case TYPE_CODE_UNDEF:
434             case TYPE_CODE_ARRAY:
435             case TYPE_CODE_STRUCT:
436             case TYPE_CODE_UNION:
437             case TYPE_CODE_VOID:
438             case TYPE_CODE_SET:
439             case TYPE_CODE_RANGE:
440             case TYPE_CODE_PASCAL_ARRAY:
441             case TYPE_CODE_MEMBER:          /* C++ */
442             case TYPE_CODE_METHOD:          /* C++ */
443             case TYPE_CODE_REF:             /* C++ */
444             default:
445                 error ("No corresponding VxWorks type for %d.  CHECK IT OUT!!!\n",
446                         TYPE_CODE(VALUE_TYPE(args[i])));
447             } /* switch */
448         if (TYPE_CODE(VALUE_TYPE(args[i])) == TYPE_CODE_FUNC)
449             argValue[i].arg_value_u.v_int = VALUE_ADDRESS(args[i]);
450         else
451             bcopy (VALUE_CONTENTS (args[i]), (char *) &argValue[i].arg_value_u,
452                    len);
453         }
454
455     /* XXX what should the type of this function addr be?
456      * XXX Both in gdb and vxWorks
457      */
458     funcInfo.func_addr = (int) funcAddr;
459     funcInfo.args.args_len = nargs;
460     funcInfo.args.args_val = argValue;
461
462     status = net_clnt_call (VX_CALL_FUNC, xdr_func_call, (char *) &funcInfo,
463                             xdr_arg_value, &funcReturn);
464
465     free ((char *) argValue);
466
467     if (status == RPC_SUCCESS)
468         {
469         /* XXX this assumes that vxWorks ALWAYS returns an int, and that
470          * XXX gdb isn't expecting anything more
471          */
472
473         /*******************
474         if (funcReturn.type == T_UNKNOWN)
475             return YYYXXX...;
476         *******************/
477         gdbValue = allocate_value (valueType);
478         bcopy (&funcReturn.arg_value_u.v_int, VALUE_CONTENTS (gdbValue),
479                 sizeof (int));
480         return gdbValue;
481         }
482     else 
483         error (rpcerr);
484     }
485 #endif /* FIXME */
486  
487 /* Start an inferior process and sets inferior_pid to its pid.
488    EXEC_FILE is the file to run.
489    ALLARGS is a string containing the arguments to the program.
490    ENV is the environment vector to pass.
491    Returns process id.  Errors reported with error().
492    On VxWorks, we ignore exec_file.  */
493  
494 void
495 vx_create_inferior (exec_file, args, env)
496      char *exec_file;
497      char *args;
498      char **env;
499 {
500   enum clnt_stat status;
501   arg_array passArgs;
502   TASK_START taskStart;
503
504   bzero ((char *) &passArgs, sizeof (passArgs));
505   bzero ((char *) &taskStart, sizeof (taskStart));
506
507   /* parse arguments, put them in passArgs */
508
509   parse_args (args, &passArgs);
510
511   if (passArgs.arg_array_len == 0)
512     error ("You must specify a function name to run, and arguments if any");
513
514   status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
515                           xdr_TASK_START, &taskStart);
516
517   if ((status != RPC_SUCCESS) || (taskStart.status == -1))
518     error ("Can't create process on remote target machine");
519
520   /* Save the name of the running function */
521   vx_running = savestring (passArgs.arg_array_val[0],
522                            strlen (passArgs.arg_array_val[0]));
523
524 #ifdef CREATE_INFERIOR_HOOK
525   CREATE_INFERIOR_HOOK (pid);
526 #endif  
527
528   push_target (&vx_run_ops);
529   inferior_pid = taskStart.pid;
530
531 #if defined (START_INFERIOR_HOOK)
532   START_INFERIOR_HOOK ();
533 #endif
534
535   /* We will get a trace trap after one instruction.
536      Insert breakpoints and continue.  */
537
538   init_wait_for_inferior ();
539
540   /* Set up the "saved terminal modes" of the inferior
541      based on what modes we are starting it with.  */
542   target_terminal_init ();
543
544   /* Install inferior's terminal modes.  */
545   target_terminal_inferior ();
546
547   /* remote_start(args); */
548   /* trap_expected = 0; */
549   stop_soon_quietly = 1;
550   wait_for_inferior ();         /* Get the task spawn event */
551   stop_soon_quietly = 0;
552
553   /* insert_step_breakpoint ();  FIXME, do we need this?  */
554   proceed(-1, -1, 0);
555 }
556
557 /* Fill ARGSTRUCT in argc/argv form with the arguments from the
558    argument string ARGSTRING.  */
559
560 static void
561 parse_args (arg_string, arg_struct)
562      register char *arg_string;
563      arg_array *arg_struct;
564 {
565   register int arg_count = 0;   /* number of arguments */
566   register int arg_index = 0;
567   register char *p0;
568  
569   bzero ((char *) arg_struct, sizeof (arg_array));
570  
571   /* first count how many arguments there are */
572
573   p0 = arg_string;
574   while (*p0 != '\0')
575     {
576       if (*(p0 = skip_white_space (p0)) == '\0')
577         break;
578       p0 = find_white_space (p0);
579       arg_count++;
580     }
581
582   arg_struct->arg_array_len = arg_count;
583   arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
584                                                  * sizeof (char *));
585
586   /* now copy argument strings into arg_struct.  */
587
588   while (*(arg_string = skip_white_space (arg_string)))
589     {
590       p0 = find_white_space (arg_string);
591       arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
592                                                            p0 - arg_string);
593       arg_string = p0;
594     }
595
596   arg_struct->arg_array_val[arg_count] = NULL;
597 }
598
599 /* Advance a string pointer across whitespace and return a pointer
600    to the first non-white character.  */
601
602 static char *
603 skip_white_space (p)
604      register char *p;
605 {
606   while (*p == ' ' || *p == '\t')
607     p++;
608   return p;
609 }
610     
611 /* Search for the first unquoted whitespace character in a string.
612    Returns a pointer to the character, or to the null terminator
613    if no whitespace is found.  */
614
615 static char *
616 find_white_space (p)
617      register char *p;
618 {
619   register int c;
620
621   while ((c = *p) != ' ' && c != '\t' && c)
622     {
623       if (c == '\'' || c == '"')
624         {
625           while (*++p != c && *p)
626             {
627               if (*p == '\\')
628                 p++;
629             }
630           if (!*p)
631             break;
632         }
633       p++;
634     }
635   return p;
636 }
637     
638 /* Poll the VxWorks target system for an event related
639    to the debugged task.
640    Returns -1 if remote wait failed, task status otherwise.  */
641
642 int
643 net_wait (pEvent)
644     RDB_EVENT *pEvent;
645 {
646     int pid;
647     enum clnt_stat status;
648
649     bzero ((char *) pEvent, sizeof (RDB_EVENT));
650
651     pid = inferior_pid;
652     status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, pEvent);
653
654     return (status == RPC_SUCCESS)? pEvent->status: -1;
655 }
656     
657 /* Suspend the remote task.
658    Returns -1 if suspend fails on target system, 0 otherwise.  */
659
660 int
661 net_quit ()
662 {
663     int pid;
664     int quit_status;
665     enum clnt_stat status;
666
667     quit_status = 0;
668
669     /* don't let rdbTask suspend itself by passing a pid of 0 */
670
671     if ((pid = inferior_pid) == 0)
672         return -1;
673
674     status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
675                             &quit_status);
676
677     return (status == RPC_SUCCESS)? quit_status: -1;
678 }
679
680 /* Read a register or registers from the remote system.  */
681
682 int
683 vx_read_register (regno)
684      int regno;
685 {
686   int status;
687   Rptrace ptrace_in;
688   Ptrace_return ptrace_out;
689   struct regs inferior_registers;
690   struct fp_status inferior_fp_registers;
691   extern char registers[];
692
693   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
694   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
695
696   /* FIXME, eventually only get the ones we need.  */
697   registers_fetched ();
698   
699   ptrace_in.pid = inferior_pid;
700   ptrace_out.info.more_data = (caddr_t) &inferior_registers;
701   status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
702   if (status)
703     error (rpcerr);
704   if (ptrace_out.status == -1)
705     {
706       errno = ptrace_out.errno;
707       return -1;
708     }
709   
710 #ifdef I80960
711
712       bcopy ((char *) inferior_registers.r_lreg,
713              &registers[REGISTER_BYTE (R0_REGNUM)], 16 * sizeof (int));
714       bcopy ((char *) inferior_registers.r_greg,
715              &registers[REGISTER_BYTE (G0_REGNUM)], 16 * sizeof (int));
716
717       /* Don't assume that a location in registers[] is properly aligned.  */
718
719       bcopy ((char *) &inferior_registers.r_pcw,
720              &registers[REGISTER_BYTE (PCW_REGNUM)], sizeof (int));
721       bcopy ((char *) &inferior_registers.r_acw,
722              &registers[REGISTER_BYTE (ACW_REGNUM)], sizeof (int));
723       bcopy ((char *) &inferior_registers.r_lreg[2],    /* r2 (RIP) -> IP */
724              &registers[REGISTER_BYTE (IP_REGNUM)], sizeof (int));
725       bcopy ((char *) &inferior_registers.r_tcw,
726              &registers[REGISTER_BYTE (TCW_REGNUM)], sizeof (int));
727
728       /* If the target has floating point registers, fetch them.
729          Otherwise, zero the floating point register values in
730          registers[] for good measure, even though we might not
731          need to.  */
732
733       if (target_has_fp)
734         {
735           ptrace_in.pid = inferior_pid;
736           ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
737           status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
738           if (status)
739             error (rpcerr);
740           if (ptrace_out.status == -1)
741             {
742               errno = ptrace_out.errno;
743               return -1;
744             }
745           
746           bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
747                  REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
748         }
749       else
750         {
751           bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
752                  REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
753         }
754
755 #else  /* not 960, thus must be 68000:  FIXME!  */
756
757   bcopy (&inferior_registers, registers, 16 * 4);
758   *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
759   *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
760
761   if (target_has_fp)
762     {
763       ptrace_in.pid = inferior_pid;
764       ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
765       status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
766       if (status)
767         error (rpcerr);
768       if (ptrace_out.status == -1)
769         {
770           errno = ptrace_out.errno;
771           return -1;
772         }
773       
774       bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
775              sizeof inferior_fp_registers.fps_regs);
776       bcopy (&inferior_fp_registers.fps_control,
777          &registers[REGISTER_BYTE (FPC_REGNUM)],
778          sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
779     }
780   else
781     {
782       bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
783              sizeof inferior_fp_registers.fps_regs);
784       bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
785          sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
786     }
787 #endif  /* various architectures */
788
789   return 0;
790 }
791
792 /* Prepare to store registers.  Since we will store all of them,
793    read out their current values now.  */
794
795 void
796 vx_prepare_to_store ()
797 {
798   vx_read_register (-1);
799 }
800
801
802 /* Store our register values back into the inferior.
803    If REGNO is -1, do this for all registers.
804    Otherwise, REGNO specifies which register (so we can save time).  */
805    /* FIXME, look at REGNO to save time here */
806
807 vx_write_register (regno)
808      int regno;
809 {
810   struct regs inferior_registers;
811   struct fp_status inferior_fp_registers;
812   extern char registers[];
813   int status;
814   Rptrace ptrace_in;
815   Ptrace_return ptrace_out;
816
817   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
818   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
819
820 #ifdef I80960
821
822   bcopy (&registers[REGISTER_BYTE (R0_REGNUM)],
823          (char *) inferior_registers.r_lreg, 16 * sizeof (int));
824   bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
825          (char *) inferior_registers.r_greg, 16 * sizeof (int));
826
827   /* Don't assume that a location in registers[] is properly aligned.  */
828
829   bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)],
830          (char *) &inferior_registers.r_pcw, sizeof (int));
831   bcopy (&registers[REGISTER_BYTE (ACW_REGNUM)],
832          (char *) &inferior_registers.r_acw, sizeof (int));
833   bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)],
834          (char *) &inferior_registers.r_tcw, sizeof (int));
835
836 #else  /* not 960 -- assume 68k -- FIXME */
837
838   bcopy (registers, &inferior_registers, 16 * 4);
839   inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
840   inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
841
842 #endif  /* Different register sets */
843
844   ptrace_in.pid = inferior_pid;
845   ptrace_in.info.ttype     = REGS;
846   ptrace_in.info.more_data = (caddr_t) &inferior_registers;
847
848   /* XXX change second param to be a proc number */
849   status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
850   if (status)
851       error (rpcerr);
852   if (ptrace_out.status == -1)
853     {
854       errno = ptrace_out.errno;
855       return -1;
856     }
857
858   /* Store floating point registers if the target has them.  */
859
860   if (target_has_fp)
861     {
862 #ifdef I80960
863
864       bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
865              sizeof inferior_fp_registers.fps_regs);
866
867 #else  /* not 960 -- assume 68k -- FIXME */
868
869       bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
870              sizeof inferior_fp_registers.fps_regs);
871       bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
872          &inferior_fp_registers.fps_control,
873          sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
874
875 #endif  /* Different register sets */
876
877       ptrace_in.pid = inferior_pid;
878       ptrace_in.info.ttype     = FPREGS;
879       ptrace_in.info.more_data = (caddr_t) &inferior_fp_registers;
880
881       status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in, &ptrace_out);
882       if (status)
883           error (rpcerr);
884       if (ptrace_out.status == -1)
885         {
886           errno = ptrace_out.errno;
887           return -1;
888         }
889     }
890   return 0;
891 }
892
893 /* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
894    to debugger memory starting at MYADDR.  WRITE is true if writing to the
895    inferior.
896    Result is the number of bytes written or read (zero if error).  The
897    protocol allows us to return a negative count, indicating that we can't
898    handle the current address but can handle one N bytes further, but
899    vxworks doesn't give us that information.  */
900
901 int
902 vx_xfer_memory (memaddr, myaddr, len, write)
903      CORE_ADDR memaddr;
904      char *myaddr;
905      int len;
906 {
907   int status;
908   Rptrace ptrace_in;
909   Ptrace_return ptrace_out;
910   C_bytes data;
911
912   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
913   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
914
915   ptrace_in.pid = inferior_pid;         /* XXX pid unnecessary for READDATA */
916   ptrace_in.addr = (int) memaddr;       /* Where from */
917   ptrace_in.data = len;                 /* How many bytes */
918
919   if (write)
920     {
921       ptrace_in.info.ttype     = DATA;
922       ptrace_in.info.more_data = (caddr_t) &data;
923
924       data.bytes = (caddr_t) myaddr;    /* Where from */
925       data.len   = len;                 /* How many bytes (again, for XDR) */
926
927       /* XXX change second param to be a proc number */
928       status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in, &ptrace_out);
929     }
930   else
931     {
932       ptrace_out.info.more_data = (caddr_t) &data;
933       data.bytes = myaddr;              /* Where to */
934       data.len   = len;                 /* How many (again, for XDR) */
935
936       /* XXX change second param to be a proc number */
937       status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
938     }
939
940   if (status)
941       error (rpcerr);
942   if (ptrace_out.status == -1)
943     {
944       return 0;         /* No bytes moved */
945     }
946   return len;           /* Moved *all* the bytes */
947 }
948
949 void
950 vx_files_info ()
951 {
952   printf ("\tAttached to host `%s'", vx_host);
953   printf (", which has %sfloating point", target_has_fp? "": "no ");
954   printf (".\n");
955 }
956
957 void
958 vx_run_files_info ()
959 {
960   printf ("\tRunning %s VxWorks process 0x%x", 
961           vx_running? "child": "attached",
962           inferior_pid);
963   if (vx_running)
964     printf (", function `%s'", vx_running);
965   printf(".\n");
966 }
967
968 void
969 vx_resume (step, siggnal)
970      int step;
971      int siggnal;
972 {
973   int status;
974   Rptrace ptrace_in;
975   Ptrace_return ptrace_out;
976
977   if (siggnal != 0 && siggnal != stop_signal)
978     error ("Cannot send signals to VxWorks processes");
979
980   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
981   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
982
983   ptrace_in.pid = inferior_pid;
984   ptrace_in.addr = 1;   /* Target side insists on this, or it panics.  */
985
986   /* XXX change second param to be a proc number */
987   status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
988                                  &ptrace_in, &ptrace_out);
989   if (status)
990       error (rpcerr);
991   if (ptrace_out.status == -1)
992     {
993       errno = ptrace_out.errno;
994       perror_with_name ("Resuming remote process");
995     }
996 }
997
998 void
999 vx_mourn_inferior ()
1000 {
1001   pop_target ();                /* Pop back to no-child state */
1002   generic_mourn_inferior ();
1003 }
1004
1005 \f
1006 /* This function allows the addition of incrementally linked object files.  */
1007
1008 void
1009 vx_load_command (arg_string, from_tty)
1010      char* arg_string;
1011      int from_tty;
1012 {
1013   CORE_ADDR text_addr;
1014   CORE_ADDR data_addr;
1015   CORE_ADDR bss_addr;
1016   
1017   if (arg_string == 0)
1018     error ("The load command takes a file name");
1019
1020   arg_string = tilde_expand (arg_string);
1021   make_cleanup (free, arg_string);
1022
1023   dont_repeat ();
1024
1025   QUIT;
1026   immediate_quit++;
1027   if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
1028     error ("Load failed on target machine");
1029   immediate_quit--;
1030
1031   /* FIXME, for now we ignore data_addr and bss_addr.  */
1032   symbol_file_add (arg_string, from_tty, text_addr, 0);
1033 }
1034
1035 #ifdef FIXME  /* Not ready for prime time */
1036 /* Single step the target program at the source or machine level.
1037    Takes an error exit if rpc fails.
1038    Returns -1 if remote single-step operation fails, else 0.  */
1039
1040 static int
1041 net_step ()
1042 {
1043   enum clnt_stat status;
1044   int step_status;
1045   SOURCE_STEP source_step;
1046
1047   source_step.taskId = inferior_pid;
1048
1049   if (step_range_end)
1050     {
1051       source_step.startAddr = step_range_start;
1052       source_step.endAddr = step_range_end;
1053     }
1054   else
1055     {
1056       source_step.startAddr = 0;
1057       source_step.endAddr = 0;
1058     }
1059
1060   status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
1061                           xdr_int, &step_status);
1062
1063   if (status == RPC_SUCCESS)
1064     return step_status;
1065   else 
1066     error (rpcerr);
1067 }
1068 #endif
1069
1070 /* Emulate ptrace using RPC calls to the VxWorks target system.
1071    Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise.  */
1072
1073 static int
1074 net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
1075     enum ptracereq request;
1076     Rptrace *pPtraceIn;
1077     Ptrace_return *pPtraceOut;
1078 {
1079   enum clnt_stat status;
1080
1081   status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
1082                           pPtraceOut);
1083
1084   if (status != RPC_SUCCESS)
1085       return -1;
1086
1087   return 0;
1088 }
1089
1090 /* Query the target for the name of the file from which VxWorks was
1091    booted.  pBootFile is the address of a pointer to the buffer to
1092    receive the file name; if the pointer pointed to by pBootFile is 
1093    NULL, memory for the buffer will be allocated by XDR.
1094    Returns -1 if rpc failed, 0 otherwise.  */
1095
1096 int
1097 net_get_boot_file (pBootFile)
1098      char **pBootFile;
1099 {
1100   enum clnt_stat status;
1101
1102   status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
1103                           xdr_wrapstring, pBootFile);
1104   return (status == RPC_SUCCESS) ? 0 : -1;
1105 }
1106
1107 /* Fetch a list of loaded object modules from the VxWorks target.
1108    Returns -1 if rpc failed, 0 otherwise
1109    There's no way to check if the returned loadTable is correct.
1110    VxWorks doesn't check it.  */
1111
1112 int
1113 net_get_symbols (pLoadTable)
1114      ldtabl *pLoadTable;                /* return pointer to ldtabl here */
1115 {
1116   enum clnt_stat status;
1117
1118   bzero ((char *) pLoadTable, sizeof (struct ldtabl));
1119
1120   status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
1121   return (status == RPC_SUCCESS) ? 0 : -1;
1122 }
1123
1124 /* Look up a symbol in the VxWorks target's symbol table.
1125    Returns status of symbol read on target side (0=success, -1=fail)
1126    Returns -1 and complain()s if rpc fails.  */
1127
1128 struct complaint cant_contact_target =
1129   {"Lost contact with VxWorks target", 0, 0};
1130
1131 int
1132 vx_lookup_symbol (name, pAddr)
1133      char *name;                /* symbol name */
1134      CORE_ADDR *pAddr;
1135 {
1136   enum clnt_stat status;
1137   SYMBOL_ADDR symbolAddr;
1138
1139   *pAddr = 0;
1140   bzero ((char *) &symbolAddr, sizeof (symbolAddr));
1141
1142   status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
1143                           xdr_SYMBOL_ADDR, &symbolAddr);
1144   if (status != RPC_SUCCESS) {
1145       complain (&cant_contact_target, 0);
1146       return -1;
1147   }
1148
1149   *pAddr = symbolAddr.addr;
1150   return symbolAddr.status;
1151 }
1152
1153 /* Check to see if the VxWorks target has a floating point coprocessor.
1154    Returns 1 if target has floating point processor, 0 otherwise.
1155    Calls error() if rpc fails.  */
1156
1157 int
1158 net_check_for_fp ()
1159 {
1160   enum clnt_stat status;
1161   bool_t fp = 0;        /* true if fp processor is present on target board */
1162
1163   status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
1164   if (status != RPC_SUCCESS)
1165       error (rpcerr);
1166
1167    return (int) fp;
1168 }
1169
1170 /* Establish an RPC connection with the VxWorks target system.
1171    Calls error () if unable to establish connection.  */
1172
1173 void
1174 net_connect (host)
1175      char *host;
1176 {
1177   struct sockaddr_in destAddr;
1178   struct hostent *destHost;
1179
1180   /* get the internet address for the given host */
1181
1182   if ((destHost = (struct hostent *) gethostbyname (host)) == NULL)
1183       error ("Invalid hostname.  Couldn't find remote host address.");
1184
1185   bzero (&destAddr, sizeof (destAddr));
1186
1187   destAddr.sin_addr.s_addr = * (u_long *) destHost->h_addr;
1188   destAddr.sin_family      = AF_INET;
1189   destAddr.sin_port        = 0; /* set to actual port that remote
1190                                    ptrace is listening on.  */
1191
1192   /* Create a tcp client transport on which to issue
1193      calls to the remote ptrace server.  */
1194
1195   ptraceSock = RPC_ANYSOCK;
1196   pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
1197   /* FIXME, here is where we deal with different version numbers of the proto */
1198   
1199   if (pClient == NULL)
1200     {
1201       clnt_pcreateerror ("\tnet_connect");
1202       error ("Couldn't connect to remote target.");
1203     }
1204 }
1205 \f
1206 /* Sleep for the specified number of milliseconds 
1207  * (assumed to be less than 1000).
1208  * If select () is interrupted, returns immediately;
1209  * takes an error exit if select () fails for some other reason.
1210  */
1211
1212 static void
1213 sleep_ms (ms)
1214      long ms;
1215 {
1216   struct timeval select_timeout;
1217   int status;
1218
1219   select_timeout.tv_sec = 0;
1220   select_timeout.tv_usec = ms * 1000;
1221
1222   status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
1223
1224   if (status < 0 && errno != EINTR)
1225     perror_with_name ("select");
1226 }
1227
1228 /* Wait for control to return from inferior to debugger.
1229    If inferior gets a signal, we may decide to start it up again
1230    instead of returning.  That is why there is a loop in this function.
1231    When this function actually returns it means the inferior
1232    should be left stopped and GDB should read more commands.  */
1233
1234 /* For network debugging with VxWorks.
1235  * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
1236  * so vx_wait() receives this information directly from
1237  * VxWorks instead of trying to figure out what happenned via a wait() call.
1238  */
1239
1240 static int
1241 vx_wait (status)
1242      int *status;
1243 {
1244   register int pid;
1245   WAITTYPE w;
1246   RDB_EVENT rdbEvent;
1247   int quit_failed;
1248
1249   do
1250     {
1251       /* If CTRL-C is hit during this loop,
1252          suspend the inferior process.  */
1253
1254       quit_failed = 0;
1255       if (quit_flag)
1256         {
1257           quit_failed = (net_quit () == -1);
1258           quit_flag = 0;
1259         }
1260
1261       /* If a net_quit () or net_wait () call has failed,
1262          allow the user to break the connection with the target.
1263          We can't simply error () out of this loop, since the 
1264          data structures representing the state of the inferior
1265          are in an inconsistent state.  */
1266
1267       if (quit_failed || net_wait (&rdbEvent) == -1)
1268         {
1269           terminal_ours ();
1270           if (query ("Can't %s.  Disconnect from target system? ",
1271                      (quit_failed) ? "suspend remote task"
1272                                    : "get status of remote task"))
1273             {
1274               target_mourn_inferior();
1275               error ("Use the \"target\" command to reconnect.");
1276             }
1277           else
1278             {
1279               terminal_inferior ();
1280               continue;
1281             }
1282         }
1283       
1284       pid = rdbEvent.taskId;
1285       if (pid == 0)
1286         {
1287           sleep_ms (200);       /* FIXME Don't kill the network too badly */
1288         }
1289       else if (pid != inferior_pid)
1290         fatal ("Bad pid for debugged task: 0x%x\n", pid);
1291     } while (pid == 0);
1292
1293   /* FIXME, eventually do more then SIGTRAP on everything...  */
1294   switch (rdbEvent.eventType)
1295     {
1296     case EVENT_EXIT:
1297       WSETEXIT (w, 0);
1298       /* FIXME is it possible to distinguish between a
1299          XXX   normal vs abnormal exit in VxWorks? */
1300       break;
1301
1302     case EVENT_START:           /* Task was just started. */
1303       WSETSTOP (w, SIGTRAP);
1304       break;
1305
1306     case EVENT_STOP:
1307       WSETSTOP (w, SIGTRAP);
1308       /* XXX was it stopped by a signal?  act accordingly */
1309       break;
1310
1311     case EVENT_BREAK:           /* Breakpoint was hit. */
1312       WSETSTOP (w, SIGTRAP);
1313       break;
1314
1315     case EVENT_SUSPEND:         /* Task was suspended, probably by ^C. */
1316       WSETSTOP (w, SIGINT);
1317       break;
1318
1319     case EVENT_BUS_ERR:         /* Task made evil nasty reference. */
1320       WSETSTOP (w, SIGBUS);
1321       break;
1322
1323     case EVENT_ZERO_DIV:        /* Division by zero */
1324       WSETSTOP (w, SIGFPE);     /* Like Unix, call it a float exception. */
1325
1326     case EVENT_SIGNAL:
1327       /* The target is not running Unix, and its
1328          faults/traces do not map nicely into Unix signals.
1329          Make sure they do not get confused with Unix signals
1330          by numbering them with values higher than the highest
1331          legal Unix signal.  code in the arch-dependent PRINT_RANDOM_SIGNAL
1332          routine will interpret the value for wait_for_inferior.  */
1333       WSETSTOP (w, rdbEvent.sigType + NSIG);
1334       break;
1335     } /* switch */
1336   *status = *(int *)&w;         /* Grumble union wait crap Grumble */
1337   return pid;
1338 }
1339 \f
1340 static int
1341 symbol_stub (arg)
1342      int arg;
1343 {
1344   char *bootFile = (char *)arg;
1345   symbol_file_command (bootFile, 0);
1346   return 1;
1347 }
1348
1349 static int
1350 add_symbol_stub (arg)
1351      int arg;
1352 {
1353   struct ldfile *pLoadFile = (struct ldfile *)arg;
1354
1355   printf("\t%s: ", pLoadFile->name);
1356   symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
1357   printf ("ok\n");
1358   return 1;
1359 }
1360 /* Target command for VxWorks target systems.
1361
1362    Used in vxgdb.  Takes the name of a remote target machine
1363    running vxWorks and connects to it to initialize remote network
1364    debugging.  */
1365
1366 static void
1367 vx_open (args, from_tty)
1368      char *args;
1369      int from_tty;
1370 {
1371   extern int close ();
1372   char *bootFile;
1373   extern char *source_path;
1374   struct ldtabl loadTable;
1375   struct ldfile *pLoadFile;
1376   int i;
1377   extern CLIENT *pClient;
1378
1379   if (!args)
1380     error_no_arg ("target machine name");
1381
1382   unpush_target (&vx_ops);
1383   printf ("Attaching remote machine across net...\n");
1384   fflush (stdout);
1385
1386   /* Allow the user to kill the connect attempt by typing ^C.
1387      Wait until the call to target_has_fp () completes before
1388      disallowing an immediate quit, since even if net_connect ()
1389      is successful, the remote debug server might be hung.  */
1390
1391   immediate_quit++;
1392
1393   net_connect (args);
1394   target_has_fp = net_check_for_fp ();
1395   printf_filtered ("Connected to %s.\n", args);
1396
1397   immediate_quit--;
1398
1399   push_target (&vx_ops);
1400
1401   /* Save a copy of the target host's name.  */
1402   vx_host = savestring (args, strlen (args));
1403
1404   /* Find out the name of the file from which the target was booted
1405      and load its symbol table.  */
1406
1407   printf_filtered ("Looking in Unix path for all loaded modules:\n");
1408   bootFile = NULL;
1409   if (!net_get_boot_file (&bootFile))
1410     {
1411       if (*bootFile) {
1412         printf_filtered ("\t%s: ", bootFile);
1413         if (catch_errors (symbol_stub, (int)bootFile,
1414                 "Error reading symbols from boot file"))
1415           puts_filtered ("ok\n");
1416       } else if (from_tty)
1417         printf ("VxWorks kernel symbols not loaded.\n");
1418     }
1419   else
1420     error ("Can't retrieve boot file name from target machine.");
1421
1422   clnt_freeres (pClient, xdr_wrapstring, &bootFile);
1423
1424   if (net_get_symbols (&loadTable) != 0)
1425     error ("Can't read loaded modules from target machine");
1426
1427   i = 0-1;
1428   while (++i < loadTable.tbl_size)
1429     {
1430       QUIT;     /* FIXME, avoids clnt_freeres below:  mem leak */
1431       pLoadFile = &loadTable.tbl_ent [i];
1432 #ifdef WRS_ORIG
1433   {
1434     register int desc;
1435     struct cleanup *old_chain;
1436     char *fullname = NULL;
1437
1438     desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
1439     if (desc < 0)
1440         perror_with_name (pLoadFile->name);
1441     old_chain = make_cleanup (close, desc);
1442     add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
1443                       pLoadFile->bss_addr);
1444     do_cleanups (old_chain);
1445   }
1446 #else
1447       /* Botches, FIXME:
1448          (1)  Searches the PATH, not the source path.
1449          (2)  data and bss are assumed to be at the usual offsets from text.  */
1450       catch_errors (add_symbol_stub, (int)pLoadFile, (char *)0);
1451 #endif
1452     }
1453   printf_filtered ("Done.\n");
1454
1455   clnt_freeres (pClient, xdr_ldtabl, &loadTable);
1456 }
1457 \f
1458 /* attach_command --
1459    takes a task started up outside of gdb and ``attaches'' to it.
1460    This stops it cold in its tracks and allows us to start tracing it.  */
1461
1462 static void
1463 vx_attach (args, from_tty)
1464      char *args;
1465      int from_tty;
1466 {
1467   int pid;
1468   char *cptr = 0;
1469   Rptrace ptrace_in;
1470   Ptrace_return ptrace_out;
1471   int status;
1472
1473   dont_repeat();
1474
1475   if (!args)
1476     error_no_arg ("process-id to attach");
1477
1478   pid = strtol (args, &cptr, 0);
1479   if ((cptr == args) || (*cptr != '\0'))
1480     error ("Invalid process-id -- give a single number in decimal or 0xhex");
1481
1482   if (from_tty)
1483       printf ("Attaching pid 0x%x.\n", pid);
1484
1485   bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
1486   bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1487   ptrace_in.pid = pid;
1488
1489   status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
1490   if (status == -1)
1491     error (rpcerr);
1492   if (ptrace_out.status == -1)
1493     {
1494       errno = ptrace_out.errno;
1495       perror_with_name ("Attaching remote process");
1496     }
1497
1498   /* It worked... */
1499   push_target (&vx_run_ops);
1500   inferior_pid = pid;
1501   vx_running = 0;
1502
1503 #if defined (START_INFERIOR_HOOK)
1504   START_INFERIOR_HOOK ();
1505 #endif
1506
1507   mark_breakpoints_out ();
1508
1509   /* Set up the "saved terminal modes" of the inferior
1510      based on what modes we are starting it with.  */
1511   target_terminal_init ();
1512
1513   /* Install inferior's terminal modes.  */
1514   target_terminal_inferior ();
1515
1516   /* We will get a task spawn event immediately.  */
1517   init_wait_for_inferior ();
1518   clear_proceed_status ();
1519   stop_soon_quietly = 1;
1520   wait_for_inferior ();
1521   stop_soon_quietly = 0;
1522   normal_stop ();
1523 }
1524
1525
1526 /* detach_command --
1527    takes a program previously attached to and detaches it.
1528    The program resumes execution and will no longer stop
1529    on signals, etc.  We better not have left any breakpoints
1530    in the program or it'll die when it hits one.  For this
1531    to work, it may be necessary for the process to have been
1532    previously attached.  It *might* work if the program was
1533    started via the normal ptrace (PTRACE_TRACEME).  */
1534
1535 static void
1536 vx_detach (args, from_tty)
1537      char *args;
1538      int from_tty;
1539 {
1540   Rptrace ptrace_in;
1541   Ptrace_return ptrace_out;
1542   int signal = 0;
1543   int status;
1544
1545   if (args)
1546     error ("Argument given to VxWorks \"detach\".");
1547
1548   if (from_tty)
1549       printf ("Detaching pid 0x%x.\n", inferior_pid);
1550
1551   if (args)             /* FIXME, should be possible to leave suspended */
1552     signal = atoi (args);
1553   
1554   bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
1555   bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1556   ptrace_in.pid = inferior_pid;
1557
1558   status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
1559   if (status == -1)
1560     error (rpcerr);
1561   if (ptrace_out.status == -1)
1562     {
1563       errno = ptrace_out.errno;
1564       perror_with_name ("Detaching VxWorks process");
1565     }
1566
1567   inferior_pid = 0;
1568   pop_target ();        /* go back to non-executing VxWorks connection */
1569 }
1570
1571 /* vx_kill -- takes a running task and wipes it out.  */
1572
1573 static void
1574 vx_kill (args, from_tty)
1575      char *args;
1576      int from_tty;
1577 {
1578   Rptrace ptrace_in;
1579   Ptrace_return ptrace_out;
1580   int status;
1581
1582   if (args)
1583     error ("Argument given to VxWorks \"kill\".");
1584
1585   if (from_tty)
1586       printf ("Killing pid 0x%x.\n", inferior_pid);
1587
1588   bzero ((char *)&ptrace_in,  sizeof (ptrace_in));
1589   bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1590   ptrace_in.pid = inferior_pid;
1591
1592   status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
1593   if (status == -1)
1594     error (rpcerr);
1595   if (ptrace_out.status == -1)
1596     {
1597       errno = ptrace_out.errno;
1598       perror_with_name ("Killing VxWorks process");
1599     }
1600
1601   /* If it gives good status, the process is *gone*, no events remain.  */
1602   inferior_pid = 0;
1603   pop_target ();        /* go back to non-executing VxWorks connection */
1604 }
1605
1606 /* Clean up from the VxWorks process target as it goes away.  */
1607
1608 void
1609 vx_proc_close (quitting)
1610      int quitting;
1611 {
1612   inferior_pid = 0;             /* No longer have a process.  */
1613   if (vx_running)
1614     free (vx_running);
1615   vx_running = 0;
1616 }
1617 \f
1618 /* Cross-net conversion of floats to and from extended form.
1619    (This is needed because different target machines have different
1620     extended floating point formats.)  */
1621
1622 /* Convert from an extended float to a double.
1623
1624    The extended float is stored as raw data pointed to by FROM.
1625    Return the converted value as raw data in the double pointed to by TO.
1626 */
1627
1628 static void
1629 vx_convert_to_virtual (regno, from, to)
1630     int regno;
1631     char *from;
1632     char *to;
1633 {
1634   enum clnt_stat status;
1635
1636   if (REGISTER_CONVERTIBLE (regno)) 
1637     {
1638       if (!target_has_fp) {
1639         *(double *)to = 0.0;    /* Skip the trouble if no float anyway */
1640         return;
1641       }
1642
1643       status = net_clnt_call (VX_CONV_FROM_68881, xdr_ext_fp, from,
1644                               xdr_double, to);
1645
1646       if (status == RPC_SUCCESS)
1647           return;
1648       else
1649           error (rpcerr);
1650     }
1651   else
1652     bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
1653 }
1654
1655
1656 /* The converse:  convert from a double to an extended float.
1657
1658    The double is stored as raw data pointed to by FROM.
1659    Return the converted value as raw data in the extended
1660    float pointed to by TO.
1661 */
1662
1663 static void
1664 vx_convert_from_virtual (regno, from, to)
1665     int regno;
1666     char *from;
1667     char *to;
1668 {
1669   enum clnt_stat status;
1670
1671   if (REGISTER_CONVERTIBLE (regno)) 
1672     {
1673       if (!target_has_fp) {
1674         bzero (to, REGISTER_RAW_SIZE (FP0_REGNUM));     /* Shrug */
1675         return;
1676       }
1677
1678       status = net_clnt_call (VX_CONV_TO_68881, xdr_double, from,
1679                               xdr_ext_fp, to);
1680       if (status == RPC_SUCCESS)
1681           return;
1682       else
1683           error (rpcerr);
1684     }
1685   else
1686     bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
1687 }
1688 \f
1689 /* Make an RPC call to the VxWorks target.
1690    Returns RPC status.  */
1691
1692 static enum clnt_stat
1693 net_clnt_call (procNum, inProc, in, outProc, out)
1694     enum ptracereq procNum;
1695     xdrproc_t inProc;
1696     char *in;
1697     xdrproc_t outProc;
1698     char *out;
1699 {
1700   enum clnt_stat status;
1701   
1702   status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
1703
1704   if (status != RPC_SUCCESS)
1705       clnt_perrno (status);
1706
1707   return status;
1708 }
1709
1710 /* Clean up before losing control.  */
1711
1712 void
1713 vx_close (quitting)
1714      int quitting;
1715 {
1716   if (pClient)
1717     clnt_destroy (pClient);     /* The net connection */
1718   pClient = 0;
1719
1720   if (vx_host)
1721     free (vx_host);             /* The hostname */
1722   vx_host = 0;
1723 }
1724
1725
1726 /* Target ops structure for accessing memory and such over the net */
1727
1728 struct target_ops vx_ops = {
1729         "vxworks", "VxWorks target memory via RPC over TCP/IP",
1730         vx_open, vx_close, vx_attach, 0, /* vx_detach, */
1731         0, 0, /* resume, wait */
1732         0, 0, /* read_reg, write_reg */
1733         0, vx_convert_to_virtual, vx_convert_from_virtual,  /* prep_to_store, */
1734         vx_xfer_memory, vx_files_info,
1735         0, 0, /* insert_breakpoint, remove_breakpoint */
1736         0, 0, 0, 0, 0,  /* terminal stuff */
1737         0, /* vx_kill, */
1738         vx_load_command, add_syms_addr_command,
1739         0,  /* call_function */
1740         vx_lookup_symbol,
1741         vx_create_inferior, 0,  /* mourn_inferior */
1742         core_stratum, 0, /* next */
1743         1, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
1744         OPS_MAGIC,              /* Always the last thing */
1745 };
1746
1747 /* Target ops structure for accessing VxWorks child processes over the net */
1748
1749 struct target_ops vx_run_ops = {
1750         "vxprocess", "VxWorks process",
1751         vx_open, vx_proc_close, 0, vx_detach, /* vx_attach */
1752         vx_resume, vx_wait,
1753         vx_read_register, vx_write_register,
1754         vx_prepare_to_store, vx_convert_to_virtual, vx_convert_from_virtual,
1755         vx_xfer_memory, vx_run_files_info,
1756         vx_insert_breakpoint, vx_remove_breakpoint,
1757         0, 0, 0, 0, 0,  /* terminal stuff */
1758         vx_kill,
1759         vx_load_command, add_syms_addr_command,
1760         call_function_by_hand,  /* FIXME, calling fns is maybe botched? */
1761         vx_lookup_symbol,
1762         0, vx_mourn_inferior,
1763         process_stratum, 0, /* next */
1764         0, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
1765                         /* all_mem is off to avoid spurious msg in "i files" */
1766         OPS_MAGIC,              /* Always the last thing */
1767 };
1768 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
1769 \f
1770 void
1771 _initialize_vx ()
1772 {
1773   add_target (&vx_ops);
1774   add_target (&vx_run_ops);
1775 }
This page took 0.168299 seconds and 4 git commands to generate.