* inferior.h: Eliminate CANNOT_EXECUTE_STACK in favor of
[deliverable/binutils-gdb.git] / gdb / remote-vx.68.c
CommitLineData
07d021a6
JG
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
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
JG
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
55extern value call_function_by_hand ();
56extern void symbol_file_command ();
57extern int stop_soon_quietly; /* for wait_for_inferior */
58
59static int net_ptrace_clnt_call (); /* Forward decl */
60static enum clnt_stat net_clnt_call (); /* Forward decl */
61extern 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
66static char *vx_host;
67static char *vx_running;
68
69/* Nonzero means target that is being debugged remotely has a floating
70 point processor. */
71
72static int target_has_fp;
73
74/* Default error message when the network is forking up. */
75
76static const char rpcerr[] = "network target debugging: rpc error";
77
78CLIENT *pClient; /* client used in net debugging */
79static int ptraceSock = RPC_ANYSOCK;
80extern int errno;
81
82enum clnt_stat net_clnt_call();
83static void parse_args ();
84
85static struct timeval rpcTimeout = { 10, 0 };
86
87static char *skip_white_space ();
88static 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
95static int
96net_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
135static int
136net_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
164int
165vx_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
173int
174vx_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. */
189value
190vx_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
392value
393vx_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
491void
492vx_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
559static void
560parse_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
601static char *
602skip_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
614static char *
615find_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
641int
642net_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
659int
660net_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
681int
682vx_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
748void
749vx_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
760vx_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
822int
823vx_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
870void
871vx_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
878void
879vx_run_files_info ()
880{
881 printf ("\tRunning VxWorks process 0x%x, function `%s'.\n",
882 inferior_pid, vx_running);
883}
884
885void
886vx_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
915void
916vx_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
925void
926vx_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
954static int
955net_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
987static int
988net_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
1010int
1011net_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
1026int
1027net_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
1042struct complaint cant_contact_target =
1043 {"Lost contact with VxWorks target", 0, 0};
1044
1045int
1046vx_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
1071int
1072net_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
1087void
1088net_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
1126static void
1127sleep_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
1154static int
1155vx_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
1258static int
1259symbol_stub (arg)
1260 int arg;
1261{
1262 char *bootFile = (char *)arg;
1263 symbol_file_command (bootFile, 0);
1264 return 1;
1265}
1266
1267static int
1268add_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
1282static void
1283vx_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
70dcc196
JK
1298 target_preopen ();
1299
07d021a6
JG
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
1391static void
1392vx_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
1429static void
1430vx_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
1462static enum clnt_stat
1463net_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
70dcc196
JK
1480/* A vxprocess target should be started via "run" not "target". */
1481/*ARGSUSED*/
1482static void
1483vx_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
07d021a6
JG
1490
1491/* Target ops structure for accessing memory and such over the net */
1492
1493struct target_ops vx_ops = {
1494 "vxworks", "VxWorks target memory via RPC over TCP/IP",
70dcc196
JK
1495 "Use VxWorks target memory. \n\
1496Specify the name of the machine to connect to.",
07d021a6
JG
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
1516struct target_ops vx_run_ops = {
1517 "vxprocess", "VxWorks process",
70dcc196
JK
1518 "VxWorks process, started by the \"run\" command.",
1519 vx_proc_open, 0, /* vx_detach, */
07d021a6
JG
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
1537void
1538_initialize_vx ()
1539{
1540 add_target (&vx_ops);
1541 add_target (&vx_run_ops);
1542}
This page took 0.169847 seconds and 4 git commands to generate.