]> Git Repo - binutils.git/blob - gdb/remote-vx.68.c
ansi name abuse changes
[binutils.git] / gdb / remote-vx.68.c
1 /* Memory-access and commands for remote VxWorks processes, for GDB.
2    Copyright (C) 1990  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 "tm-vxworks68.h"
23 #include "param-no-tm.h"
24 #include "frame.h"
25 #include "inferior.h"
26 #include "wait.h"
27 #include "target.h"
28 #include "gdbcore.h"
29 #include "command.h"
30 #include "symtab.h"
31 #include "symfile.h"            /* for struct complaint */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <fcntl.h>
38 #include <sys/types.h>
39 #include <sys/time.h>
40 #include <sys/socket.h>
41 #define free bogon_free         /* Sun claims "int free()" not void */
42 #include <rpc/rpc.h>
43 #undef free
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;
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 extern int errno;
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     load_timeout.tv_sec = 0x7FFF7FFF;   /* A large number, effectively inf. */
115     load_timeout.tv_usec = 0;
116  
117     status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
118                         &ldstruct, load_timeout);
119
120     if (status == RPC_SUCCESS)
121       {
122         if (*ldstruct.name == NULL)     /* load failed on VxWorks side */
123           return -1;
124         *pTextAddr = ldstruct.txt_addr;
125         *pDataAddr = ldstruct.data_addr;
126         *pBssAddr = ldstruct.bss_addr;
127         return 0;
128       }
129     else
130         return -1;
131     }
132       
133 /* returns 0 if successful, errno if RPC failed or VxWorks complains. */
134
135 static int
136 net_break (addr, procnum)
137     int addr;
138     u_long procnum;
139     {
140     enum clnt_stat status;
141     int break_status;
142     Rptrace ptrace_in;  /* XXX This is stupid.  It doesn't need to be a ptrace
143                            structure.  How about something smaller? */
144
145     bzero ((char *) &ptrace_in, sizeof (ptrace_in));
146     break_status = 0;
147
148     ptrace_in.addr = addr;
149     ptrace_in.pid = inferior_pid;
150
151     status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
152                             &break_status);
153
154     if (status != RPC_SUCCESS)
155         return errno;
156
157     if (break_status == -1)
158       return ENOMEM;
159     return break_status;        /* probably (FIXME) zero */
160     }
161  
162 /* returns 0 if successful, errno otherwise */
163
164 int
165 vx_insert_breakpoint (addr)
166     int addr;
167     {
168     return net_break (addr, VX_BREAK_ADD);
169     }
170
171 /* returns 0 if successful, errno otherwise */
172
173 int
174 vx_remove_breakpoint (addr)
175     int addr;
176     {
177     return net_break (addr, VX_BREAK_DELETE);
178     }
179
180 /* Call a function on the VxWorks target system.
181    ARGS is a vector of values of arguments (NARGS of them).
182    FUNCTION is a value, the function to be called.
183    Returns a struct value * representing what the function returned.
184    May fail to return, if a breakpoint or signal is hit
185    during the execution of the function.  */
186
187 #ifdef FIXME
188 /* FIXME, function calls are really fried.  GO back to manual method. */
189 value
190 vx_call_function (function, nargs, args)
191      value function;
192      int nargs;
193      value *args;
194 {
195   register CORE_ADDR sp;
196   register int i;
197   CORE_ADDR start_sp;
198   static REGISTER_TYPE dummy[] = CALL_DUMMY;
199   REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
200   CORE_ADDR old_sp;
201   struct type *value_type;
202   unsigned char struct_return;
203   CORE_ADDR struct_addr;
204   struct inferior_status inf_status;
205   struct cleanup *old_chain;
206   CORE_ADDR funaddr;
207   int using_gcc;
208
209   save_inferior_status (&inf_status, 1);
210   old_chain = make_cleanup (restore_inferior_status, &inf_status);
211
212   /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
213      (and POP_FRAME for restoring them).  (At least on most machines)
214      they are saved on the stack in the inferior.  */
215   PUSH_DUMMY_FRAME;
216
217   old_sp = sp = read_register (SP_REGNUM);
218
219 #if 1 INNER_THAN 2              /* Stack grows down */
220   sp -= sizeof dummy;
221   start_sp = sp;
222 #else                           /* Stack grows up */
223   start_sp = sp;
224   sp += sizeof dummy;
225 #endif
226
227   funaddr = find_function_addr (function, &value_type);
228
229   {
230     struct block *b = block_for_pc (funaddr);
231     /* If compiled without -g, assume GCC.  */
232     using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
233   }
234
235   /* Are we returning a value using a structure return or a normal
236      value return? */
237
238   struct_return = using_struct_return (function, funaddr, value_type,
239                                        using_gcc);
240
241   /* Create a call sequence customized for this function
242      and the number of arguments for it.  */
243   bcopy (dummy, dummy1, sizeof dummy);
244   FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
245                   value_type, using_gcc);
246
247 #if CALL_DUMMY_LOCATION == ON_STACK
248   write_memory (start_sp, dummy1, sizeof dummy);
249
250 #else /* Not on stack.  */
251 #if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
252   /* Convex Unix prohibits executing in the stack segment. */
253   /* Hope there is empty room at the top of the text segment. */
254   {
255     static checked = 0;
256     if (!checked)
257       for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
258         if (read_memory_integer (start_sp, 1) != 0)
259           error ("text segment full -- no place to put call");
260     checked = 1;
261     sp = old_sp;
262     start_sp = text_end - sizeof dummy;
263     write_memory (start_sp, dummy1, sizeof dummy);
264   }
265 #else /* After text_end.  */
266   {
267     int errcode;
268     sp = old_sp;
269     start_sp = text_end;
270     errcode = target_write_memory (start_sp, dummy1, sizeof dummy);
271     if (errcode != 0)
272       error ("Cannot write text segment -- call_function failed");
273   }
274 #endif /* After text_end.  */
275 #endif /* Not on stack.  */
276
277 #ifdef STACK_ALIGN
278   /* If stack grows down, we must leave a hole at the top. */
279   {
280     int len = 0;
281
282     /* Reserve space for the return structure to be written on the
283        stack, if necessary */
284
285     if (struct_return)
286       len += TYPE_LENGTH (value_type);
287     
288     for (i = nargs - 1; i >= 0; i--)
289       len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
290 #ifdef CALL_DUMMY_STACK_ADJUST
291     len += CALL_DUMMY_STACK_ADJUST;
292 #endif
293 #if 1 INNER_THAN 2
294     sp -= STACK_ALIGN (len) - len;
295 #else
296     sp += STACK_ALIGN (len) - len;
297 #endif
298   }
299 #endif /* STACK_ALIGN */
300
301     /* Reserve space for the return structure to be written on the
302        stack, if necessary */
303
304     if (struct_return)
305       {
306 #if 1 INNER_THAN 2
307         sp -= TYPE_LENGTH (value_type);
308         struct_addr = sp;
309 #else
310         struct_addr = sp;
311         sp += TYPE_LENGTH (value_type);
312 #endif
313       }
314
315 #if defined (REG_STRUCT_HAS_ADDR)
316   {
317     /* This is a machine like the sparc, where we need to pass a pointer
318        to the structure, not the structure itself.  */
319     if (REG_STRUCT_HAS_ADDR (using_gcc))
320       for (i = nargs - 1; i >= 0; i--)
321         if (TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT)
322           {
323             CORE_ADDR addr;
324 #if !(1 INNER_THAN 2)
325             /* The stack grows up, so the address of the thing we push
326                is the stack pointer before we push it.  */
327             addr = sp;
328 #endif
329             /* Push the structure.  */
330             sp = value_push (sp, args[i]);
331 #if 1 INNER_THAN 2
332             /* The stack grows down, so the address of the thing we push
333                is the stack pointer after we push it.  */
334             addr = sp;
335 #endif
336             /* The value we're going to pass is the address of the thing
337                we just pushed.  */
338             args[i] = value_from_long (builtin_type_long, (LONGEST) addr);
339           }
340   }
341 #endif /* REG_STRUCT_HAS_ADDR.  */
342
343 #ifdef PUSH_ARGUMENTS
344   PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
345 #else /* !PUSH_ARGUMENTS */
346   for (i = nargs - 1; i >= 0; i--)
347     sp = value_arg_push (sp, args[i]);
348 #endif /* !PUSH_ARGUMENTS */
349
350 #ifdef CALL_DUMMY_STACK_ADJUST
351 #if 1 INNER_THAN 2
352   sp -= CALL_DUMMY_STACK_ADJUST;
353 #else
354   sp += CALL_DUMMY_STACK_ADJUST;
355 #endif
356 #endif /* CALL_DUMMY_STACK_ADJUST */
357
358   /* Store the address at which the structure is supposed to be
359      written.  Note that this (and the code which reserved the space
360      above) assumes that gcc was used to compile this function.  Since
361      it doesn't cost us anything but space and if the function is pcc
362      it will ignore this value, we will make that assumption.
363
364      Also note that on some machines (like the sparc) pcc uses a 
365      convention like gcc's.  */
366
367   if (struct_return)
368     STORE_STRUCT_RETURN (struct_addr, sp);
369
370   /* Write the stack pointer.  This is here because the statements above
371      might fool with it.  On SPARC, this write also stores the register
372      window into the right place in the new stack frame, which otherwise
373      wouldn't happen.  (See write_inferior_registers in sparc-xdep.c.)  */
374   write_register (SP_REGNUM, sp);
375
376   /* Figure out the value returned by the function.  */
377   {
378     char retbuf[REGISTER_BYTES];
379
380     /* Execute the stack dummy routine, calling FUNCTION.
381        When it is done, discard the empty frame
382        after storing the contents of all regs into retbuf.  */
383     run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
384
385     do_cleanups (old_chain);
386
387     return value_being_returned (value_type, retbuf, struct_return);
388   }
389 }
390 /* should return a value of some sort */
391  
392 value
393 vx_call_function (funcAddr, nargs, args, valueType)
394     char *funcAddr;
395     int nargs;
396     value *args;
397     struct type * valueType;
398 {
399     int i;
400     func_call funcInfo;
401     arg_value *argValue;
402     enum clnt_stat status;
403     register int len;
404     arg_value funcReturn;
405     value gdbValue;
406
407     argValue = (arg_value *) xmalloc (nargs * sizeof (arg_value));
408
409     bzero (argValue, nargs * sizeof (arg_value));
410     bzero (&funcReturn, sizeof (funcReturn));
411
412     for (i = nargs - 1; i >= 0; i--)
413         {
414         len = TYPE_LENGTH (VALUE_TYPE (args [i]));
415
416         switch (TYPE_CODE (VALUE_TYPE (args[i])))
417             {
418             /* XXX put other types here.  Where's CHAR, etc??? */
419
420             case TYPE_CODE_FLT:
421                 argValue[i].type = T_FLOAT;
422                 break;
423             case TYPE_CODE_INT:
424             case TYPE_CODE_PTR:
425             case TYPE_CODE_ENUM:
426             case TYPE_CODE_FUNC:
427                 argValue[i].type = T_INT;
428                 break;
429
430             case TYPE_CODE_UNDEF:
431             case TYPE_CODE_ARRAY:
432             case TYPE_CODE_STRUCT:
433             case TYPE_CODE_UNION:
434             case TYPE_CODE_VOID:
435             case TYPE_CODE_SET:
436             case TYPE_CODE_RANGE:
437             case TYPE_CODE_PASCAL_ARRAY:
438             case TYPE_CODE_MEMBER:          /* C++ */
439             case TYPE_CODE_METHOD:          /* C++ */
440             case TYPE_CODE_REF:             /* C++ */
441             default:
442                 error ("No corresponding VxWorks type for %d.  CHECK IT OUT!!!\n",
443                         TYPE_CODE(VALUE_TYPE(args[i])));
444             } /* switch */
445         if (TYPE_CODE(VALUE_TYPE(args[i])) == TYPE_CODE_FUNC)
446             argValue[i].arg_value_u.v_int = VALUE_ADDRESS(args[i]);
447         else
448             bcopy (VALUE_CONTENTS (args[i]), (char *) &argValue[i].arg_value_u,
449                    len);
450         }
451
452     /* XXX what should the type of this function addr be?
453      * XXX Both in gdb and vxWorks
454      */
455     funcInfo.func_addr = (int) funcAddr;
456     funcInfo.args.args_len = nargs;
457     funcInfo.args.args_val = argValue;
458
459     status = net_clnt_call (VX_CALL_FUNC, xdr_func_call, (char *) &funcInfo,
460                             xdr_arg_value, &funcReturn);
461
462     free ((char *) argValue);
463
464     if (status == RPC_SUCCESS)
465         {
466         /* XXX this assumes that vxWorks ALWAYS returns an int, and that
467          * XXX gdb isn't expecting anything more
468          */
469
470         /*******************
471         if (funcReturn.type == T_UNKNOWN)
472             return YYYXXX...;
473         *******************/
474         gdbValue = allocate_value (valueType);
475         bcopy (&funcReturn.arg_value_u.v_int, VALUE_CONTENTS (gdbValue),
476                 sizeof (int));
477         return gdbValue;
478         }
479     else 
480         error (rpcerr);
481     }
482 #endif /* FIXME */
483  
484 /* Start an inferior process and sets inferior_pid to its pid.
485    EXEC_FILE is the file to run.
486    ALLARGS is a string containing the arguments to the program.
487    ENV is the environment vector to pass.
488    Returns process id.  Errors reported with error().
489    On VxWorks, we ignore exec_file.  */
490  
491 void
492 vx_create_inferior (exec_file, args, env)
493      char *exec_file;
494      char *args;
495      char **env;
496 {
497   enum clnt_stat status;
498   arg_array passArgs;
499   TASK_START taskStart;
500
501   bzero ((char *) &passArgs, sizeof (passArgs));
502   bzero ((char *) &taskStart, sizeof (taskStart));
503
504   /* parse arguments, put them in passArgs */
505
506   parse_args (args, &passArgs);
507
508   if (passArgs.arg_array_len == 0)
509     error ("You must specify a function name to run, and arguments if any");
510
511   status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
512                           xdr_TASK_START, &taskStart);
513
514   if ((status != RPC_SUCCESS) || (taskStart.status == -1))
515     error ("Can't create process on remote target machine");
516
517   /* Save the name of the running function */
518   if (vx_running)
519     free (vx_running);
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 #else  /* I80960 */
711   bcopy (&inferior_registers, registers, 16 * 4);
712   *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
713   *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
714
715   if (target_has_fp)
716     {
717       ptrace_in.pid = inferior_pid;
718       ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
719       status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
720       if (status)
721         error (rpcerr);
722       if (ptrace_out.status == -1)
723         {
724           errno = ptrace_out.errno;
725           return -1;
726         }
727       
728       bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
729              sizeof inferior_fp_registers.fps_regs);
730       bcopy (&inferior_fp_registers.fps_control,
731          &registers[REGISTER_BYTE (FPC_REGNUM)],
732          sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
733     }
734   else
735     {
736       bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
737              sizeof inferior_fp_registers.fps_regs);
738       bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
739          sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
740     }
741 #endif
742   return 0;
743 }
744
745 /* Prepare to store registers.  Since we will store all of them,
746    read out their current values now.  */
747
748 void
749 vx_prepare_to_store ()
750 {
751   vx_read_register (-1);
752 }
753
754
755 /* Store our register values back into the inferior.
756    If REGNO is -1, do this for all registers.
757    Otherwise, REGNO specifies which register (so we can save time).  */
758    /* FIXME, look at REGNO to save time here */
759
760 vx_write_register (regno)
761      int regno;
762 {
763   struct regs inferior_registers;
764   struct fp_status inferior_fp_registers;
765   extern char registers[];
766   int status;
767   Rptrace ptrace_in;
768   Ptrace_return ptrace_out;
769
770   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
771   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
772
773   bcopy (registers, &inferior_registers, 16 * 4);
774   inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
775   inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
776   ptrace_in.pid = inferior_pid;
777   ptrace_in.info.ttype     = REGS;
778   ptrace_in.info.more_data = (caddr_t) &inferior_registers;
779
780   /* XXX change second param to be a proc number */
781   status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
782   if (status)
783       error (rpcerr);
784   if (ptrace_out.status == -1)
785     {
786       errno = ptrace_out.errno;
787       return -1;
788     }
789
790   if (target_has_fp)
791     {
792       bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
793              sizeof inferior_fp_registers.fps_regs);
794       bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
795          &inferior_fp_registers.fps_control,
796          sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
797
798       ptrace_in.pid = inferior_pid;
799       ptrace_in.info.ttype     = FPREGS;
800       ptrace_in.info.more_data = (caddr_t) &inferior_fp_registers;
801
802       status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in, &ptrace_out);
803       if (status)
804           error (rpcerr);
805       if (ptrace_out.status == -1)
806         {
807           errno = ptrace_out.errno;
808           return -1;
809         }
810     }
811   return 0;
812 }
813
814 /* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
815    to debugger memory starting at MYADDR.  WRITE is true if writing to the
816    inferior.
817    Result is the number of bytes written or read (zero if error).  The
818    protocol allows us to return a negative count, indicating that we can't
819    handle the current address but can handle one N bytes further, but
820    vxworks doesn't give us that information.  */
821
822 int
823 vx_xfer_memory (memaddr, myaddr, len, write)
824      CORE_ADDR memaddr;
825      char *myaddr;
826      int len;
827 {
828   int status;
829   Rptrace ptrace_in;
830   Ptrace_return ptrace_out;
831   C_bytes data;
832
833   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
834   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
835
836   ptrace_in.pid = inferior_pid;         /* XXX pid unnecessary for READDATA */
837   ptrace_in.addr = (int) memaddr;       /* Where from */
838   ptrace_in.data = len;                 /* How many bytes */
839
840   if (write)
841     {
842       ptrace_in.info.ttype     = DATA;
843       ptrace_in.info.more_data = (caddr_t) &data;
844
845       data.bytes = (caddr_t) myaddr;    /* Where from */
846       data.len   = len;                 /* How many bytes (again, for XDR) */
847
848       /* XXX change second param to be a proc number */
849       status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in, &ptrace_out);
850     }
851   else
852     {
853       ptrace_out.info.more_data = (caddr_t) &data;
854       data.bytes = myaddr;              /* Where to */
855       data.len   = len;                 /* How many (again, for XDR) */
856
857       /* XXX change second param to be a proc number */
858       status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
859     }
860
861   if (status)
862       error (rpcerr);
863   if (ptrace_out.status == -1)
864     {
865       return 0;         /* No bytes moved */
866     }
867   return len;           /* Moved *all* the bytes */
868 }
869
870 void
871 vx_files_info ()
872 {
873   printf ("\tAttached to host `%s'", vx_host);
874   printf (", which has %sfloating point", target_has_fp? "": "no ");
875   printf (".\n");
876 }
877
878 void
879 vx_run_files_info ()
880 {
881   printf ("\tRunning VxWorks process 0x%x, function `%s'.\n",
882           inferior_pid, vx_running);
883 }
884
885 void
886 vx_resume (step, siggnal)
887      int step;
888      int siggnal;
889 {
890   int status;
891   Rptrace ptrace_in;
892   Ptrace_return ptrace_out;
893
894   if (siggnal != 0)
895     error ("Cannot send signals to VxWorks processes");
896
897   bzero ((char *) &ptrace_in, sizeof (ptrace_in));
898   bzero ((char *) &ptrace_out, sizeof (ptrace_out));
899
900   ptrace_in.pid = inferior_pid;
901   ptrace_in.addr = 1;   /* Target side insists on this, or it panics.  */
902
903   /* XXX change second param to be a proc number */
904   status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
905                                  &ptrace_in, &ptrace_out);
906   if (status)
907       error (rpcerr);
908   if (ptrace_out.status == -1)
909     {
910       errno = ptrace_out.errno;
911       perror_with_name ("Resuming remote process");
912     }
913 }
914
915 void
916 vx_mourn_inferior ()
917 {
918   pop_target ();                /* Pop back to no-child state */
919   generic_mourn_inferior ();
920 }
921
922 \f
923 /* This function allows the addition of incrementally linked object files.  */
924
925 void
926 vx_add_file_command (arg_string, from_tty)
927      char* arg_string;
928      int from_tty;
929 {
930   CORE_ADDR text_addr;
931   CORE_ADDR data_addr;
932   CORE_ADDR bss_addr;
933   
934   if (arg_string == 0)
935     error ("add-file takes a file name in VxWorks");
936
937   arg_string = tilde_expand (arg_string);
938   make_cleanup (free, arg_string);
939
940   dont_repeat ();
941
942   if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
943     error ("Load failed on target machine");
944
945   /* FIXME, for now we ignore data_addr and bss_addr.  */
946   symbol_file_add (arg_string, from_tty, text_addr, 0);
947 }
948
949 #ifdef FIXME  /* Not ready for prime time */
950 /* Single step the target program at the source or machine level.
951    Takes an error exit if rpc fails.
952    Returns -1 if remote single-step operation fails, else 0.  */
953
954 static int
955 net_step ()
956 {
957   enum clnt_stat status;
958   int step_status;
959   SOURCE_STEP source_step;
960
961   source_step.taskId = inferior_pid;
962
963   if (step_range_end)
964     {
965       source_step.startAddr = step_range_start;
966       source_step.endAddr = step_range_end;
967     }
968   else
969     {
970       source_step.startAddr = 0;
971       source_step.endAddr = 0;
972     }
973
974   status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
975                           xdr_int, &step_status);
976
977   if (status == RPC_SUCCESS)
978     return step_status;
979   else 
980     error (rpcerr);
981 }
982 #endif
983
984 /* Emulate ptrace using RPC calls to the VxWorks target system.
985    Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise.  */
986
987 static int
988 net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
989     enum ptracereq request;
990     Rptrace *pPtraceIn;
991     Ptrace_return *pPtraceOut;
992 {
993   enum clnt_stat status;
994
995   status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
996                           pPtraceOut);
997
998   if (status != RPC_SUCCESS)
999       return -1;
1000
1001   return 0;
1002 }
1003
1004 /* Query the target for the name of the file from which VxWorks was
1005    booted.  pBootFile is the address of a pointer to the buffer to
1006    receive the file name; if the pointer pointed to by pBootFile is 
1007    NULL, memory for the buffer will be allocated by XDR.
1008    Returns -1 if rpc failed, 0 otherwise.  */
1009
1010 int
1011 net_get_boot_file (pBootFile)
1012      char **pBootFile;
1013 {
1014   enum clnt_stat status;
1015
1016   status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
1017                           xdr_wrapstring, pBootFile);
1018   return (status == RPC_SUCCESS) ? 0 : -1;
1019 }
1020
1021 /* Fetch a list of loaded object modules from the VxWorks target.
1022    Returns -1 if rpc failed, 0 otherwise
1023    There's no way to check if the returned loadTable is correct.
1024    VxWorks doesn't check it.  */
1025
1026 int
1027 net_get_symbols (pLoadTable)
1028      ldtabl *pLoadTable;                /* return pointer to ldtabl here */
1029 {
1030   enum clnt_stat status;
1031
1032   bzero ((char *) pLoadTable, sizeof (struct ldtabl));
1033
1034   status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
1035   return (status == RPC_SUCCESS) ? 0 : -1;
1036 }
1037
1038 /* Look up a symbol in the VxWorks target's symbol table.
1039    Returns status of symbol read on target side (0=success, -1=fail)
1040    Returns -1 and complain()s if rpc fails.  */
1041
1042 struct complaint cant_contact_target =
1043   {"Lost contact with VxWorks target", 0, 0};
1044
1045 int
1046 vx_lookup_symbol (name, pAddr)
1047      char *name;                /* symbol name */
1048      CORE_ADDR *pAddr;
1049 {
1050   enum clnt_stat status;
1051   SYMBOL_ADDR symbolAddr;
1052
1053   *pAddr = 0;
1054   bzero ((char *) &symbolAddr, sizeof (symbolAddr));
1055
1056   status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
1057                           xdr_SYMBOL_ADDR, &symbolAddr);
1058   if (status != RPC_SUCCESS) {
1059       complain (&cant_contact_target, 0);
1060       return -1;
1061   }
1062
1063   *pAddr = symbolAddr.addr;
1064   return symbolAddr.status;
1065 }
1066
1067 /* Check to see if the VxWorks target has a floating point coprocessor.
1068    Returns 1 if target has floating point processor, 0 otherwise.
1069    Calls error() if rpc fails.  */
1070
1071 int
1072 net_check_for_fp ()
1073 {
1074   enum clnt_stat status;
1075   bool_t fp = 0;        /* true if fp processor is present on target board */
1076
1077   status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
1078   if (status != RPC_SUCCESS)
1079       error (rpcerr);
1080
1081    return (int) fp;
1082 }
1083
1084 /* Establish an RPC connection with the VxWorks target system.
1085    Calls error () if unable to establish connection.  */
1086
1087 void
1088 net_connect (host)
1089      char *host;
1090 {
1091   struct sockaddr_in destAddr;
1092   struct hostent *destHost;
1093
1094   /* get the internet address for the given host */
1095
1096   if ((destHost = (struct hostent *) gethostbyname (host)) == NULL)
1097       error ("Invalid hostname.  Couldn't attach remote target.");
1098
1099   bzero (&destAddr, sizeof (destAddr));
1100
1101   destAddr.sin_addr.s_addr = * (u_long *) destHost->h_addr;
1102   destAddr.sin_family      = AF_INET;
1103   destAddr.sin_port        = 0; /* set to actual port that remote
1104                                    ptrace is listening on.  */
1105
1106   /* Create a tcp client transport on which to issue
1107      calls to the remote ptrace server.  */
1108
1109   ptraceSock = RPC_ANYSOCK;
1110   pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
1111   /* FIXME, here is where we deal with different version numbers of the proto */
1112   
1113   if (pClient == NULL)
1114     {
1115       clnt_pcreateerror ("\tnet_connect");
1116       error ("Couldn't connect to remote target.");
1117     }
1118 }
1119 \f
1120 /* Sleep for the specified number of milliseconds 
1121  * (assumed to be less than 1000).
1122  * If select () is interrupted, returns immediately;
1123  * takes an error exit if select () fails for some other reason.
1124  */
1125
1126 static void
1127 sleep_ms (ms)
1128      long ms;
1129 {
1130   struct timeval select_timeout;
1131   int status;
1132
1133   select_timeout.tv_sec = 0;
1134   select_timeout.tv_usec = ms * 1000;
1135
1136   status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
1137
1138   if (status < 0 && errno != EINTR)
1139     perror_with_name ("select");
1140 }
1141
1142 /* Wait for control to return from inferior to debugger.
1143    If inferior gets a signal, we may decide to start it up again
1144    instead of returning.  That is why there is a loop in this function.
1145    When this function actually returns it means the inferior
1146    should be left stopped and GDB should read more commands.  */
1147
1148 /* For network debugging with VxWorks.
1149  * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
1150  * so vx_wait() receives this information directly from
1151  * VxWorks instead of trying to figure out what happenned via a wait() call.
1152  */
1153
1154 static int
1155 vx_wait (status)
1156      int *status;
1157 {
1158   register int pid;
1159   WAITTYPE w;
1160   RDB_EVENT rdbEvent;
1161   int quit_failed;
1162
1163   do
1164     {
1165       /* If CTRL-C is hit during this loop,
1166          suspend the inferior process.  */
1167
1168       quit_failed = 0;
1169       if (quit_flag)
1170         {
1171           quit_failed = (net_quit () == -1);
1172           quit_flag = 0;
1173         }
1174
1175       /* If a net_quit () or net_wait () call has failed,
1176          allow the user to break the connection with the target.
1177          We can't simply error () out of this loop, since the 
1178          data structures representing the state of the inferior
1179          are in an inconsistent state.  */
1180
1181       if (quit_failed || net_wait (&rdbEvent) == -1)
1182         {
1183           terminal_ours ();
1184           if (query ("Can't %s.  Disconnect from target system? ",
1185                      (quit_failed) ? "suspend remote task"
1186                                    : "get status of remote task"))
1187             {
1188               target_mourn_inferior();
1189               error ("Use the \"target\" command to reconnect.");
1190             }
1191           else
1192             {
1193               terminal_inferior ();
1194               continue;
1195             }
1196         }
1197       
1198
1199       if (quit_failed || net_wait (&rdbEvent) == -1)
1200         {
1201           error ("Wait on remote target failed");
1202         }
1203       
1204       pid = rdbEvent.taskId;
1205       if (pid == 0)
1206         {
1207           sleep_ms (200);       /* FIXME Don't kill the network too badly */
1208         }
1209       else if (pid != inferior_pid)
1210         fatal ("Bad pid for debugged task: 0x%x\n", pid);
1211     } while (pid == 0);
1212
1213   /* FIXME, eventually do more then SIGTRAP on everything...  */
1214   switch (rdbEvent.eventType)
1215     {
1216     case EVENT_EXIT:
1217       WSETEXIT (w, 0);
1218       /* FIXME is it possible to distinguish between a
1219          XXX   normal vs abnormal exit in VxWorks? */
1220       break;
1221
1222     case EVENT_START:
1223       WSETSTOP (w, SIGTRAP);
1224       break;
1225
1226     case EVENT_STOP:
1227       WSETSTOP (w, SIGTRAP);
1228       /* XXX was it stopped by a signal?  act accordingly */
1229       break;
1230
1231     case EVENT_BREAK:
1232         /* Expecting a trace trap.  Stop the inferior and
1233          * return silently when it happens.  */
1234       WSETSTOP (w, SIGTRAP);
1235       break;
1236
1237     case EVENT_SUSPEND:
1238       target_terminal_ours_for_output ();
1239       printf ("\nRemote task suspended\n");  /* FIXME */
1240       fflush (stdout);
1241       WSETSTOP (w, SIGTRAP);
1242       break;
1243
1244     case EVENT_SIGNAL:
1245       /* The target is not running Unix, and its
1246          faults/traces do not map nicely into Unix signals.
1247          Make sure they do not get confused with Unix signals
1248          by numbering them with values higher than the highest
1249          legal Unix signal.  code in the arch-dependent PRINT_RANDOM_SIGNAL
1250          routine will interpret the value for wait_for_inferior.  */
1251       WSETSTOP (w, rdbEvent.sigType + NSIG);
1252       break;
1253     } /* switch */
1254   *status = *(int *)&w;         /* Grumble union wait crap Grumble */
1255   return pid;
1256 }
1257 \f
1258 static int
1259 symbol_stub (arg)
1260      int arg;
1261 {
1262   char *bootFile = (char *)arg;
1263   symbol_file_command (bootFile, 0);
1264   return 1;
1265 }
1266
1267 static int
1268 add_symbol_stub (arg)
1269      int arg;
1270 {
1271   struct ldfile *pLoadFile = (struct ldfile *)arg;
1272
1273   symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0);
1274   return 1;
1275 }
1276 /* Target command for VxWorks target systems.
1277
1278    Used in vxgdb.  Takes the name of a remote target machine
1279    running vxWorks and connects to it to initialize remote network
1280    debugging.  */
1281
1282 static void
1283 vx_open (args, from_tty)
1284      char *args;
1285      int from_tty;
1286 {
1287   extern int close ();
1288   char *bootFile;
1289   extern char *source_path;
1290   struct ldtabl loadTable;
1291   struct ldfile *pLoadFile;
1292   int i;
1293   extern CLIENT *pClient;
1294
1295   if (!args)
1296     error_no_arg ("target machine name");
1297
1298   target_preopen ();
1299   
1300   printf ("Attaching remote machine across net...\n");
1301   fflush (stdout);
1302
1303   /* Allow the user to kill the connect attempt by typing ^C.
1304      Wait until the call to target_has_fp () completes before
1305      disallowing an immediate quit, since even if net_connect ()
1306      is successful, the remote debug server might be hung.  */
1307
1308   immediate_quit++;
1309
1310   net_connect (args);
1311   target_has_fp = net_check_for_fp ();
1312   printf_filtered ("Connected to %s\n", args);
1313
1314   immediate_quit--;
1315
1316   push_target (&vx_ops);
1317
1318   /* Save a copy of the target host's name.  */
1319   if (vx_host)
1320     free (vx_host);
1321   vx_host = savestring (args, strlen (args));
1322
1323   /* Find out the name of the file from which the target was booted
1324      and load its symbol table.  */
1325
1326   bootFile = NULL;
1327   if (!net_get_boot_file (&bootFile))
1328     {
1329       if (*bootFile) {
1330         printf_filtered ("%s: ", bootFile);
1331         if (catch_errors (symbol_stub, (int)bootFile,
1332                 "Error reading symbols from boot file"))
1333           puts_filtered ("ok\n");
1334       } else if (from_tty)
1335         printf ("VxWorks kernel symbols not loaded.\n");
1336     }
1337   else
1338     error ("Can't retrieve boot file name from target machine.");
1339
1340   clnt_freeres (pClient, xdr_wrapstring, &bootFile);
1341
1342   if (net_get_symbols (&loadTable) != 0)
1343     error ("Can't read loaded modules from target machine");
1344
1345   i = 0-1;
1346   while (++i < loadTable.tbl_size)
1347     {
1348     QUIT;       /* FIXME, avoids clnt_freeres below:  mem leak */
1349     pLoadFile = &loadTable.tbl_ent [i];
1350 #ifdef WRS_ORIG
1351   {
1352     register int desc;
1353     struct cleanup *old_chain;
1354     char *fullname = NULL;
1355
1356     desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
1357     if (desc < 0)
1358         perror_with_name (pLoadFile->name);
1359     old_chain = make_cleanup (close, desc);
1360     add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
1361                       pLoadFile->bss_addr);
1362     do_cleanups (old_chain);
1363   }
1364 #else
1365     /* Botches, FIXME:
1366        (1)  Searches the PATH, not the source path.
1367        (2)  data and bss are assumed to be at the usual offsets from text.  */
1368     catch_errors (add_symbol_stub, (int)pLoadFile,
1369         "Error in reading symbols from loaded module.");
1370 #endif
1371     }
1372
1373   clnt_freeres (pClient, xdr_ldtabl, &loadTable);
1374
1375   if (from_tty)
1376     {
1377       puts_filtered ("Success!\n");
1378     }
1379 }
1380 \f
1381 /* Cross-net conversion of floats to and from extended form.
1382    (This is needed because different target machines have different
1383     extended floating point formats.)  */
1384
1385 /* Convert from an extended float to a double.
1386
1387    The extended float is stored as raw data pointed to by FROM.
1388    Return the converted value as raw data in the double pointed to by TO.
1389 */
1390
1391 static void
1392 vx_convert_to_virtual (regno, from, to)
1393     int regno;
1394     char *from;
1395     char *to;
1396 {
1397   enum clnt_stat status;
1398   ext_fp from_ext_fp;
1399   double to_double;
1400
1401   if (REGISTER_CONVERTIBLE (regno)) 
1402     {
1403       if (!target_has_fp) {
1404         *(double *)to = 0.0;    /* Skip the trouble if no float anyway */
1405         return;
1406       }
1407       bcopy (from, (char *) &from_ext_fp, sizeof (from_ext_fp));
1408       bzero ((char *) &to_double, sizeof (to_double));
1409
1410       status = net_clnt_call (VX_CONV_FROM_68881, xdr_ext_fp, &from_ext_fp,
1411                               xdr_double, &to_double);
1412       if (status == RPC_SUCCESS)
1413           bcopy ((char *) &to_double, to, sizeof (to_double));
1414       else
1415           error (rpcerr);
1416     }
1417   else
1418     bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
1419 }
1420
1421
1422 /* The converse:  convert from a double to an extended float.
1423
1424    The double is stored as raw data pointed to by FROM.
1425    Return the converted value as raw data in the extended
1426    float pointed to by TO.
1427 */
1428
1429 static void
1430 vx_convert_from_virtual (regno, from, to)
1431     int regno;
1432     char *from;
1433     char *to;
1434 {
1435   enum clnt_stat status;
1436   ext_fp to_ext_fp;
1437   double from_double;
1438
1439   if (REGISTER_CONVERTIBLE (regno)) 
1440     {
1441       if (!target_has_fp) {
1442         bzero (to, REGISTER_RAW_SIZE (FP0_REGNUM));     /* Shrug */
1443         return;
1444       }
1445       bcopy (from, (char *) &from_double, sizeof (from_double));
1446       bzero ((char *) &to_ext_fp, sizeof (to_ext_fp));
1447
1448       status = net_clnt_call (VX_CONV_TO_68881, xdr_double, &from_double,
1449                               xdr_ext_fp, &to_ext_fp);
1450       if (status == RPC_SUCCESS)
1451           bcopy ((char *) &to_ext_fp, to, sizeof (to_ext_fp));
1452       else
1453           error (rpcerr);
1454     }
1455   else
1456     bcopy (from, to, REGISTER_VIRTUAL_SIZE (regno));
1457 }
1458 \f
1459 /* Make an RPC call to the VxWorks target.
1460    Returns RPC status.  */
1461
1462 static enum clnt_stat
1463 net_clnt_call (procNum, inProc, in, outProc, out)
1464     enum ptracereq procNum;
1465     xdrproc_t inProc;
1466     char *in;
1467     xdrproc_t outProc;
1468     char *out;
1469 {
1470   enum clnt_stat status;
1471   
1472   status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
1473
1474   if (status != RPC_SUCCESS)
1475       clnt_perrno (status);
1476
1477   return status;
1478 }
1479
1480 /* A vxprocess target should be started via "run" not "target".  */
1481 /*ARGSUSED*/
1482 static void
1483 vx_proc_open (name, from_tty)
1484      char *name;
1485      int from_tty;
1486 {
1487   error ("Use the \"run\" command to start a VxWorks process.");
1488 }
1489
1490
1491 /* Target ops structure for accessing memory and such over the net */
1492
1493 struct target_ops vx_ops = {
1494         "vxworks", "VxWorks target memory via RPC over TCP/IP",
1495         "Use VxWorks target memory.  \n\
1496 Specify the name of the machine to connect to.",
1497         vx_open, 0, /* vx_detach, */
1498         0, 0, /* resume, wait */
1499         0, 0, /* read_reg, write_reg */
1500         0, vx_convert_to_virtual, vx_convert_from_virtual,  /* prep_to_store, */
1501         vx_xfer_memory, vx_files_info,
1502         0, 0, /* insert_breakpoint, remove_breakpoint */
1503         0, 0, 0, 0, 0,  /* terminal stuff */
1504         0, /* vx_kill, */
1505         vx_add_file_command,
1506         call_function_by_hand,  /* FIXME, calling fns is maybe botched? */
1507         vx_lookup_symbol,
1508         vx_create_inferior, 0,  /* mourn_inferior */
1509         core_stratum, 0, /* next */
1510         1, 1, 0, 0, 0,  /* all mem, mem, stack, regs, exec */
1511         OPS_MAGIC,              /* Always the last thing */
1512 };
1513
1514 /* Target ops structure for accessing VxWorks child processes over the net */
1515
1516 struct target_ops vx_run_ops = {
1517         "vxprocess", "VxWorks process",
1518         "VxWorks process, started by the \"run\" command.",
1519         vx_proc_open, 0, /* vx_detach, */
1520         vx_resume, vx_wait,
1521         vx_read_register, vx_write_register,
1522         vx_prepare_to_store, vx_convert_to_virtual, vx_convert_from_virtual,
1523         vx_xfer_memory, vx_run_files_info,
1524         vx_insert_breakpoint, vx_remove_breakpoint,
1525         0, 0, 0, 0, 0,  /* terminal stuff */
1526         0, /* vx_kill, */
1527         vx_add_file_command,
1528         call_function_by_hand,  /* FIXME, calling fns is maybe botched? */
1529         vx_lookup_symbol,
1530         vx_create_inferior, vx_mourn_inferior,
1531         process_stratum, 0, /* next */
1532         1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
1533         OPS_MAGIC,              /* Always the last thing */
1534 };
1535 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
1536 \f
1537 void
1538 _initialize_vx ()
1539 {
1540   add_target (&vx_ops);
1541   add_target (&vx_run_ops);
1542 }
This page took 0.107775 seconds and 4 git commands to generate.