1 /* Memory-access and commands for remote VxWorks processes, for GDB.
2 Copyright 1990, 1991 Free Software Foundation, Inc.
3 Contributed by Wind River Systems and Cygnus Support.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #define TM_FILE_OVERRIDE
23 #include "tm-vxworks68.h"
31 #include "symfile.h" /* for struct complaint */
37 #include <sys/types.h>
39 #include <sys/socket.h>
40 #define free bogon_free /* Sun claims "int free()" not void */
45 #include "xdr_ptrace.h"
48 #include "dbgRpcLib.h"
50 /* get rid of value.h if possible */
54 extern void symbol_file_command ();
55 extern int stop_soon_quietly
; /* for wait_for_inferior */
57 static int net_ptrace_clnt_call (); /* Forward decl */
58 static enum clnt_stat
net_clnt_call (); /* Forward decl */
59 extern struct target_ops vx_ops
, vx_run_ops
; /* Forward declaration */
61 /* Saved name of target host and called function for "info files".
65 static char *vx_running
;
67 /* Nonzero means target that is being debugged remotely has a floating
70 static int target_has_fp
;
72 /* Default error message when the network is forking up. */
74 static const char rpcerr
[] = "network target debugging: rpc error";
76 CLIENT
*pClient
; /* client used in net debugging */
77 static int ptraceSock
= RPC_ANYSOCK
;
80 enum clnt_stat
net_clnt_call();
81 static void parse_args ();
83 static struct timeval rpcTimeout
= { 10, 0 };
85 static char *skip_white_space ();
86 static char *find_white_space ();
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. */
94 net_load (filename
, pTextAddr
, pDataAddr
, pBssAddr
)
100 enum clnt_stat status
;
101 struct ldfile ldstruct
;
102 struct timeval load_timeout
;
104 bzero ((char *) &ldstruct
, sizeof (ldstruct
));
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. */
112 load_timeout
.tv_sec
= 0x7FFF7FFF; /* A large number, effectively inf. */
113 load_timeout
.tv_usec
= 0;
115 status
= clnt_call (pClient
, VX_LOAD
, xdr_wrapstring
, &filename
, xdr_ldfile
,
116 &ldstruct
, load_timeout
);
118 if (status
== RPC_SUCCESS
)
120 if (*ldstruct
.name
== NULL
) /* load failed on VxWorks side */
122 *pTextAddr
= ldstruct
.txt_addr
;
123 *pDataAddr
= ldstruct
.data_addr
;
124 *pBssAddr
= ldstruct
.bss_addr
;
131 /* returns 0 if successful, errno if RPC failed or VxWorks complains. */
134 net_break (addr
, procnum
)
138 enum clnt_stat status
;
140 Rptrace ptrace_in
; /* XXX This is stupid. It doesn't need to be a ptrace
141 structure. How about something smaller? */
143 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
146 ptrace_in
.addr
= addr
;
147 ptrace_in
.pid
= inferior_pid
;
149 status
= net_clnt_call (procnum
, xdr_rptrace
, &ptrace_in
, xdr_int
,
152 if (status
!= RPC_SUCCESS
)
155 if (break_status
== -1)
157 return break_status
; /* probably (FIXME) zero */
160 /* returns 0 if successful, errno otherwise */
163 vx_insert_breakpoint (addr
)
166 return net_break (addr
, VX_BREAK_ADD
);
169 /* returns 0 if successful, errno otherwise */
172 vx_remove_breakpoint (addr
)
175 return net_break (addr
, VX_BREAK_DELETE
);
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. */
186 /* FIXME, function calls are really fried. GO back to manual method. */
188 call_function (function
, nargs
, args
)
193 register CORE_ADDR sp
;
196 static REGISTER_TYPE dummy
[] = CALL_DUMMY
;
197 REGISTER_TYPE dummy1
[sizeof dummy
/ sizeof (REGISTER_TYPE
)];
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
;
207 save_inferior_status (&inf_status
, 1);
208 old_chain
= make_cleanup (restore_inferior_status
, &inf_status
);
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. */
215 old_sp
= sp
= read_register (SP_REGNUM
);
217 #if 1 INNER_THAN 2 /* Stack grows down */
220 #else /* Stack grows up */
225 funaddr
= find_function_addr (function
, &value_type
);
228 struct block
*b
= block_for_pc (funaddr
);
229 /* If compiled without -g, assume GCC. */
230 using_gcc
= b
== NULL
|| BLOCK_GCC_COMPILED (b
);
233 /* Are we returning a value using a structure return or a normal
236 struct_return
= using_struct_return (function
, funaddr
, value_type
,
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
);
245 #if CALL_DUMMY_LOCATION == ON_STACK
246 write_memory (start_sp
, dummy1
, sizeof dummy
);
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. */
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");
260 start_sp
= text_end
- sizeof dummy
;
261 write_memory (start_sp
, dummy1
, sizeof dummy
);
263 #else /* After text_end. */
268 errcode
= target_write_memory (start_sp
, dummy1
, sizeof dummy
);
270 error ("Cannot write text segment -- vx_call_function failed");
272 #endif /* After text_end. */
273 #endif /* Not on stack. */
276 /* If stack grows down, we must leave a hole at the top. */
280 /* Reserve space for the return structure to be written on the
281 stack, if necessary */
284 len
+= TYPE_LENGTH (value_type
);
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
;
292 sp
-= STACK_ALIGN (len
) - len
;
294 sp
+= STACK_ALIGN (len
) - len
;
297 #endif /* STACK_ALIGN */
299 /* Reserve space for the return structure to be written on the
300 stack, if necessary */
305 sp
-= TYPE_LENGTH (value_type
);
309 sp
+= TYPE_LENGTH (value_type
);
313 #if defined (REG_STRUCT_HAS_ADDR)
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
--)
319 if ( TYPE_CODE (VALUE_TYPE (args
[i
])) == TYPE_CODE_STRUCT
320 || TYPE_CODE (VALUE_TYPE (args
[i
])) == TYPE_CODE_UNION
)
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. */
328 /* Push the structure. */
329 sp
= value_push (sp
, args
[i
]);
331 /* The stack grows down, so the address of the thing we push
332 is the stack pointer after we push it. */
335 /* The value we're going to pass is the address of the thing
337 args
[i
] = value_from_long (builtin_type_long
, (LONGEST
) addr
);
340 #endif /* REG_STRUCT_HAS_ADDR. */
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 */
349 #ifdef CALL_DUMMY_STACK_ADJUST
351 sp
-= CALL_DUMMY_STACK_ADJUST
;
353 sp
+= CALL_DUMMY_STACK_ADJUST
;
355 #endif /* CALL_DUMMY_STACK_ADJUST */
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.
363 Also note that on some machines (like the sparc) pcc uses a
364 convention like gcc's. */
367 STORE_STRUCT_RETURN (struct_addr
, sp
);
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
);
375 /* Figure out the value returned by the function. */
377 char retbuf
[REGISTER_BYTES
];
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
);
384 do_cleanups (old_chain
);
386 return value_being_returned (value_type
, retbuf
, struct_return
);
389 /* should return a value of some sort */
392 vx_call_function (funcAddr
, nargs
, args
, valueType
)
396 struct type
* valueType
;
401 enum clnt_stat status
;
403 arg_value funcReturn
;
406 argValue
= (arg_value
*) xmalloc (nargs
* sizeof (arg_value
));
408 bzero (argValue
, nargs
* sizeof (arg_value
));
409 bzero (&funcReturn
, sizeof (funcReturn
));
411 for (i
= nargs
- 1; i
>= 0; i
--)
413 len
= TYPE_LENGTH (VALUE_TYPE (args
[i
]));
415 switch (TYPE_CODE (VALUE_TYPE (args
[i
])))
417 /* XXX put other types here. Where's CHAR, etc??? */
420 argValue
[i
].type
= T_FLOAT
;
426 argValue
[i
].type
= T_INT
;
429 case TYPE_CODE_UNDEF
:
430 case TYPE_CODE_ARRAY
:
431 case TYPE_CODE_STRUCT
:
432 case TYPE_CODE_UNION
:
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++ */
441 error ("No corresponding VxWorks type for %d. CHECK IT OUT!!!\n",
442 TYPE_CODE(VALUE_TYPE(args
[i
])));
444 if (TYPE_CODE(VALUE_TYPE(args
[i
])) == TYPE_CODE_FUNC
)
445 argValue
[i
].arg_value_u
.v_int
= VALUE_ADDRESS(args
[i
]);
447 bcopy (VALUE_CONTENTS (args
[i
]), (char *) &argValue
[i
].arg_value_u
,
451 /* XXX what should the type of this function addr be?
452 * XXX Both in gdb and vxWorks
454 funcInfo
.func_addr
= (int) funcAddr
;
455 funcInfo
.args
.args_len
= nargs
;
456 funcInfo
.args
.args_val
= argValue
;
458 status
= net_clnt_call (VX_CALL_FUNC
, xdr_func_call
, (char *) &funcInfo
,
459 xdr_arg_value
, &funcReturn
);
461 free ((char *) argValue
);
463 if (status
== RPC_SUCCESS
)
465 /* XXX this assumes that vxWorks ALWAYS returns an int, and that
466 * XXX gdb isn't expecting anything more
470 if (funcReturn.type == T_UNKNOWN)
473 gdbValue
= allocate_value (valueType
);
474 bcopy (&funcReturn
.arg_value_u
.v_int
, VALUE_CONTENTS (gdbValue
),
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. */
491 vx_create_inferior (exec_file
, args
, env
)
496 enum clnt_stat status
;
498 TASK_START taskStart
;
500 bzero ((char *) &passArgs
, sizeof (passArgs
));
501 bzero ((char *) &taskStart
, sizeof (taskStart
));
503 /* parse arguments, put them in passArgs */
505 parse_args (args
, &passArgs
);
507 if (passArgs
.arg_array_len
== 0)
508 error ("You must specify a function name to run, and arguments if any");
510 status
= net_clnt_call (PROCESS_START
, xdr_arg_array
, &passArgs
,
511 xdr_TASK_START
, &taskStart
);
513 if ((status
!= RPC_SUCCESS
) || (taskStart
.status
== -1))
514 error ("Can't create process on remote target machine");
516 /* Save the name of the running function */
519 vx_running
= savestring (passArgs
.arg_array_val
[0],
520 strlen (passArgs
.arg_array_val
[0]));
522 #ifdef CREATE_INFERIOR_HOOK
523 CREATE_INFERIOR_HOOK (pid
);
526 push_target (&vx_run_ops
);
527 inferior_pid
= taskStart
.pid
;
529 #if defined (START_INFERIOR_HOOK)
530 START_INFERIOR_HOOK ();
533 /* We will get a trace trap after one instruction.
534 Insert breakpoints and continue. */
536 init_wait_for_inferior ();
538 /* Set up the "saved terminal modes" of the inferior
539 based on what modes we are starting it with. */
540 target_terminal_init ();
542 /* Install inferior's terminal modes. */
543 target_terminal_inferior ();
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;
551 /* insert_step_breakpoint (); FIXME, do we need this? */
555 /* Fill ARGSTRUCT in argc/argv form with the arguments from the
556 argument string ARGSTRING. */
559 parse_args (arg_string
, arg_struct
)
560 register char *arg_string
;
561 arg_array
*arg_struct
;
563 register int arg_count
= 0; /* number of arguments */
564 register int arg_index
= 0;
567 bzero ((char *) arg_struct
, sizeof (arg_array
));
569 /* first count how many arguments there are */
574 if (*(p0
= skip_white_space (p0
)) == '\0')
576 p0
= find_white_space (p0
);
580 arg_struct
->arg_array_len
= arg_count
;
581 arg_struct
->arg_array_val
= (char **) xmalloc ((arg_count
+ 1)
584 /* now copy argument strings into arg_struct. */
586 while (*(arg_string
= skip_white_space (arg_string
)))
588 p0
= find_white_space (arg_string
);
589 arg_struct
->arg_array_val
[arg_index
++] = savestring (arg_string
,
594 arg_struct
->arg_array_val
[arg_count
] = NULL
;
597 /* Advance a string pointer across whitespace and return a pointer
598 to the first non-white character. */
604 while (*p
== ' ' || *p
== '\t')
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. */
619 while ((c
= *p
) != ' ' && c
!= '\t' && c
)
621 if (c
== '\'' || c
== '"')
623 while (*++p
!= c
&& *p
)
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. */
645 enum clnt_stat status
;
647 bzero ((char *) pEvent
, sizeof (RDB_EVENT
));
650 status
= net_clnt_call (PROCESS_WAIT
, xdr_int
, &pid
, xdr_RDB_EVENT
, pEvent
);
652 return (status
== RPC_SUCCESS
)? pEvent
->status
: -1;
655 /* Suspend the remote task.
656 Returns -1 if suspend fails on target system, 0 otherwise. */
663 enum clnt_stat status
;
667 /* don't let rdbTask suspend itself by passing a pid of 0 */
669 if ((pid
= inferior_pid
) == 0)
672 status
= net_clnt_call (VX_TASK_SUSPEND
, xdr_int
, &pid
, xdr_int
,
675 return (status
== RPC_SUCCESS
)? quit_status
: -1;
678 /* Read a register or registers from the remote system. */
681 vx_read_register (regno
)
686 Ptrace_return ptrace_out
;
687 struct regs inferior_registers
;
688 struct fp_status inferior_fp_registers
;
689 extern char registers
[];
691 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
692 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
694 /* FIXME, eventually only get the ones we need. */
695 registers_fetched ();
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
);
702 if (ptrace_out
.status
== -1)
704 errno
= ptrace_out
.errno
;
710 bcopy (&inferior_registers
, registers
, 16 * 4);
711 *(int *)®isters
[REGISTER_BYTE (PS_REGNUM
)] = inferior_registers
.r_ps
;
712 *(int *)®isters
[REGISTER_BYTE (PC_REGNUM
)] = inferior_registers
.r_pc
;
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
);
721 if (ptrace_out
.status
== -1)
723 errno
= ptrace_out
.errno
;
727 bcopy (&inferior_fp_registers
, ®isters
[REGISTER_BYTE (FP0_REGNUM
)],
728 sizeof inferior_fp_registers
.fps_regs
);
729 bcopy (&inferior_fp_registers
.fps_control
,
730 ®isters
[REGISTER_BYTE (FPC_REGNUM
)],
731 sizeof inferior_fp_registers
- sizeof inferior_fp_registers
.fps_regs
);
735 bzero (®isters
[REGISTER_BYTE (FP0_REGNUM
)],
736 sizeof inferior_fp_registers
.fps_regs
);
737 bzero (®isters
[REGISTER_BYTE (FPC_REGNUM
)],
738 sizeof inferior_fp_registers
- sizeof inferior_fp_registers
.fps_regs
);
744 /* Prepare to store registers. Since we will store all of them,
745 read out their current values now. */
748 vx_prepare_to_store ()
750 vx_read_register (-1);
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 */
759 vx_write_register (regno
)
762 struct regs inferior_registers
;
763 struct fp_status inferior_fp_registers
;
764 extern char registers
[];
767 Ptrace_return ptrace_out
;
769 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
770 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
772 bcopy (registers
, &inferior_registers
, 16 * 4);
773 inferior_registers
.r_ps
= *(int *)®isters
[REGISTER_BYTE (PS_REGNUM
)];
774 inferior_registers
.r_pc
= *(int *)®isters
[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
;
779 /* XXX change second param to be a proc number */
780 status
= net_ptrace_clnt_call (PTRACE_SETREGS
, &ptrace_in
, &ptrace_out
);
783 if (ptrace_out
.status
== -1)
785 errno
= ptrace_out
.errno
;
791 bcopy (®isters
[REGISTER_BYTE (FP0_REGNUM
)], &inferior_fp_registers
,
792 sizeof inferior_fp_registers
.fps_regs
);
793 bcopy (®isters
[REGISTER_BYTE (FPC_REGNUM
)],
794 &inferior_fp_registers
.fps_control
,
795 sizeof inferior_fp_registers
- sizeof inferior_fp_registers
.fps_regs
);
797 ptrace_in
.pid
= inferior_pid
;
798 ptrace_in
.info
.ttype
= FPREGS
;
799 ptrace_in
.info
.more_data
= (caddr_t
) &inferior_fp_registers
;
801 status
= net_ptrace_clnt_call (PTRACE_SETFPREGS
, &ptrace_in
, &ptrace_out
);
804 if (ptrace_out
.status
== -1)
806 errno
= ptrace_out
.errno
;
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
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. */
822 vx_xfer_memory (memaddr
, myaddr
, len
, write
)
829 Ptrace_return ptrace_out
;
832 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
833 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
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 */
841 ptrace_in
.info
.ttype
= DATA
;
842 ptrace_in
.info
.more_data
= (caddr_t
) &data
;
844 data
.bytes
= (caddr_t
) myaddr
; /* Where from */
845 data
.len
= len
; /* How many bytes (again, for XDR) */
847 /* XXX change second param to be a proc number */
848 status
= net_ptrace_clnt_call (PTRACE_WRITEDATA
, &ptrace_in
, &ptrace_out
);
852 ptrace_out
.info
.more_data
= (caddr_t
) &data
;
853 data
.bytes
= myaddr
; /* Where to */
854 data
.len
= len
; /* How many (again, for XDR) */
856 /* XXX change second param to be a proc number */
857 status
= net_ptrace_clnt_call (PTRACE_READDATA
, &ptrace_in
, &ptrace_out
);
862 if (ptrace_out
.status
== -1)
864 return 0; /* No bytes moved */
866 return len
; /* Moved *all* the bytes */
872 printf ("\tAttached to host `%s'", vx_host
);
873 printf (", which has %sfloating point", target_has_fp
? "": "no ");
880 printf ("\tRunning VxWorks process 0x%x, function `%s'.\n",
881 inferior_pid
, vx_running
);
885 vx_resume (step
, siggnal
)
891 Ptrace_return ptrace_out
;
894 error ("Cannot send signals to VxWorks processes");
896 bzero ((char *) &ptrace_in
, sizeof (ptrace_in
));
897 bzero ((char *) &ptrace_out
, sizeof (ptrace_out
));
899 ptrace_in
.pid
= inferior_pid
;
900 ptrace_in
.addr
= 1; /* Target side insists on this, or it panics. */
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
);
907 if (ptrace_out
.status
== -1)
909 errno
= ptrace_out
.errno
;
910 perror_with_name ("Resuming remote process");
917 pop_target (); /* Pop back to no-child state */
918 generic_mourn_inferior ();
922 /* This function allows the addition of incrementally linked object files. */
925 vx_add_file_command (arg_string
, from_tty
)
934 error ("add-file takes a file name in VxWorks");
936 arg_string
= tilde_expand (arg_string
);
937 make_cleanup (free
, arg_string
);
941 if (net_load (arg_string
, &text_addr
, &data_addr
, &bss_addr
) == -1)
942 error ("Load failed on target machine");
944 /* FIXME, for now we ignore data_addr and bss_addr. */
945 symbol_file_add (arg_string
, from_tty
, text_addr
, 0);
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. */
956 enum clnt_stat status
;
958 SOURCE_STEP source_step
;
960 source_step
.taskId
= inferior_pid
;
964 source_step
.startAddr
= step_range_start
;
965 source_step
.endAddr
= step_range_end
;
969 source_step
.startAddr
= 0;
970 source_step
.endAddr
= 0;
973 status
= net_clnt_call (VX_SOURCE_STEP
, xdr_SOURCE_STEP
, &source_step
,
974 xdr_int
, &step_status
);
976 if (status
== RPC_SUCCESS
)
983 /* Emulate ptrace using RPC calls to the VxWorks target system.
984 Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */
987 net_ptrace_clnt_call (request
, pPtraceIn
, pPtraceOut
)
988 enum ptracereq request
;
990 Ptrace_return
*pPtraceOut
;
992 enum clnt_stat status
;
994 status
= net_clnt_call (request
, xdr_rptrace
, pPtraceIn
, xdr_ptrace_return
,
997 if (status
!= RPC_SUCCESS
)
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. */
1010 net_get_boot_file (pBootFile
)
1013 enum clnt_stat status
;
1015 status
= net_clnt_call (VX_BOOT_FILE_INQ
, xdr_void
, (char *) 0,
1016 xdr_wrapstring
, pBootFile
);
1017 return (status
== RPC_SUCCESS
) ? 0 : -1;
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. */
1026 net_get_symbols (pLoadTable
)
1027 ldtabl
*pLoadTable
; /* return pointer to ldtabl here */
1029 enum clnt_stat status
;
1031 bzero ((char *) pLoadTable
, sizeof (struct ldtabl
));
1033 status
= net_clnt_call (VX_STATE_INQ
, xdr_void
, 0, xdr_ldtabl
, pLoadTable
);
1034 return (status
== RPC_SUCCESS
) ? 0 : -1;
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. */
1041 struct complaint cant_contact_target
=
1042 {"Lost contact with VxWorks target", 0, 0};
1045 vx_lookup_symbol (name
, pAddr
)
1046 char *name
; /* symbol name */
1049 enum clnt_stat status
;
1050 SYMBOL_ADDR symbolAddr
;
1053 bzero ((char *) &symbolAddr
, sizeof (symbolAddr
));
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);
1062 *pAddr
= symbolAddr
.addr
;
1063 return symbolAddr
.status
;
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. */
1073 enum clnt_stat status
;
1074 bool_t fp
= 0; /* true if fp processor is present on target board */
1076 status
= net_clnt_call (VX_FP_INQUIRE
, xdr_void
, 0, xdr_bool
, &fp
);
1077 if (status
!= RPC_SUCCESS
)
1083 /* Establish an RPC connection with the VxWorks target system.
1084 Calls error () if unable to establish connection. */
1090 struct sockaddr_in destAddr
;
1091 struct hostent
*destHost
;
1093 /* get the internet address for the given host */
1095 if ((destHost
= (struct hostent
*) gethostbyname (host
)) == NULL
)
1096 error ("Invalid hostname. Couldn't attach remote target.");
1098 bzero (&destAddr
, sizeof (destAddr
));
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. */
1105 /* Create a tcp client transport on which to issue
1106 calls to the remote ptrace server. */
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 */
1112 if (pClient
== NULL
)
1114 clnt_pcreateerror ("\tnet_connect");
1115 error ("Couldn't connect to remote target.");
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.
1129 struct timeval select_timeout
;
1132 select_timeout
.tv_sec
= 0;
1133 select_timeout
.tv_usec
= ms
* 1000;
1135 status
= select (0, (fd_set
*) 0, (fd_set
*) 0, (fd_set
*) 0, &select_timeout
);
1137 if (status
< 0 && errno
!= EINTR
)
1138 perror_with_name ("select");
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. */
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.
1164 /* If CTRL-C is hit during this loop,
1165 suspend the inferior process. */
1170 quit_failed
= (net_quit () == -1);
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. */
1180 if (quit_failed
|| net_wait (&rdbEvent
) == -1)
1183 if (query ("Can't %s. Disconnect from target system? ",
1184 (quit_failed
) ? "suspend remote task"
1185 : "get status of remote task"))
1187 target_mourn_inferior();
1188 error ("Use the \"target\" command to reconnect.");
1192 terminal_inferior ();
1198 if (quit_failed
|| net_wait (&rdbEvent
) == -1)
1200 error ("Wait on remote target failed");
1203 pid
= rdbEvent
.taskId
;
1206 sleep_ms (200); /* FIXME Don't kill the network too badly */
1208 else if (pid
!= inferior_pid
)
1209 fatal ("Bad pid for debugged task: 0x%x\n", pid
);
1212 /* FIXME, eventually do more then SIGTRAP on everything... */
1213 switch (rdbEvent
.eventType
)
1217 /* FIXME is it possible to distinguish between a
1218 XXX normal vs abnormal exit in VxWorks? */
1222 WSETSTOP (w
, SIGTRAP
);
1226 WSETSTOP (w
, SIGTRAP
);
1227 /* XXX was it stopped by a signal? act accordingly */
1231 /* Expecting a trace trap. Stop the inferior and
1232 * return silently when it happens. */
1233 WSETSTOP (w
, SIGTRAP
);
1237 target_terminal_ours_for_output ();
1238 printf ("\nRemote task suspended\n"); /* FIXME */
1240 WSETSTOP (w
, SIGTRAP
);
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
);
1253 *status
= *(int *)&w
; /* Grumble union wait crap Grumble */
1261 char *bootFile
= (char *)arg
;
1262 symbol_file_command (bootFile
, 0);
1267 add_symbol_stub (arg
)
1270 struct ldfile
*pLoadFile
= (struct ldfile
*)arg
;
1272 symbol_file_add (pLoadFile
->name
, 0, pLoadFile
->txt_addr
, 0);
1275 /* Target command for VxWorks target systems.
1277 Used in vxgdb. Takes the name of a remote target machine
1278 running vxWorks and connects to it to initialize remote network
1282 vx_open (args
, from_tty
)
1286 extern int close ();
1288 extern char *source_path
;
1289 struct ldtabl loadTable
;
1290 struct ldfile
*pLoadFile
;
1292 extern CLIENT
*pClient
;
1295 error_no_arg ("target machine name");
1299 printf ("Attaching remote machine across net...\n");
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. */
1310 target_has_fp
= net_check_for_fp ();
1311 printf_filtered ("Connected to %s\n", args
);
1315 push_target (&vx_ops
);
1317 /* Save a copy of the target host's name. */
1320 vx_host
= savestring (args
, strlen (args
));
1322 /* Find out the name of the file from which the target was booted
1323 and load its symbol table. */
1326 if (!net_get_boot_file (&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");
1337 error ("Can't retrieve boot file name from target machine.");
1339 clnt_freeres (pClient
, xdr_wrapstring
, &bootFile
);
1341 if (net_get_symbols (&loadTable
) != 0)
1342 error ("Can't read loaded modules from target machine");
1345 while (++i
< loadTable
.tbl_size
)
1347 QUIT
; /* FIXME, avoids clnt_freeres below: mem leak */
1348 pLoadFile
= &loadTable
.tbl_ent
[i
];
1352 struct cleanup
*old_chain
;
1353 char *fullname
= NULL
;
1355 desc
= openp (source_path
, 0, pLoadFile
->name
, O_RDONLY
, 0, &fullname
);
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
);
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.");
1372 clnt_freeres (pClient
, xdr_ldtabl
, &loadTable
);
1376 puts_filtered ("Success!\n");
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.) */
1384 /* Convert from an extended float to a double.
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.
1391 vx_convert_to_virtual (regno
, from
, to
)
1396 enum clnt_stat status
;
1400 if (REGISTER_CONVERTIBLE (regno
))
1402 if (!target_has_fp
) {
1403 *(double *)to
= 0.0; /* Skip the trouble if no float anyway */
1406 bcopy (from
, (char *) &from_ext_fp
, sizeof (from_ext_fp
));
1407 bzero ((char *) &to_double
, sizeof (to_double
));
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
));
1417 bcopy (from
, to
, REGISTER_VIRTUAL_SIZE (regno
));
1421 /* The converse: convert from a double to an extended float.
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.
1429 vx_convert_from_virtual (regno
, from
, to
)
1434 enum clnt_stat status
;
1438 if (REGISTER_CONVERTIBLE (regno
))
1440 if (!target_has_fp
) {
1441 bzero (to
, REGISTER_RAW_SIZE (FP0_REGNUM
)); /* Shrug */
1444 bcopy (from
, (char *) &from_double
, sizeof (from_double
));
1445 bzero ((char *) &to_ext_fp
, sizeof (to_ext_fp
));
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
));
1455 bcopy (from
, to
, REGISTER_VIRTUAL_SIZE (regno
));
1458 /* Make an RPC call to the VxWorks target.
1459 Returns RPC status. */
1461 static enum clnt_stat
1462 net_clnt_call (procNum
, inProc
, in
, outProc
, out
)
1463 enum ptracereq procNum
;
1469 enum clnt_stat status
;
1471 status
= clnt_call (pClient
, procNum
, inProc
, in
, outProc
, out
, rpcTimeout
);
1473 if (status
!= RPC_SUCCESS
)
1474 clnt_perrno (status
);
1479 /* A vxprocess target should be started via "run" not "target". */
1482 vx_proc_open (name
, from_tty
)
1486 error ("Use the \"run\" command to start a VxWorks process.");
1490 /* Target ops structure for accessing memory and such over the net */
1492 struct target_ops vx_ops
= {
1493 "vxworks", "VxWorks target memory via RPC over TCP/IP",
1494 "Use VxWorks target memory. \n\
1495 Specify the name of the machine to connect to.",
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 */
1504 vx_add_file_command
,
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 */
1512 /* Target ops structure for accessing VxWorks child processes over the net */
1514 struct target_ops vx_run_ops
= {
1515 "vxprocess", "VxWorks process",
1516 "VxWorks process, started by the \"run\" command.",
1517 vx_proc_open
, 0, /* vx_detach, */
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 */
1525 vx_add_file_command
,
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 */
1532 /* ==> Remember when reading at end of file, there are two "ops" structs here. */
1537 add_target (&vx_ops
);
1538 add_target (&vx_run_ops
);