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.
5 This file is part of GDB.
7 GDB 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 1, or (at your option)
12 GDB 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.
17 You should have received a copy of the GNU General Public License
18 along with GDB; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include "tm-vxworks68.h"
23 #include "param-no-tm.h"
31 #include "symfile.h" /* for struct complaint */
38 #include <sys/types.h>
40 #include <sys/socket.h>
41 #define free bogon_free /* Sun claims "int free()" not void */
46 #include "xdr_ptrace.h"
49 #include "dbgRpcLib.h"
51 /* get rid of value.h if possible */
55 extern value
call_function_by_hand ();
56 extern void symbol_file_command ();
57 extern int stop_soon_quietly
; /* for wait_for_inferior */
59 static int net_ptrace_clnt_call (); /* Forward decl */
60 static enum clnt_stat
net_clnt_call (); /* Forward decl */
61 extern struct target_ops vx_ops
, vx_run_ops
; /* Forward declaration */
63 /* Saved name of target host and called function for "info files".
67 static char *vx_running
;
69 /* Nonzero means target that is being debugged remotely has a floating
72 static int target_has_fp
;
74 /* Default error message when the network is forking up. */
76 static const char rpcerr
[] = "network target debugging: rpc error";
78 CLIENT
*pClient
; /* client used in net debugging */
79 static int ptraceSock
= RPC_ANYSOCK
;
82 enum clnt_stat
net_clnt_call();
83 static void parse_args ();
85 static struct timeval rpcTimeout
= { 10, 0 };
87 static char *skip_white_space ();
88 static char *find_white_space ();
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. */
96 net_load (filename
, pTextAddr
, pDataAddr
, pBssAddr
)
102 enum clnt_stat status
;
103 struct ldfile ldstruct
;
104 struct timeval load_timeout
;
106 bzero ((char *) &ldstruct
, sizeof (ldstruct
));
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. */
114 load_timeout
.tv_sec
= 0x7FFF7FFF; /* A large number, effectively inf. */
115 load_timeout
.tv_usec
= 0;
117 status
= clnt_call (pClient
, VX_LOAD
, xdr_wrapstring
, &filename
, xdr_ldfile
,
118 &ldstruct
, load_timeout
);
120 if (status
== RPC_SUCCESS
)
122 if (*ldstruct
.name
== NULL
) /* load failed on VxWorks side */
124 *pTextAddr
= ldstruct
.txt_addr
;
125 *pDataAddr
= ldstruct
.data_addr
;
126 *pBssAddr
= ldstruct
.bss_addr
;
133 /* returns 0 if successful, errno if RPC failed or VxWorks complains. */
136 net_break (addr
, procnum
)
140 enum clnt_stat status
;
142 Rptrace ptrace_in
; /* XXX This is stupid. It doesn't need to be a ptrace
143 structure. How about something smaller? */
145 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
148 ptrace_in
.addr
= addr
;
149 ptrace_in
.pid
= inferior_pid
;
151 status
= net_clnt_call (procnum
, xdr_rptrace
, &ptrace_in
, xdr_int
,
154 if (status
!= RPC_SUCCESS
)
157 if (break_status
== -1)
159 return break_status
; /* probably (FIXME) zero */
162 /* returns 0 if successful, errno otherwise */
165 vx_insert_breakpoint (addr
)
168 return net_break (addr
, VX_BREAK_ADD
);
171 /* returns 0 if successful, errno otherwise */
174 vx_remove_breakpoint (addr
)
177 return net_break (addr
, VX_BREAK_DELETE
);
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. */
188 /* FIXME, function calls are really fried. GO back to manual method. */
190 vx_call_function (function
, nargs
, args
)
195 register CORE_ADDR sp
;
198 static REGISTER_TYPE dummy
[] = CALL_DUMMY
;
199 REGISTER_TYPE dummy1
[sizeof dummy
/ sizeof (REGISTER_TYPE
)];
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
;
209 save_inferior_status (&inf_status
, 1);
210 old_chain
= make_cleanup (restore_inferior_status
, &inf_status
);
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. */
217 old_sp
= sp
= read_register (SP_REGNUM
);
219 #if 1 INNER_THAN 2 /* Stack grows down */
222 #else /* Stack grows up */
227 funaddr
= find_function_addr (function
, &value_type
);
230 struct block
*b
= block_for_pc (funaddr
);
231 /* If compiled without -g, assume GCC. */
232 using_gcc
= b
== NULL
|| BLOCK_GCC_COMPILED (b
);
235 /* Are we returning a value using a structure return or a normal
238 struct_return
= using_struct_return (function
, funaddr
, value_type
,
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
);
247 #if CALL_DUMMY_LOCATION == ON_STACK
248 write_memory (start_sp
, dummy1
, sizeof dummy
);
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. */
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");
262 start_sp
= text_end
- sizeof dummy
;
263 write_memory (start_sp
, dummy1
, sizeof dummy
);
265 #else /* After text_end. */
270 errcode
= target_write_memory (start_sp
, dummy1
, sizeof dummy
);
272 error ("Cannot write text segment -- call_function failed");
274 #endif /* After text_end. */
275 #endif /* Not on stack. */
278 /* If stack grows down, we must leave a hole at the top. */
282 /* Reserve space for the return structure to be written on the
283 stack, if necessary */
286 len
+= TYPE_LENGTH (value_type
);
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
;
294 sp
-= STACK_ALIGN (len
) - len
;
296 sp
+= STACK_ALIGN (len
) - len
;
299 #endif /* STACK_ALIGN */
301 /* Reserve space for the return structure to be written on the
302 stack, if necessary */
307 sp
-= TYPE_LENGTH (value_type
);
311 sp
+= TYPE_LENGTH (value_type
);
315 #if defined (REG_STRUCT_HAS_ADDR)
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
)
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. */
329 /* Push the structure. */
330 sp
= value_push (sp
, args
[i
]);
332 /* The stack grows down, so the address of the thing we push
333 is the stack pointer after we push it. */
336 /* The value we're going to pass is the address of the thing
338 args
[i
] = value_from_long (builtin_type_long
, (LONGEST
) addr
);
341 #endif /* REG_STRUCT_HAS_ADDR. */
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 */
350 #ifdef CALL_DUMMY_STACK_ADJUST
352 sp
-= CALL_DUMMY_STACK_ADJUST
;
354 sp
+= CALL_DUMMY_STACK_ADJUST
;
356 #endif /* CALL_DUMMY_STACK_ADJUST */
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.
364 Also note that on some machines (like the sparc) pcc uses a
365 convention like gcc's. */
368 STORE_STRUCT_RETURN (struct_addr
, sp
);
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
);
376 /* Figure out the value returned by the function. */
378 char retbuf
[REGISTER_BYTES
];
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
);
385 do_cleanups (old_chain
);
387 return value_being_returned (value_type
, retbuf
, struct_return
);
390 /* should return a value of some sort */
393 vx_call_function (funcAddr
, nargs
, args
, valueType
)
397 struct type
* valueType
;
402 enum clnt_stat status
;
404 arg_value funcReturn
;
407 argValue
= (arg_value
*) xmalloc (nargs
* sizeof (arg_value
));
409 bzero (argValue
, nargs
* sizeof (arg_value
));
410 bzero (&funcReturn
, sizeof (funcReturn
));
412 for (i
= nargs
- 1; i
>= 0; i
--)
414 len
= TYPE_LENGTH (VALUE_TYPE (args
[i
]));
416 switch (TYPE_CODE (VALUE_TYPE (args
[i
])))
418 /* XXX put other types here. Where's CHAR, etc??? */
421 argValue
[i
].type
= T_FLOAT
;
427 argValue
[i
].type
= T_INT
;
430 case TYPE_CODE_UNDEF
:
431 case TYPE_CODE_ARRAY
:
432 case TYPE_CODE_STRUCT
:
433 case TYPE_CODE_UNION
:
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++ */
442 error ("No corresponding VxWorks type for %d. CHECK IT OUT!!!\n",
443 TYPE_CODE(VALUE_TYPE(args
[i
])));
445 if (TYPE_CODE(VALUE_TYPE(args
[i
])) == TYPE_CODE_FUNC
)
446 argValue
[i
].arg_value_u
.v_int
= VALUE_ADDRESS(args
[i
]);
448 bcopy (VALUE_CONTENTS (args
[i
]), (char *) &argValue
[i
].arg_value_u
,
452 /* XXX what should the type of this function addr be?
453 * XXX Both in gdb and vxWorks
455 funcInfo
.func_addr
= (int) funcAddr
;
456 funcInfo
.args
.args_len
= nargs
;
457 funcInfo
.args
.args_val
= argValue
;
459 status
= net_clnt_call (VX_CALL_FUNC
, xdr_func_call
, (char *) &funcInfo
,
460 xdr_arg_value
, &funcReturn
);
462 free ((char *) argValue
);
464 if (status
== RPC_SUCCESS
)
466 /* XXX this assumes that vxWorks ALWAYS returns an int, and that
467 * XXX gdb isn't expecting anything more
471 if (funcReturn.type == T_UNKNOWN)
474 gdbValue
= allocate_value (valueType
);
475 bcopy (&funcReturn
.arg_value_u
.v_int
, VALUE_CONTENTS (gdbValue
),
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. */
492 vx_create_inferior (exec_file
, args
, env
)
497 enum clnt_stat status
;
499 TASK_START taskStart
;
501 bzero ((char *) &passArgs
, sizeof (passArgs
));
502 bzero ((char *) &taskStart
, sizeof (taskStart
));
504 /* parse arguments, put them in passArgs */
506 parse_args (args
, &passArgs
);
508 if (passArgs
.arg_array_len
== 0)
509 error ("You must specify a function name to run, and arguments if any");
511 status
= net_clnt_call (PROCESS_START
, xdr_arg_array
, &passArgs
,
512 xdr_TASK_START
, &taskStart
);
514 if ((status
!= RPC_SUCCESS
) || (taskStart
.status
== -1))
515 error ("Can't create process on remote target machine");
517 /* Save the name of the running function */
520 vx_running
= savestring (passArgs
.arg_array_val
[0],
521 strlen (passArgs
.arg_array_val
[0]));
523 #ifdef CREATE_INFERIOR_HOOK
524 CREATE_INFERIOR_HOOK (pid
);
527 push_target (&vx_run_ops
);
528 inferior_pid
= taskStart
.pid
;
530 #if defined (START_INFERIOR_HOOK)
531 START_INFERIOR_HOOK ();
534 /* We will get a trace trap after one instruction.
535 Insert breakpoints and continue. */
537 init_wait_for_inferior ();
539 /* Set up the "saved terminal modes" of the inferior
540 based on what modes we are starting it with. */
541 target_terminal_init ();
543 /* Install inferior's terminal modes. */
544 target_terminal_inferior ();
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;
552 /* insert_step_breakpoint (); FIXME, do we need this? */
556 /* Fill ARGSTRUCT in argc/argv form with the arguments from the
557 argument string ARGSTRING. */
560 parse_args (arg_string
, arg_struct
)
561 register char *arg_string
;
562 arg_array
*arg_struct
;
564 register int arg_count
= 0; /* number of arguments */
565 register int arg_index
= 0;
568 bzero ((char *) arg_struct
, sizeof (arg_array
));
570 /* first count how many arguments there are */
575 if (*(p0
= skip_white_space (p0
)) == '\0')
577 p0
= find_white_space (p0
);
581 arg_struct
->arg_array_len
= arg_count
;
582 arg_struct
->arg_array_val
= (char **) xmalloc ((arg_count
+ 1)
585 /* now copy argument strings into arg_struct. */
587 while (*(arg_string
= skip_white_space (arg_string
)))
589 p0
= find_white_space (arg_string
);
590 arg_struct
->arg_array_val
[arg_index
++] = savestring (arg_string
,
595 arg_struct
->arg_array_val
[arg_count
] = NULL
;
598 /* Advance a string pointer across whitespace and return a pointer
599 to the first non-white character. */
605 while (*p
== ' ' || *p
== '\t')
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. */
620 while ((c
= *p
) != ' ' && c
!= '\t' && c
)
622 if (c
== '\'' || c
== '"')
624 while (*++p
!= c
&& *p
)
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. */
646 enum clnt_stat status
;
648 bzero ((char *) pEvent
, sizeof (RDB_EVENT
));
651 status
= net_clnt_call (PROCESS_WAIT
, xdr_int
, &pid
, xdr_RDB_EVENT
, pEvent
);
653 return (status
== RPC_SUCCESS
)? pEvent
->status
: -1;
656 /* Suspend the remote task.
657 Returns -1 if suspend fails on target system, 0 otherwise. */
664 enum clnt_stat status
;
668 /* don't let rdbTask suspend itself by passing a pid of 0 */
670 if ((pid
= inferior_pid
) == 0)
673 status
= net_clnt_call (VX_TASK_SUSPEND
, xdr_int
, &pid
, xdr_int
,
676 return (status
== RPC_SUCCESS
)? quit_status
: -1;
679 /* Read a register or registers from the remote system. */
682 vx_read_register (regno
)
687 Ptrace_return ptrace_out
;
688 struct regs inferior_registers
;
689 struct fp_status inferior_fp_registers
;
690 extern char registers
[];
692 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
693 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
695 /* FIXME, eventually only get the ones we need. */
696 registers_fetched ();
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
);
703 if (ptrace_out
.status
== -1)
705 errno
= ptrace_out
.errno
;
711 bcopy (&inferior_registers
, registers
, 16 * 4);
712 *(int *)®isters
[REGISTER_BYTE (PS_REGNUM
)] = inferior_registers
.r_ps
;
713 *(int *)®isters
[REGISTER_BYTE (PC_REGNUM
)] = inferior_registers
.r_pc
;
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
);
722 if (ptrace_out
.status
== -1)
724 errno
= ptrace_out
.errno
;
728 bcopy (&inferior_fp_registers
, ®isters
[REGISTER_BYTE (FP0_REGNUM
)],
729 sizeof inferior_fp_registers
.fps_regs
);
730 bcopy (&inferior_fp_registers
.fps_control
,
731 ®isters
[REGISTER_BYTE (FPC_REGNUM
)],
732 sizeof inferior_fp_registers
- sizeof inferior_fp_registers
.fps_regs
);
736 bzero (®isters
[REGISTER_BYTE (FP0_REGNUM
)],
737 sizeof inferior_fp_registers
.fps_regs
);
738 bzero (®isters
[REGISTER_BYTE (FPC_REGNUM
)],
739 sizeof inferior_fp_registers
- sizeof inferior_fp_registers
.fps_regs
);
745 /* Prepare to store registers. Since we will store all of them,
746 read out their current values now. */
749 vx_prepare_to_store ()
751 vx_read_register (-1);
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 */
760 vx_write_register (regno
)
763 struct regs inferior_registers
;
764 struct fp_status inferior_fp_registers
;
765 extern char registers
[];
768 Ptrace_return ptrace_out
;
770 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
771 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
773 bcopy (registers
, &inferior_registers
, 16 * 4);
774 inferior_registers
.r_ps
= *(int *)®isters
[REGISTER_BYTE (PS_REGNUM
)];
775 inferior_registers
.r_pc
= *(int *)®isters
[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
;
780 /* XXX change second param to be a proc number */
781 status
= net_ptrace_clnt_call (PTRACE_SETREGS
, &ptrace_in
, &ptrace_out
);
784 if (ptrace_out
.status
== -1)
786 errno
= ptrace_out
.errno
;
792 bcopy (®isters
[REGISTER_BYTE (FP0_REGNUM
)], &inferior_fp_registers
,
793 sizeof inferior_fp_registers
.fps_regs
);
794 bcopy (®isters
[REGISTER_BYTE (FPC_REGNUM
)],
795 &inferior_fp_registers
.fps_control
,
796 sizeof inferior_fp_registers
- sizeof inferior_fp_registers
.fps_regs
);
798 ptrace_in
.pid
= inferior_pid
;
799 ptrace_in
.info
.ttype
= FPREGS
;
800 ptrace_in
.info
.more_data
= (caddr_t
) &inferior_fp_registers
;
802 status
= net_ptrace_clnt_call (PTRACE_SETFPREGS
, &ptrace_in
, &ptrace_out
);
805 if (ptrace_out
.status
== -1)
807 errno
= ptrace_out
.errno
;
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
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. */
823 vx_xfer_memory (memaddr
, myaddr
, len
, write
)
830 Ptrace_return ptrace_out
;
833 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
834 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
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 */
842 ptrace_in
.info
.ttype
= DATA
;
843 ptrace_in
.info
.more_data
= (caddr_t
) &data
;
845 data
.bytes
= (caddr_t
) myaddr
; /* Where from */
846 data
.len
= len
; /* How many bytes (again, for XDR) */
848 /* XXX change second param to be a proc number */
849 status
= net_ptrace_clnt_call (PTRACE_WRITEDATA
, &ptrace_in
, &ptrace_out
);
853 ptrace_out
.info
.more_data
= (caddr_t
) &data
;
854 data
.bytes
= myaddr
; /* Where to */
855 data
.len
= len
; /* How many (again, for XDR) */
857 /* XXX change second param to be a proc number */
858 status
= net_ptrace_clnt_call (PTRACE_READDATA
, &ptrace_in
, &ptrace_out
);
863 if (ptrace_out
.status
== -1)
865 return 0; /* No bytes moved */
867 return len
; /* Moved *all* the bytes */
873 printf ("\tAttached to host `%s'", vx_host
);
874 printf (", which has %sfloating point", target_has_fp
? "": "no ");
881 printf ("\tRunning VxWorks process 0x%x, function `%s'.\n",
882 inferior_pid
, vx_running
);
886 vx_resume (step
, siggnal
)
892 Ptrace_return ptrace_out
;
895 error ("Cannot send signals to VxWorks processes");
897 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
898 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
900 ptrace_in
.pid
= inferior_pid
;
901 ptrace_in
.addr
= 1; /* Target side insists on this, or it panics. */
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
);
908 if (ptrace_out
.status
== -1)
910 errno
= ptrace_out
.errno
;
911 perror_with_name ("Resuming remote process");
918 pop_target (); /* Pop back to no-child state */
919 generic_mourn_inferior ();
923 /* This function allows the addition of incrementally linked object files. */
926 vx_add_file_command (arg_string
, from_tty
)
935 error ("add-file takes a file name in VxWorks");
937 arg_string
= tilde_expand (arg_string
);
938 make_cleanup (free
, arg_string
);
942 if (net_load (arg_string
, &text_addr
, &data_addr
, &bss_addr
) == -1)
943 error ("Load failed on target machine");
945 /* FIXME, for now we ignore data_addr and bss_addr. */
946 symbol_file_add (arg_string
, from_tty
, text_addr
, 0);
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. */
957 enum clnt_stat status
;
959 SOURCE_STEP source_step
;
961 source_step
.taskId
= inferior_pid
;
965 source_step
.startAddr
= step_range_start
;
966 source_step
.endAddr
= step_range_end
;
970 source_step
.startAddr
= 0;
971 source_step
.endAddr
= 0;
974 status
= net_clnt_call (VX_SOURCE_STEP
, xdr_SOURCE_STEP
, &source_step
,
975 xdr_int
, &step_status
);
977 if (status
== RPC_SUCCESS
)
984 /* Emulate ptrace using RPC calls to the VxWorks target system.
985 Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */
988 net_ptrace_clnt_call (request
, pPtraceIn
, pPtraceOut
)
989 enum ptracereq request
;
991 Ptrace_return
*pPtraceOut
;
993 enum clnt_stat status
;
995 status
= net_clnt_call (request
, xdr_rptrace
, pPtraceIn
, xdr_ptrace_return
,
998 if (status
!= RPC_SUCCESS
)
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. */
1011 net_get_boot_file (pBootFile
)
1014 enum clnt_stat status
;
1016 status
= net_clnt_call (VX_BOOT_FILE_INQ
, xdr_void
, (char *) 0,
1017 xdr_wrapstring
, pBootFile
);
1018 return (status
== RPC_SUCCESS
) ? 0 : -1;
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. */
1027 net_get_symbols (pLoadTable
)
1028 ldtabl
*pLoadTable
; /* return pointer to ldtabl here */
1030 enum clnt_stat status
;
1032 bzero ((char *) pLoadTable
, sizeof (struct ldtabl
));
1034 status
= net_clnt_call (VX_STATE_INQ
, xdr_void
, 0, xdr_ldtabl
, pLoadTable
);
1035 return (status
== RPC_SUCCESS
) ? 0 : -1;
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. */
1042 struct complaint cant_contact_target
=
1043 {"Lost contact with VxWorks target", 0, 0};
1046 vx_lookup_symbol (name
, pAddr
)
1047 char *name
; /* symbol name */
1050 enum clnt_stat status
;
1051 SYMBOL_ADDR symbolAddr
;
1054 bzero ((char *) &symbolAddr
, sizeof (symbolAddr
));
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);
1063 *pAddr
= symbolAddr
.addr
;
1064 return symbolAddr
.status
;
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. */
1074 enum clnt_stat status
;
1075 bool_t fp
= 0; /* true if fp processor is present on target board */
1077 status
= net_clnt_call (VX_FP_INQUIRE
, xdr_void
, 0, xdr_bool
, &fp
);
1078 if (status
!= RPC_SUCCESS
)
1084 /* Establish an RPC connection with the VxWorks target system.
1085 Calls error () if unable to establish connection. */
1091 struct sockaddr_in destAddr
;
1092 struct hostent
*destHost
;
1094 /* get the internet address for the given host */
1096 if ((destHost
= (struct hostent
*) gethostbyname (host
)) == NULL
)
1097 error ("Invalid hostname. Couldn't attach remote target.");
1099 bzero (&destAddr
, sizeof (destAddr
));
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. */
1106 /* Create a tcp client transport on which to issue
1107 calls to the remote ptrace server. */
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 */
1113 if (pClient
== NULL
)
1115 clnt_pcreateerror ("\tnet_connect");
1116 error ("Couldn't connect to remote target.");
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.
1130 struct timeval select_timeout
;
1133 select_timeout
.tv_sec
= 0;
1134 select_timeout
.tv_usec
= ms
* 1000;
1136 status
= select (0, (fd_set
*) 0, (fd_set
*) 0, (fd_set
*) 0, &select_timeout
);
1138 if (status
< 0 && errno
!= EINTR
)
1139 perror_with_name ("select");
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. */
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.
1165 /* If CTRL-C is hit during this loop,
1166 suspend the inferior process. */
1171 quit_failed
= (net_quit () == -1);
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. */
1181 if (quit_failed
|| net_wait (&rdbEvent
) == -1)
1184 if (query ("Can't %s. Disconnect from target system? ",
1185 (quit_failed
) ? "suspend remote task"
1186 : "get status of remote task"))
1188 target_mourn_inferior();
1189 error ("Use the \"target\" command to reconnect.");
1193 terminal_inferior ();
1199 if (quit_failed
|| net_wait (&rdbEvent
) == -1)
1201 error ("Wait on remote target failed");
1204 pid
= rdbEvent
.taskId
;
1207 sleep_ms (200); /* FIXME Don't kill the network too badly */
1209 else if (pid
!= inferior_pid
)
1210 fatal ("Bad pid for debugged task: 0x%x\n", pid
);
1213 /* FIXME, eventually do more then SIGTRAP on everything... */
1214 switch (rdbEvent
.eventType
)
1218 /* FIXME is it possible to distinguish between a
1219 XXX normal vs abnormal exit in VxWorks? */
1223 WSETSTOP (w
, SIGTRAP
);
1227 WSETSTOP (w
, SIGTRAP
);
1228 /* XXX was it stopped by a signal? act accordingly */
1232 /* Expecting a trace trap. Stop the inferior and
1233 * return silently when it happens. */
1234 WSETSTOP (w
, SIGTRAP
);
1238 target_terminal_ours_for_output ();
1239 printf ("\nRemote task suspended\n"); /* FIXME */
1241 WSETSTOP (w
, SIGTRAP
);
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
);
1254 *status
= *(int *)&w
; /* Grumble union wait crap Grumble */
1262 char *bootFile
= (char *)arg
;
1263 symbol_file_command (bootFile
, 0);
1268 add_symbol_stub (arg
)
1271 struct ldfile
*pLoadFile
= (struct ldfile
*)arg
;
1273 symbol_file_add (pLoadFile
->name
, 0, pLoadFile
->txt_addr
, 0);
1276 /* Target command for VxWorks target systems.
1278 Used in vxgdb. Takes the name of a remote target machine
1279 running vxWorks and connects to it to initialize remote network
1283 vx_open (args
, from_tty
)
1287 extern int close ();
1289 extern char *source_path
;
1290 struct ldtabl loadTable
;
1291 struct ldfile
*pLoadFile
;
1293 extern CLIENT
*pClient
;
1296 error_no_arg ("target machine name");
1298 printf ("Attaching remote machine across net...\n");
1301 /* Allow the user to kill the connect attempt by typing ^C.
1302 Wait until the call to target_has_fp () completes before
1303 disallowing an immediate quit, since even if net_connect ()
1304 is successful, the remote debug server might be hung. */
1309 target_has_fp
= net_check_for_fp ();
1310 printf_filtered ("Connected to %s\n", args
);
1314 push_target (&vx_ops
);
1316 /* Save a copy of the target host's name. */
1319 vx_host
= savestring (args
, strlen (args
));
1321 /* Find out the name of the file from which the target was booted
1322 and load its symbol table. */
1325 if (!net_get_boot_file (&bootFile
))
1328 printf_filtered ("%s: ", bootFile
);
1329 if (catch_errors (symbol_stub
, (int)bootFile
,
1330 "Error reading symbols from boot file"))
1331 puts_filtered ("ok\n");
1332 } else if (from_tty
)
1333 printf ("VxWorks kernel symbols not loaded.\n");
1336 error ("Can't retrieve boot file name from target machine.");
1338 clnt_freeres (pClient
, xdr_wrapstring
, &bootFile
);
1340 if (net_get_symbols (&loadTable
) != 0)
1341 error ("Can't read loaded modules from target machine");
1344 while (++i
< loadTable
.tbl_size
)
1346 QUIT
; /* FIXME, avoids clnt_freeres below: mem leak */
1347 pLoadFile
= &loadTable
.tbl_ent
[i
];
1351 struct cleanup
*old_chain
;
1352 char *fullname
= NULL
;
1354 desc
= openp (source_path
, 0, pLoadFile
->name
, O_RDONLY
, 0, &fullname
);
1356 perror_with_name (pLoadFile
->name
);
1357 old_chain
= make_cleanup (close
, desc
);
1358 add_file_at_addr (fullname
, desc
, pLoadFile
->txt_addr
, pLoadFile
->data_addr
,
1359 pLoadFile
->bss_addr
);
1360 do_cleanups (old_chain
);
1364 (1) Searches the PATH, not the source path.
1365 (2) data and bss are assumed to be at the usual offsets from text. */
1366 catch_errors (add_symbol_stub
, (int)pLoadFile
,
1367 "Error in reading symbols from loaded module.");
1371 clnt_freeres (pClient
, xdr_ldtabl
, &loadTable
);
1375 puts_filtered ("Success!\n");
1379 /* Cross-net conversion of floats to and from extended form.
1380 (This is needed because different target machines have different
1381 extended floating point formats.) */
1383 /* Convert from an extended float to a double.
1385 The extended float is stored as raw data pointed to by FROM.
1386 Return the converted value as raw data in the double pointed to by TO.
1390 vx_convert_to_virtual (regno
, from
, to
)
1395 enum clnt_stat status
;
1399 if (REGISTER_CONVERTIBLE (regno
))
1401 if (!target_has_fp
) {
1402 *(double *)to
= 0.0; /* Skip the trouble if no float anyway */
1405 bcopy (from
, (char *) &from_ext_fp
, sizeof (from_ext_fp
));
1406 bzero ((char *) &to_double
, sizeof (to_double
));
1408 status
= net_clnt_call (VX_CONV_FROM_68881
, xdr_ext_fp
, &from_ext_fp
,
1409 xdr_double
, &to_double
);
1410 if (status
== RPC_SUCCESS
)
1411 bcopy ((char *) &to_double
, to
, sizeof (to_double
));
1416 bcopy (from
, to
, REGISTER_VIRTUAL_SIZE (regno
));
1420 /* The converse: convert from a double to an extended float.
1422 The double is stored as raw data pointed to by FROM.
1423 Return the converted value as raw data in the extended
1424 float pointed to by TO.
1428 vx_convert_from_virtual (regno
, from
, to
)
1433 enum clnt_stat status
;
1437 if (REGISTER_CONVERTIBLE (regno
))
1439 if (!target_has_fp
) {
1440 bzero (to
, REGISTER_RAW_SIZE (FP0_REGNUM
)); /* Shrug */
1443 bcopy (from
, (char *) &from_double
, sizeof (from_double
));
1444 bzero ((char *) &to_ext_fp
, sizeof (to_ext_fp
));
1446 status
= net_clnt_call (VX_CONV_TO_68881
, xdr_double
, &from_double
,
1447 xdr_ext_fp
, &to_ext_fp
);
1448 if (status
== RPC_SUCCESS
)
1449 bcopy ((char *) &to_ext_fp
, to
, sizeof (to_ext_fp
));
1454 bcopy (from
, to
, REGISTER_VIRTUAL_SIZE (regno
));
1457 /* Make an RPC call to the VxWorks target.
1458 Returns RPC status. */
1460 static enum clnt_stat
1461 net_clnt_call (procNum
, inProc
, in
, outProc
, out
)
1462 enum ptracereq procNum
;
1468 enum clnt_stat status
;
1470 status
= clnt_call (pClient
, procNum
, inProc
, in
, outProc
, out
, rpcTimeout
);
1472 if (status
!= RPC_SUCCESS
)
1473 clnt_perrno (status
);
1479 /* Target ops structure for accessing memory and such over the net */
1481 struct target_ops vx_ops
= {
1482 "vxworks", "VxWorks target memory via RPC over TCP/IP",
1483 vx_open
, 0, /* vx_detach, */
1484 0, 0, /* resume, wait */
1485 0, 0, /* read_reg, write_reg */
1486 0, vx_convert_to_virtual
, vx_convert_from_virtual
, /* prep_to_store, */
1487 vx_xfer_memory
, vx_files_info
,
1488 0, 0, /* insert_breakpoint, remove_breakpoint */
1489 0, 0, 0, 0, 0, /* terminal stuff */
1491 vx_add_file_command
,
1492 call_function_by_hand
, /* FIXME, calling fns is maybe botched? */
1494 vx_create_inferior
, 0, /* mourn_inferior */
1495 core_stratum
, 0, /* next */
1496 1, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */
1497 OPS_MAGIC
, /* Always the last thing */
1500 /* Target ops structure for accessing VxWorks child processes over the net */
1502 struct target_ops vx_run_ops
= {
1503 "vxprocess", "VxWorks process",
1504 vx_open
, 0, /* vx_detach, */
1506 vx_read_register
, vx_write_register
,
1507 vx_prepare_to_store
, vx_convert_to_virtual
, vx_convert_from_virtual
,
1508 vx_xfer_memory
, vx_run_files_info
,
1509 vx_insert_breakpoint
, vx_remove_breakpoint
,
1510 0, 0, 0, 0, 0, /* terminal stuff */
1512 vx_add_file_command
,
1513 call_function_by_hand
, /* FIXME, calling fns is maybe botched? */
1515 vx_create_inferior
, vx_mourn_inferior
,
1516 process_stratum
, 0, /* next */
1517 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1518 OPS_MAGIC
, /* Always the last thing */
1520 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
1525 add_target (&vx_ops
);
1526 add_target (&vx_run_ops
);