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