* xm-sun3os4.h, xm-sun4os4.h: Enable HAVE_MMAP.
[deliverable/binutils-gdb.git] / gdb / remote-vx.68.c
1 /* Memory-access and commands for remote VxWorks processes, for GDB.
2 Copyright 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 #define TM_FILE_OVERRIDE
22 #include "defs.h"
23 #include "tm-vxworks68.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 void symbol_file_command ();
56 extern int stop_soon_quietly; /* for wait_for_inferior */
57
58 static int net_ptrace_clnt_call (); /* Forward decl */
59 static enum clnt_stat net_clnt_call (); /* Forward decl */
60 extern struct target_ops vx_ops, vx_run_ops; /* Forward declaration */
61
62 /* Saved name of target host and called function for "info files".
63 Both malloc'd. */
64
65 static char *vx_host;
66 static char *vx_running;
67
68 /* Nonzero means target that is being debugged remotely has a floating
69 point processor. */
70
71 static int target_has_fp;
72
73 /* Default error message when the network is forking up. */
74
75 static const char rpcerr[] = "network target debugging: rpc error";
76
77 CLIENT *pClient; /* client used in net debugging */
78 static int ptraceSock = RPC_ANYSOCK;
79 extern int errno;
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 load_timeout.tv_sec = 0x7FFF7FFF; /* A large number, effectively inf. */
114 load_timeout.tv_usec = 0;
115
116 status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
117 &ldstruct, load_timeout);
118
119 if (status == RPC_SUCCESS)
120 {
121 if (*ldstruct.name == NULL) /* load failed on VxWorks side */
122 return -1;
123 *pTextAddr = ldstruct.txt_addr;
124 *pDataAddr = ldstruct.data_addr;
125 *pBssAddr = ldstruct.bss_addr;
126 return 0;
127 }
128 else
129 return -1;
130 }
131
132 /* returns 0 if successful, errno if RPC failed or VxWorks complains. */
133
134 static int
135 net_break (addr, procnum)
136 int addr;
137 u_long procnum;
138 {
139 enum clnt_stat status;
140 int break_status;
141 Rptrace ptrace_in; /* XXX This is stupid. It doesn't need to be a ptrace
142 structure. How about something smaller? */
143
144 bzero ((char *) &ptrace_in, sizeof (ptrace_in));
145 break_status = 0;
146
147 ptrace_in.addr = addr;
148 ptrace_in.pid = inferior_pid;
149
150 status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
151 &break_status);
152
153 if (status != RPC_SUCCESS)
154 return errno;
155
156 if (break_status == -1)
157 return ENOMEM;
158 return break_status; /* probably (FIXME) zero */
159 }
160
161 /* returns 0 if successful, errno otherwise */
162
163 int
164 vx_insert_breakpoint (addr)
165 int addr;
166 {
167 return net_break (addr, VX_BREAK_ADD);
168 }
169
170 /* returns 0 if successful, errno otherwise */
171
172 int
173 vx_remove_breakpoint (addr)
174 int addr;
175 {
176 return net_break (addr, VX_BREAK_DELETE);
177 }
178
179 /* Call a function on the VxWorks target system.
180 ARGS is a vector of values of arguments (NARGS of them).
181 FUNCTION is a value, the function to be called.
182 Returns a struct value * representing what the function returned.
183 May fail to return, if a breakpoint or signal is hit
184 during the execution of the function. */
185
186 #ifdef FIXME
187 /* FIXME, function calls are really fried. GO back to manual method. */
188 value
189 call_function (function, nargs, args)
190 value function;
191 int nargs;
192 value *args;
193 {
194 register CORE_ADDR sp;
195 register int i;
196 CORE_ADDR start_sp;
197 static REGISTER_TYPE dummy[] = CALL_DUMMY;
198 REGISTER_TYPE dummy1[sizeof dummy / sizeof (REGISTER_TYPE)];
199 CORE_ADDR old_sp;
200 struct type *value_type;
201 unsigned char struct_return;
202 CORE_ADDR struct_addr;
203 struct inferior_status inf_status;
204 struct cleanup *old_chain;
205 CORE_ADDR funaddr;
206 int using_gcc;
207
208 save_inferior_status (&inf_status, 1);
209 old_chain = make_cleanup (restore_inferior_status, &inf_status);
210
211 /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
212 (and POP_FRAME for restoring them). (At least on most machines)
213 they are saved on the stack in the inferior. */
214 PUSH_DUMMY_FRAME;
215
216 old_sp = sp = read_register (SP_REGNUM);
217
218 #if 1 INNER_THAN 2 /* Stack grows down */
219 sp -= sizeof dummy;
220 start_sp = sp;
221 #else /* Stack grows up */
222 start_sp = sp;
223 sp += sizeof dummy;
224 #endif
225
226 funaddr = find_function_addr (function, &value_type);
227
228 {
229 struct block *b = block_for_pc (funaddr);
230 /* If compiled without -g, assume GCC. */
231 using_gcc = b == NULL || BLOCK_GCC_COMPILED (b);
232 }
233
234 /* Are we returning a value using a structure return or a normal
235 value return? */
236
237 struct_return = using_struct_return (function, funaddr, value_type,
238 using_gcc);
239
240 /* Create a call sequence customized for this function
241 and the number of arguments for it. */
242 bcopy (dummy, dummy1, sizeof dummy);
243 FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
244 value_type, using_gcc);
245
246 #if CALL_DUMMY_LOCATION == ON_STACK
247 write_memory (start_sp, dummy1, sizeof dummy);
248
249 #else /* Not on stack. */
250 #if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
251 /* Convex Unix prohibits executing in the stack segment. */
252 /* Hope there is empty room at the top of the text segment. */
253 {
254 static checked = 0;
255 if (!checked)
256 for (start_sp = text_end - sizeof dummy; start_sp < text_end; ++start_sp)
257 if (read_memory_integer (start_sp, 1) != 0)
258 error ("text segment full -- no place to put call");
259 checked = 1;
260 sp = old_sp;
261 start_sp = text_end - sizeof dummy;
262 write_memory (start_sp, dummy1, sizeof dummy);
263 }
264 #else /* After text_end. */
265 {
266 int errcode;
267 sp = old_sp;
268 start_sp = text_end;
269 errcode = target_write_memory (start_sp, dummy1, sizeof dummy);
270 if (errcode != 0)
271 error ("Cannot write text segment -- vx_call_function failed");
272 }
273 #endif /* After text_end. */
274 #endif /* Not on stack. */
275
276 #ifdef STACK_ALIGN
277 /* If stack grows down, we must leave a hole at the top. */
278 {
279 int len = 0;
280
281 /* Reserve space for the return structure to be written on the
282 stack, if necessary */
283
284 if (struct_return)
285 len += TYPE_LENGTH (value_type);
286
287 for (i = nargs - 1; i >= 0; i--)
288 len += TYPE_LENGTH (VALUE_TYPE (value_arg_coerce (args[i])));
289 #ifdef CALL_DUMMY_STACK_ADJUST
290 len += CALL_DUMMY_STACK_ADJUST;
291 #endif
292 #if 1 INNER_THAN 2
293 sp -= STACK_ALIGN (len) - len;
294 #else
295 sp += STACK_ALIGN (len) - len;
296 #endif
297 }
298 #endif /* STACK_ALIGN */
299
300 /* Reserve space for the return structure to be written on the
301 stack, if necessary */
302
303 if (struct_return)
304 {
305 #if 1 INNER_THAN 2
306 sp -= TYPE_LENGTH (value_type);
307 struct_addr = sp;
308 #else
309 struct_addr = sp;
310 sp += TYPE_LENGTH (value_type);
311 #endif
312 }
313
314 #if defined (REG_STRUCT_HAS_ADDR)
315 {
316 /* This is a machine like the sparc, where we need to pass a pointer
317 to the structure, not the structure itself. */
318 if (REG_STRUCT_HAS_ADDR (using_gcc))
319 for (i = nargs - 1; i >= 0; i--)
320 if ( TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_STRUCT
321 || TYPE_CODE (VALUE_TYPE (args[i])) == TYPE_CODE_UNION)
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 vx_lookup_symbol,
1507 vx_create_inferior, 0, /* mourn_inferior */
1508 core_stratum, 0, /* next */
1509 1, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */
1510 OPS_MAGIC, /* Always the last thing */
1511 };
1512
1513 /* Target ops structure for accessing VxWorks child processes over the net */
1514
1515 struct target_ops vx_run_ops = {
1516 "vxprocess", "VxWorks process",
1517 "VxWorks process, started by the \"run\" command.",
1518 vx_proc_open, 0, /* vx_detach, */
1519 vx_resume, vx_wait,
1520 vx_read_register, vx_write_register,
1521 vx_prepare_to_store, vx_convert_to_virtual, vx_convert_from_virtual,
1522 vx_xfer_memory, vx_run_files_info,
1523 vx_insert_breakpoint, vx_remove_breakpoint,
1524 0, 0, 0, 0, 0, /* terminal stuff */
1525 0, /* vx_kill, */
1526 vx_add_file_command,
1527 vx_lookup_symbol,
1528 vx_create_inferior, vx_mourn_inferior,
1529 process_stratum, 0, /* next */
1530 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1531 OPS_MAGIC, /* Always the last thing */
1532 };
1533 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
1534 \f
1535 void
1536 _initialize_vx ()
1537 {
1538 add_target (&vx_ops);
1539 add_target (&vx_run_ops);
1540 }
This page took 0.061293 seconds and 4 git commands to generate.