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