Improve release doc slightly.
[deliverable/binutils-gdb.git] / gdb / remote-vx.c
CommitLineData
dd3b648e 1/* Memory-access and commands for remote VxWorks processes, for GDB.
e17960fb 2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
dd3b648e
RP
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
dd3b648e 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.
dd3b648e 11
99a7de40 12This program is distributed in the hope that it will be useful,
dd3b648e
RP
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. */
dd3b648e
RP
20
21#include "defs.h"
dd3b648e
RP
22#include "frame.h"
23#include "inferior.h"
24#include "wait.h"
25#include "target.h"
26#include "gdbcore.h"
27#include "command.h"
28#include "symtab.h"
29#include "symfile.h" /* for struct complaint */
30
dd3b648e
RP
31#include <string.h>
32#include <errno.h>
33#include <signal.h>
34#include <fcntl.h>
35#include <sys/types.h>
36#include <sys/time.h>
37#include <sys/socket.h>
0d6d92c7 38#define malloc bogon_malloc /* Sun claims "char *malloc()" not void * */
dd3b648e 39#define free bogon_free /* Sun claims "int free()" not void */
b67903ac 40#define realloc bogon_realloc /* Sun claims "char *realloc()", not void * */
dd3b648e 41#include <rpc/rpc.h>
0d6d92c7 42#undef malloc
dd3b648e 43#undef free
b67903ac 44#undef realloc
dd3b648e
RP
45#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
46#include <netdb.h>
aa942355
SG
47#include "vx-share/ptrace.h"
48#include "vx-share/xdr_ptrace.h"
49#include "vx-share/xdr_ld.h"
50#include "vx-share/xdr_rdb.h"
51#include "vx-share/dbgRpcLib.h"
afc5505f 52#include "vx-share/reg.h"
dd3b648e 53
dd3b648e 54#include <symtab.h>
1ab3bf1b 55
dd3b648e 56extern void symbol_file_command ();
dd3b648e 57extern int stop_soon_quietly; /* for wait_for_inferior */
8616205a
SG
58extern void host_convert_to_virtual ();
59extern void host_convert_from_virtual ();
dd3b648e
RP
60
61static int net_ptrace_clnt_call (); /* Forward decl */
62static enum clnt_stat net_clnt_call (); /* Forward decl */
63extern struct target_ops vx_ops, vx_run_ops; /* Forward declaration */
64
65/* Saved name of target host and called function for "info files".
66 Both malloc'd. */
67
68static char *vx_host;
69static char *vx_running; /* Called function */
70
71/* Nonzero means target that is being debugged remotely has a floating
72 point processor. */
73
74static int target_has_fp;
75
76/* Default error message when the network is forking up. */
77
78static const char rpcerr[] = "network target debugging: rpc error";
79
80CLIENT *pClient; /* client used in net debugging */
81static int ptraceSock = RPC_ANYSOCK;
82
83enum clnt_stat net_clnt_call();
84static void parse_args ();
85
86static struct timeval rpcTimeout = { 10, 0 };
87
88static char *skip_white_space ();
89static char *find_white_space ();
90
91/* Tell the VxWorks target system to download a file.
92 The load addresses of the text, data, and bss segments are
afc5505f 93 stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively).
dd3b648e
RP
94 Returns 0 for success, -1 for failure. */
95
96static int
97net_load (filename, pTextAddr, pDataAddr, pBssAddr)
98 char *filename;
99 CORE_ADDR *pTextAddr;
100 CORE_ADDR *pDataAddr;
101 CORE_ADDR *pBssAddr;
102 {
103 enum clnt_stat status;
104 struct ldfile ldstruct;
105 struct timeval load_timeout;
106
107 bzero ((char *) &ldstruct, sizeof (ldstruct));
108
109 /* We invoke clnt_call () here directly, instead of through
110 net_clnt_call (), because we need to set a large timeout value.
111 The load on the target side can take quite a while, easily
112 more than 10 seconds. The user can kill this call by typing
113 CTRL-C if there really is a problem with the load.
afc5505f 114
dd3b648e
RP
115 Do not change the tv_sec value without checking -- select() imposes
116 a limit of 10**8 on it for no good reason that I can see... */
117
118 load_timeout.tv_sec = 99999999; /* A large number, effectively inf. */
119 load_timeout.tv_usec = 0;
120
121 status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
122 &ldstruct, load_timeout);
123
124 if (status == RPC_SUCCESS)
125 {
afc5505f 126 if (*ldstruct.name == 0) /* load failed on VxWorks side */
dd3b648e
RP
127 return -1;
128 *pTextAddr = ldstruct.txt_addr;
129 *pDataAddr = ldstruct.data_addr;
130 *pBssAddr = ldstruct.bss_addr;
131 return 0;
132 }
133 else
134 return -1;
135 }
136
137/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
138
139static int
140net_break (addr, procnum)
141 int addr;
142 u_long procnum;
143 {
144 enum clnt_stat status;
145 int break_status;
146 Rptrace ptrace_in; /* XXX This is stupid. It doesn't need to be a ptrace
147 structure. How about something smaller? */
148
149 bzero ((char *) &ptrace_in, sizeof (ptrace_in));
150 break_status = 0;
151
152 ptrace_in.addr = addr;
153 ptrace_in.pid = inferior_pid;
154
155 status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
156 &break_status);
157
158 if (status != RPC_SUCCESS)
159 return errno;
160
161 if (break_status == -1)
162 return ENOMEM;
163 return break_status; /* probably (FIXME) zero */
164 }
165
166/* returns 0 if successful, errno otherwise */
167
8616205a 168static int
dd3b648e
RP
169vx_insert_breakpoint (addr)
170 int addr;
171 {
172 return net_break (addr, VX_BREAK_ADD);
173 }
174
175/* returns 0 if successful, errno otherwise */
176
8616205a 177static int
dd3b648e
RP
178vx_remove_breakpoint (addr)
179 int addr;
180 {
181 return net_break (addr, VX_BREAK_DELETE);
182 }
183
dd3b648e
RP
184/* Start an inferior process and sets inferior_pid to its pid.
185 EXEC_FILE is the file to run.
186 ALLARGS is a string containing the arguments to the program.
187 ENV is the environment vector to pass.
188 Returns process id. Errors reported with error().
189 On VxWorks, we ignore exec_file. */
190
8616205a 191static void
dd3b648e
RP
192vx_create_inferior (exec_file, args, env)
193 char *exec_file;
194 char *args;
195 char **env;
196{
197 enum clnt_stat status;
198 arg_array passArgs;
199 TASK_START taskStart;
200
201 bzero ((char *) &passArgs, sizeof (passArgs));
202 bzero ((char *) &taskStart, sizeof (taskStart));
203
204 /* parse arguments, put them in passArgs */
205
206 parse_args (args, &passArgs);
207
208 if (passArgs.arg_array_len == 0)
209 error ("You must specify a function name to run, and arguments if any");
210
211 status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
212 xdr_TASK_START, &taskStart);
213
214 if ((status != RPC_SUCCESS) || (taskStart.status == -1))
215 error ("Can't create process on remote target machine");
216
217 /* Save the name of the running function */
218 vx_running = savestring (passArgs.arg_array_val[0],
219 strlen (passArgs.arg_array_val[0]));
220
221#ifdef CREATE_INFERIOR_HOOK
222 CREATE_INFERIOR_HOOK (pid);
223#endif
224
225 push_target (&vx_run_ops);
226 inferior_pid = taskStart.pid;
227
dd3b648e
RP
228 /* We will get a trace trap after one instruction.
229 Insert breakpoints and continue. */
230
231 init_wait_for_inferior ();
232
233 /* Set up the "saved terminal modes" of the inferior
234 based on what modes we are starting it with. */
235 target_terminal_init ();
236
237 /* Install inferior's terminal modes. */
238 target_terminal_inferior ();
239
dd3b648e
RP
240 stop_soon_quietly = 1;
241 wait_for_inferior (); /* Get the task spawn event */
242 stop_soon_quietly = 0;
243
244 /* insert_step_breakpoint (); FIXME, do we need this? */
245 proceed(-1, -1, 0);
246}
247
248/* Fill ARGSTRUCT in argc/argv form with the arguments from the
249 argument string ARGSTRING. */
250
251static void
252parse_args (arg_string, arg_struct)
253 register char *arg_string;
254 arg_array *arg_struct;
255{
256 register int arg_count = 0; /* number of arguments */
257 register int arg_index = 0;
258 register char *p0;
259
260 bzero ((char *) arg_struct, sizeof (arg_array));
261
262 /* first count how many arguments there are */
263
264 p0 = arg_string;
265 while (*p0 != '\0')
266 {
267 if (*(p0 = skip_white_space (p0)) == '\0')
268 break;
269 p0 = find_white_space (p0);
270 arg_count++;
271 }
272
273 arg_struct->arg_array_len = arg_count;
274 arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
275 * sizeof (char *));
276
277 /* now copy argument strings into arg_struct. */
278
279 while (*(arg_string = skip_white_space (arg_string)))
280 {
281 p0 = find_white_space (arg_string);
282 arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
283 p0 - arg_string);
284 arg_string = p0;
285 }
286
287 arg_struct->arg_array_val[arg_count] = NULL;
288}
289
290/* Advance a string pointer across whitespace and return a pointer
291 to the first non-white character. */
292
293static char *
294skip_white_space (p)
295 register char *p;
296{
297 while (*p == ' ' || *p == '\t')
298 p++;
299 return p;
300}
301
302/* Search for the first unquoted whitespace character in a string.
303 Returns a pointer to the character, or to the null terminator
304 if no whitespace is found. */
305
306static char *
307find_white_space (p)
308 register char *p;
309{
310 register int c;
311
312 while ((c = *p) != ' ' && c != '\t' && c)
313 {
314 if (c == '\'' || c == '"')
315 {
316 while (*++p != c && *p)
317 {
318 if (*p == '\\')
319 p++;
320 }
321 if (!*p)
322 break;
323 }
324 p++;
325 }
326 return p;
327}
328
329/* Poll the VxWorks target system for an event related
330 to the debugged task.
331 Returns -1 if remote wait failed, task status otherwise. */
332
8616205a 333static int
dd3b648e
RP
334net_wait (pEvent)
335 RDB_EVENT *pEvent;
336{
337 int pid;
338 enum clnt_stat status;
339
340 bzero ((char *) pEvent, sizeof (RDB_EVENT));
341
342 pid = inferior_pid;
343 status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT, pEvent);
344
345 return (status == RPC_SUCCESS)? pEvent->status: -1;
346}
347
348/* Suspend the remote task.
349 Returns -1 if suspend fails on target system, 0 otherwise. */
350
8616205a 351static int
dd3b648e
RP
352net_quit ()
353{
354 int pid;
355 int quit_status;
356 enum clnt_stat status;
357
358 quit_status = 0;
359
360 /* don't let rdbTask suspend itself by passing a pid of 0 */
361
362 if ((pid = inferior_pid) == 0)
363 return -1;
364
365 status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
366 &quit_status);
367
368 return (status == RPC_SUCCESS)? quit_status: -1;
369}
370
371/* Read a register or registers from the remote system. */
372
8616205a 373static void
dd3b648e
RP
374vx_read_register (regno)
375 int regno;
376{
377 int status;
378 Rptrace ptrace_in;
379 Ptrace_return ptrace_out;
8616205a
SG
380 C_bytes in_data;
381 C_bytes out_data;
dd3b648e
RP
382 extern char registers[];
383
384 bzero ((char *) &ptrace_in, sizeof (ptrace_in));
385 bzero ((char *) &ptrace_out, sizeof (ptrace_out));
386
387 /* FIXME, eventually only get the ones we need. */
388 registers_fetched ();
389
390 ptrace_in.pid = inferior_pid;
8616205a 391 ptrace_out.info.more_data = (caddr_t) &out_data;
afc5505f 392#ifndef I80960
8616205a 393 out_data.len = 18 * REGISTER_RAW_SIZE (0); /* FIXME 68k hack */
afc5505f
KR
394#else
395 out_data.len = (16 + 16 + 3) * REGISTER_RAW_SIZE (0);
396#endif
8616205a
SG
397 out_data.bytes = (caddr_t) registers;
398
dd3b648e
RP
399 status = net_ptrace_clnt_call (PTRACE_GETREGS, &ptrace_in, &ptrace_out);
400 if (status)
401 error (rpcerr);
402 if (ptrace_out.status == -1)
403 {
404 errno = ptrace_out.errno;
8616205a 405 perror_with_name ("net_ptrace_clnt_call(PTRACE_GETREGS)");
dd3b648e
RP
406 }
407
408#ifdef I80960
409
afc5505f
KR
410 {
411 /* If the target has floating point registers, fetch them.
412 Otherwise, zero the floating point register values in
413 registers[] for good measure, even though we might not
414 need to. */
415 /* @@ Can't use this -- the rdb library for the 960 target
416 doesn't support setting or retrieving FP regs. KR */
417#if 0
418 struct fp_status inferior_fp_registers;
419
420 if (target_has_fp)
421 {
422 ptrace_in.pid = inferior_pid;
423 ptrace_out.info.more_data = (caddr_t) &inferior_fp_registers;
424 status = net_ptrace_clnt_call (PTRACE_GETFPREGS,
425 &ptrace_in, &ptrace_out);
426 if (status)
427 error (rpcerr);
428 if (ptrace_out.status == -1)
429 {
430 errno = ptrace_out.errno;
431 perror_with_name ("net_ptrace_clnt_call(PTRACE_GETFPREGS)");
432 }
433
434 bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
435 REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
436 }
437 else
438 {
439 bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
440 REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
441 }
442#endif
443 }
dd3b648e
RP
444#else /* not 960, thus must be 68000: FIXME! */
445
dd3b648e
RP
446 if (target_has_fp)
447 {
448 ptrace_in.pid = inferior_pid;
8616205a
SG
449 ptrace_out.info.more_data = (caddr_t) &out_data;
450 out_data.len = 8 * REGISTER_RAW_SIZE (FP0_REGNUM) /* FIXME */
451 + (3 * sizeof (REGISTER_TYPE));
452 out_data.bytes = (caddr_t) &registers[REGISTER_BYTE (FP0_REGNUM)];
453
dd3b648e
RP
454 status = net_ptrace_clnt_call (PTRACE_GETFPREGS, &ptrace_in, &ptrace_out);
455 if (status)
456 error (rpcerr);
457 if (ptrace_out.status == -1)
458 {
459 errno = ptrace_out.errno;
8616205a 460 perror_with_name ("net_ptrace_clnt_call(PTRACE_GETFPREGS)");
dd3b648e 461 }
dd3b648e
RP
462 }
463 else
464 {
465 bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
8616205a 466 8 * REGISTER_RAW_SIZE (FP0_REGNUM));
dd3b648e 467 bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
8616205a 468 3 * sizeof (REGISTER_TYPE));
dd3b648e
RP
469 }
470#endif /* various architectures */
dd3b648e
RP
471}
472
473/* Prepare to store registers. Since we will store all of them,
474 read out their current values now. */
475
8616205a 476static void
dd3b648e
RP
477vx_prepare_to_store ()
478{
4ddd278f
JG
479 /* Fetch all registers, if any of them are not yet fetched. */
480 read_register_bytes (0, NULL, REGISTER_BYTES);
dd3b648e
RP
481}
482
483
484/* Store our register values back into the inferior.
485 If REGNO is -1, do this for all registers.
486 Otherwise, REGNO specifies which register (so we can save time). */
487 /* FIXME, look at REGNO to save time here */
488
8616205a 489static void
dd3b648e
RP
490vx_write_register (regno)
491 int regno;
492{
8616205a
SG
493 C_bytes in_data;
494 C_bytes out_data;
dd3b648e
RP
495 extern char registers[];
496 int status;
497 Rptrace ptrace_in;
498 Ptrace_return ptrace_out;
499
500 bzero ((char *) &ptrace_in, sizeof (ptrace_in));
501 bzero ((char *) &ptrace_out, sizeof (ptrace_out));
502
8616205a
SG
503 ptrace_in.pid = inferior_pid;
504 ptrace_in.info.ttype = DATA;
505 ptrace_in.info.more_data = (caddr_t) &in_data;
506
507 in_data.bytes = registers;
508
dd3b648e
RP
509#ifdef I80960
510
afc5505f 511 in_data.len = (16 + 16 + 3) * sizeof (REGISTER_TYPE);
dd3b648e
RP
512
513#else /* not 960 -- assume 68k -- FIXME */
514
8616205a 515 in_data.len = 18 * sizeof (REGISTER_TYPE);
dd3b648e
RP
516
517#endif /* Different register sets */
518
dd3b648e
RP
519 /* XXX change second param to be a proc number */
520 status = net_ptrace_clnt_call (PTRACE_SETREGS, &ptrace_in, &ptrace_out);
521 if (status)
522 error (rpcerr);
523 if (ptrace_out.status == -1)
524 {
525 errno = ptrace_out.errno;
8616205a 526 perror_with_name ("net_ptrace_clnt_call(PTRACE_SETREGS)");
dd3b648e
RP
527 }
528
529 /* Store floating point registers if the target has them. */
530
531 if (target_has_fp)
532 {
8616205a
SG
533 ptrace_in.pid = inferior_pid;
534 ptrace_in.info.ttype = DATA;
535 ptrace_in.info.more_data = (caddr_t) &in_data;
536
537
dd3b648e 538#ifdef I80960
afc5505f
KR
539#if 0 /* @@ Not supported by target. */
540 in_data.bytes = &registers[REGISTER_BYTE (FP0_REGNUM)];
541 in_data.len = 4 * REGISTER_RAW_SIZE (FP0_REGNUM);
542#endif
dd3b648e
RP
543#else /* not 960 -- assume 68k -- FIXME */
544
8616205a
SG
545 in_data.bytes = &registers[REGISTER_BYTE (FP0_REGNUM)];
546 in_data.len = (8 * REGISTER_RAW_SIZE (FP0_REGNUM)
547 + (3 * sizeof (REGISTER_TYPE)));
dd3b648e
RP
548
549#endif /* Different register sets */
550
dd3b648e
RP
551 status = net_ptrace_clnt_call (PTRACE_SETFPREGS, &ptrace_in, &ptrace_out);
552 if (status)
553 error (rpcerr);
554 if (ptrace_out.status == -1)
555 {
556 errno = ptrace_out.errno;
8616205a 557 perror_with_name ("net_ptrace_clnt_call(PTRACE_SETFPREGS)");
dd3b648e
RP
558 }
559 }
dd3b648e
RP
560}
561
562/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
563 to debugger memory starting at MYADDR. WRITE is true if writing to the
564 inferior.
565 Result is the number of bytes written or read (zero if error). The
566 protocol allows us to return a negative count, indicating that we can't
567 handle the current address but can handle one N bytes further, but
568 vxworks doesn't give us that information. */
569
8616205a 570static int
8f1f2a72 571vx_xfer_memory (memaddr, myaddr, len, write, target)
dd3b648e
RP
572 CORE_ADDR memaddr;
573 char *myaddr;
574 int len;
8f1f2a72
JG
575 int write;
576 struct target_ops *target; /* ignored */
dd3b648e
RP
577{
578 int status;
579 Rptrace ptrace_in;
580 Ptrace_return ptrace_out;
581 C_bytes data;
582
583 bzero ((char *) &ptrace_in, sizeof (ptrace_in));
584 bzero ((char *) &ptrace_out, sizeof (ptrace_out));
585
586 ptrace_in.pid = inferior_pid; /* XXX pid unnecessary for READDATA */
587 ptrace_in.addr = (int) memaddr; /* Where from */
588 ptrace_in.data = len; /* How many bytes */
589
590 if (write)
591 {
592 ptrace_in.info.ttype = DATA;
593 ptrace_in.info.more_data = (caddr_t) &data;
594
595 data.bytes = (caddr_t) myaddr; /* Where from */
596 data.len = len; /* How many bytes (again, for XDR) */
597
598 /* XXX change second param to be a proc number */
599 status = net_ptrace_clnt_call (PTRACE_WRITEDATA, &ptrace_in, &ptrace_out);
600 }
601 else
602 {
603 ptrace_out.info.more_data = (caddr_t) &data;
604 data.bytes = myaddr; /* Where to */
605 data.len = len; /* How many (again, for XDR) */
606
607 /* XXX change second param to be a proc number */
608 status = net_ptrace_clnt_call (PTRACE_READDATA, &ptrace_in, &ptrace_out);
609 }
610
611 if (status)
612 error (rpcerr);
613 if (ptrace_out.status == -1)
614 {
615 return 0; /* No bytes moved */
616 }
617 return len; /* Moved *all* the bytes */
618}
619
8616205a 620static void
dd3b648e
RP
621vx_files_info ()
622{
623 printf ("\tAttached to host `%s'", vx_host);
624 printf (", which has %sfloating point", target_has_fp? "": "no ");
625 printf (".\n");
626}
627
8616205a 628static void
dd3b648e
RP
629vx_run_files_info ()
630{
e3af0493 631 printf ("\tRunning %s VxWorks process %s",
dd3b648e 632 vx_running? "child": "attached",
e3af0493 633 local_hex_string(inferior_pid));
dd3b648e
RP
634 if (vx_running)
635 printf (", function `%s'", vx_running);
636 printf(".\n");
637}
638
8616205a 639static void
dd3b648e
RP
640vx_resume (step, siggnal)
641 int step;
642 int siggnal;
643{
644 int status;
645 Rptrace ptrace_in;
646 Ptrace_return ptrace_out;
647
648 if (siggnal != 0 && siggnal != stop_signal)
649 error ("Cannot send signals to VxWorks processes");
650
651 bzero ((char *) &ptrace_in, sizeof (ptrace_in));
652 bzero ((char *) &ptrace_out, sizeof (ptrace_out));
653
654 ptrace_in.pid = inferior_pid;
655 ptrace_in.addr = 1; /* Target side insists on this, or it panics. */
656
657 /* XXX change second param to be a proc number */
658 status = net_ptrace_clnt_call (step? PTRACE_SINGLESTEP: PTRACE_CONT,
659 &ptrace_in, &ptrace_out);
660 if (status)
661 error (rpcerr);
662 if (ptrace_out.status == -1)
663 {
664 errno = ptrace_out.errno;
665 perror_with_name ("Resuming remote process");
666 }
667}
668
8616205a 669static void
dd3b648e
RP
670vx_mourn_inferior ()
671{
672 pop_target (); /* Pop back to no-child state */
673 generic_mourn_inferior ();
674}
675
676\f
677/* This function allows the addition of incrementally linked object files. */
678
8616205a 679static void
dd3b648e
RP
680vx_load_command (arg_string, from_tty)
681 char* arg_string;
682 int from_tty;
683{
684 CORE_ADDR text_addr;
685 CORE_ADDR data_addr;
686 CORE_ADDR bss_addr;
687
688 if (arg_string == 0)
689 error ("The load command takes a file name");
690
691 arg_string = tilde_expand (arg_string);
692 make_cleanup (free, arg_string);
693
694 dont_repeat ();
695
696 QUIT;
697 immediate_quit++;
698 if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
699 error ("Load failed on target machine");
700 immediate_quit--;
701
702 /* FIXME, for now we ignore data_addr and bss_addr. */
4ed3a9ea 703 symbol_file_add (arg_string, from_tty, text_addr, 0, 0, 0);
dd3b648e
RP
704}
705
706#ifdef FIXME /* Not ready for prime time */
707/* Single step the target program at the source or machine level.
708 Takes an error exit if rpc fails.
709 Returns -1 if remote single-step operation fails, else 0. */
710
711static int
712net_step ()
713{
714 enum clnt_stat status;
715 int step_status;
716 SOURCE_STEP source_step;
717
718 source_step.taskId = inferior_pid;
719
720 if (step_range_end)
721 {
722 source_step.startAddr = step_range_start;
723 source_step.endAddr = step_range_end;
724 }
725 else
726 {
727 source_step.startAddr = 0;
728 source_step.endAddr = 0;
729 }
730
731 status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
732 xdr_int, &step_status);
733
734 if (status == RPC_SUCCESS)
735 return step_status;
736 else
737 error (rpcerr);
738}
739#endif
740
741/* Emulate ptrace using RPC calls to the VxWorks target system.
742 Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */
743
744static int
745net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
746 enum ptracereq request;
747 Rptrace *pPtraceIn;
748 Ptrace_return *pPtraceOut;
749{
750 enum clnt_stat status;
751
752 status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
753 pPtraceOut);
754
755 if (status != RPC_SUCCESS)
756 return -1;
757
758 return 0;
759}
760
761/* Query the target for the name of the file from which VxWorks was
762 booted. pBootFile is the address of a pointer to the buffer to
763 receive the file name; if the pointer pointed to by pBootFile is
764 NULL, memory for the buffer will be allocated by XDR.
765 Returns -1 if rpc failed, 0 otherwise. */
766
8616205a 767static int
dd3b648e
RP
768net_get_boot_file (pBootFile)
769 char **pBootFile;
770{
771 enum clnt_stat status;
772
773 status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
774 xdr_wrapstring, pBootFile);
775 return (status == RPC_SUCCESS) ? 0 : -1;
776}
777
778/* Fetch a list of loaded object modules from the VxWorks target.
779 Returns -1 if rpc failed, 0 otherwise
780 There's no way to check if the returned loadTable is correct.
781 VxWorks doesn't check it. */
782
8616205a 783static int
dd3b648e
RP
784net_get_symbols (pLoadTable)
785 ldtabl *pLoadTable; /* return pointer to ldtabl here */
786{
787 enum clnt_stat status;
788
789 bzero ((char *) pLoadTable, sizeof (struct ldtabl));
790
791 status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
792 return (status == RPC_SUCCESS) ? 0 : -1;
793}
794
795/* Look up a symbol in the VxWorks target's symbol table.
796 Returns status of symbol read on target side (0=success, -1=fail)
797 Returns -1 and complain()s if rpc fails. */
798
799struct complaint cant_contact_target =
800 {"Lost contact with VxWorks target", 0, 0};
801
8616205a 802static int
dd3b648e
RP
803vx_lookup_symbol (name, pAddr)
804 char *name; /* symbol name */
805 CORE_ADDR *pAddr;
806{
807 enum clnt_stat status;
808 SYMBOL_ADDR symbolAddr;
809
810 *pAddr = 0;
811 bzero ((char *) &symbolAddr, sizeof (symbolAddr));
812
813 status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
814 xdr_SYMBOL_ADDR, &symbolAddr);
815 if (status != RPC_SUCCESS) {
816 complain (&cant_contact_target, 0);
817 return -1;
818 }
819
820 *pAddr = symbolAddr.addr;
821 return symbolAddr.status;
822}
823
824/* Check to see if the VxWorks target has a floating point coprocessor.
825 Returns 1 if target has floating point processor, 0 otherwise.
826 Calls error() if rpc fails. */
827
8616205a 828static int
dd3b648e
RP
829net_check_for_fp ()
830{
831 enum clnt_stat status;
832 bool_t fp = 0; /* true if fp processor is present on target board */
833
834 status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
835 if (status != RPC_SUCCESS)
836 error (rpcerr);
837
838 return (int) fp;
839}
840
841/* Establish an RPC connection with the VxWorks target system.
842 Calls error () if unable to establish connection. */
843
8616205a 844static void
dd3b648e
RP
845net_connect (host)
846 char *host;
847{
848 struct sockaddr_in destAddr;
849 struct hostent *destHost;
850
851 /* get the internet address for the given host */
852
853 if ((destHost = (struct hostent *) gethostbyname (host)) == NULL)
854 error ("Invalid hostname. Couldn't find remote host address.");
855
856 bzero (&destAddr, sizeof (destAddr));
857
858 destAddr.sin_addr.s_addr = * (u_long *) destHost->h_addr;
859 destAddr.sin_family = AF_INET;
860 destAddr.sin_port = 0; /* set to actual port that remote
861 ptrace is listening on. */
862
863 /* Create a tcp client transport on which to issue
864 calls to the remote ptrace server. */
865
866 ptraceSock = RPC_ANYSOCK;
867 pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
868 /* FIXME, here is where we deal with different version numbers of the proto */
869
870 if (pClient == NULL)
871 {
872 clnt_pcreateerror ("\tnet_connect");
873 error ("Couldn't connect to remote target.");
874 }
875}
876\f
877/* Sleep for the specified number of milliseconds
878 * (assumed to be less than 1000).
879 * If select () is interrupted, returns immediately;
880 * takes an error exit if select () fails for some other reason.
881 */
882
883static void
884sleep_ms (ms)
885 long ms;
886{
887 struct timeval select_timeout;
888 int status;
889
890 select_timeout.tv_sec = 0;
891 select_timeout.tv_usec = ms * 1000;
892
893 status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &select_timeout);
894
895 if (status < 0 && errno != EINTR)
896 perror_with_name ("select");
897}
898
899/* Wait for control to return from inferior to debugger.
900 If inferior gets a signal, we may decide to start it up again
901 instead of returning. That is why there is a loop in this function.
902 When this function actually returns it means the inferior
903 should be left stopped and GDB should read more commands. */
904
905/* For network debugging with VxWorks.
906 * VxWorks knows when tasks hit breakpoints, receive signals, exit, etc,
907 * so vx_wait() receives this information directly from
908 * VxWorks instead of trying to figure out what happenned via a wait() call.
909 */
910
911static int
912vx_wait (status)
913 int *status;
914{
915 register int pid;
916 WAITTYPE w;
917 RDB_EVENT rdbEvent;
918 int quit_failed;
919
920 do
921 {
922 /* If CTRL-C is hit during this loop,
923 suspend the inferior process. */
924
925 quit_failed = 0;
926 if (quit_flag)
927 {
928 quit_failed = (net_quit () == -1);
929 quit_flag = 0;
930 }
931
932 /* If a net_quit () or net_wait () call has failed,
933 allow the user to break the connection with the target.
934 We can't simply error () out of this loop, since the
935 data structures representing the state of the inferior
936 are in an inconsistent state. */
937
938 if (quit_failed || net_wait (&rdbEvent) == -1)
939 {
940 terminal_ours ();
941 if (query ("Can't %s. Disconnect from target system? ",
942 (quit_failed) ? "suspend remote task"
943 : "get status of remote task"))
944 {
945 target_mourn_inferior();
946 error ("Use the \"target\" command to reconnect.");
947 }
948 else
949 {
950 terminal_inferior ();
951 continue;
952 }
953 }
954
955 pid = rdbEvent.taskId;
956 if (pid == 0)
957 {
958 sleep_ms (200); /* FIXME Don't kill the network too badly */
959 }
960 else if (pid != inferior_pid)
e3af0493 961 fatal ("Bad pid for debugged task: %s\n", local_hex_string(pid));
dd3b648e
RP
962 } while (pid == 0);
963
964 /* FIXME, eventually do more then SIGTRAP on everything... */
965 switch (rdbEvent.eventType)
966 {
967 case EVENT_EXIT:
968 WSETEXIT (w, 0);
969 /* FIXME is it possible to distinguish between a
970 XXX normal vs abnormal exit in VxWorks? */
971 break;
972
973 case EVENT_START: /* Task was just started. */
974 WSETSTOP (w, SIGTRAP);
975 break;
976
977 case EVENT_STOP:
978 WSETSTOP (w, SIGTRAP);
979 /* XXX was it stopped by a signal? act accordingly */
980 break;
981
982 case EVENT_BREAK: /* Breakpoint was hit. */
983 WSETSTOP (w, SIGTRAP);
984 break;
985
986 case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */
987 WSETSTOP (w, SIGINT);
988 break;
989
990 case EVENT_BUS_ERR: /* Task made evil nasty reference. */
991 WSETSTOP (w, SIGBUS);
992 break;
993
994 case EVENT_ZERO_DIV: /* Division by zero */
995 WSETSTOP (w, SIGFPE); /* Like Unix, call it a float exception. */
021959e2 996 break;
dd3b648e
RP
997
998 case EVENT_SIGNAL:
999 /* The target is not running Unix, and its
1000 faults/traces do not map nicely into Unix signals.
1001 Make sure they do not get confused with Unix signals
1002 by numbering them with values higher than the highest
1003 legal Unix signal. code in the arch-dependent PRINT_RANDOM_SIGNAL
1004 routine will interpret the value for wait_for_inferior. */
1005 WSETSTOP (w, rdbEvent.sigType + NSIG);
1006 break;
1007 } /* switch */
1008 *status = *(int *)&w; /* Grumble union wait crap Grumble */
1009 return pid;
1010}
1011\f
1012static int
1013symbol_stub (arg)
bdbd5f50 1014 char *arg;
dd3b648e 1015{
bdbd5f50 1016 symbol_file_command (arg, 0);
dd3b648e
RP
1017 return 1;
1018}
1019
1020static int
1021add_symbol_stub (arg)
bdbd5f50 1022 char *arg;
dd3b648e
RP
1023{
1024 struct ldfile *pLoadFile = (struct ldfile *)arg;
1025
1026 printf("\t%s: ", pLoadFile->name);
4ed3a9ea 1027 symbol_file_add (pLoadFile->name, 0, pLoadFile->txt_addr, 0, 0, 0);
dd3b648e
RP
1028 printf ("ok\n");
1029 return 1;
1030}
1031/* Target command for VxWorks target systems.
1032
1033 Used in vxgdb. Takes the name of a remote target machine
1034 running vxWorks and connects to it to initialize remote network
1035 debugging. */
1036
1037static void
1038vx_open (args, from_tty)
1039 char *args;
1040 int from_tty;
1041{
1042 extern int close ();
1043 char *bootFile;
1044 extern char *source_path;
1045 struct ldtabl loadTable;
1046 struct ldfile *pLoadFile;
1047 int i;
1048 extern CLIENT *pClient;
1049
1050 if (!args)
1051 error_no_arg ("target machine name");
1052
70dcc196
JK
1053 target_preopen (from_tty);
1054
dd3b648e
RP
1055 unpush_target (&vx_ops);
1056 printf ("Attaching remote machine across net...\n");
1057 fflush (stdout);
1058
1059 /* Allow the user to kill the connect attempt by typing ^C.
1060 Wait until the call to target_has_fp () completes before
1061 disallowing an immediate quit, since even if net_connect ()
1062 is successful, the remote debug server might be hung. */
1063
1064 immediate_quit++;
1065
1066 net_connect (args);
1067 target_has_fp = net_check_for_fp ();
1068 printf_filtered ("Connected to %s.\n", args);
1069
1070 immediate_quit--;
1071
1072 push_target (&vx_ops);
1073
1074 /* Save a copy of the target host's name. */
1075 vx_host = savestring (args, strlen (args));
1076
1077 /* Find out the name of the file from which the target was booted
1078 and load its symbol table. */
1079
1080 printf_filtered ("Looking in Unix path for all loaded modules:\n");
1081 bootFile = NULL;
1082 if (!net_get_boot_file (&bootFile))
1083 {
1084 if (*bootFile) {
1085 printf_filtered ("\t%s: ", bootFile);
bdbd5f50 1086 if (catch_errors (symbol_stub, bootFile,
06b6c733 1087 "Error while reading symbols from boot file:\n"))
dd3b648e
RP
1088 puts_filtered ("ok\n");
1089 } else if (from_tty)
1090 printf ("VxWorks kernel symbols not loaded.\n");
1091 }
1092 else
1093 error ("Can't retrieve boot file name from target machine.");
1094
1095 clnt_freeres (pClient, xdr_wrapstring, &bootFile);
1096
1097 if (net_get_symbols (&loadTable) != 0)
1098 error ("Can't read loaded modules from target machine");
1099
1100 i = 0-1;
1101 while (++i < loadTable.tbl_size)
1102 {
1103 QUIT; /* FIXME, avoids clnt_freeres below: mem leak */
1104 pLoadFile = &loadTable.tbl_ent [i];
1105#ifdef WRS_ORIG
1106 {
1107 register int desc;
1108 struct cleanup *old_chain;
1109 char *fullname = NULL;
1110
1111 desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
1112 if (desc < 0)
1113 perror_with_name (pLoadFile->name);
1114 old_chain = make_cleanup (close, desc);
1115 add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
1116 pLoadFile->bss_addr);
1117 do_cleanups (old_chain);
1118 }
1119#else
1120 /* Botches, FIXME:
1121 (1) Searches the PATH, not the source path.
1122 (2) data and bss are assumed to be at the usual offsets from text. */
bdbd5f50 1123 catch_errors (add_symbol_stub, (char *)pLoadFile, (char *)0);
dd3b648e
RP
1124#endif
1125 }
1126 printf_filtered ("Done.\n");
1127
1128 clnt_freeres (pClient, xdr_ldtabl, &loadTable);
1129}
1130\f
1131/* attach_command --
1132 takes a task started up outside of gdb and ``attaches'' to it.
1133 This stops it cold in its tracks and allows us to start tracing it. */
1134
1135static void
1136vx_attach (args, from_tty)
1137 char *args;
1138 int from_tty;
1139{
1140 int pid;
1141 char *cptr = 0;
1142 Rptrace ptrace_in;
1143 Ptrace_return ptrace_out;
1144 int status;
1145
1146 dont_repeat();
1147
1148 if (!args)
1149 error_no_arg ("process-id to attach");
1150
1151 pid = strtol (args, &cptr, 0);
1152 if ((cptr == args) || (*cptr != '\0'))
1153 error ("Invalid process-id -- give a single number in decimal or 0xhex");
1154
1155 if (from_tty)
e3af0493 1156 printf ("Attaching pid %s.\n", local_hex_string(pid));
dd3b648e
RP
1157
1158 bzero ((char *)&ptrace_in, sizeof (ptrace_in));
1159 bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1160 ptrace_in.pid = pid;
1161
1162 status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
1163 if (status == -1)
1164 error (rpcerr);
1165 if (ptrace_out.status == -1)
1166 {
1167 errno = ptrace_out.errno;
1168 perror_with_name ("Attaching remote process");
1169 }
1170
1171 /* It worked... */
1172 push_target (&vx_run_ops);
1173 inferior_pid = pid;
1174 vx_running = 0;
1175
dd3b648e
RP
1176 mark_breakpoints_out ();
1177
1178 /* Set up the "saved terminal modes" of the inferior
1179 based on what modes we are starting it with. */
1180 target_terminal_init ();
1181
1182 /* Install inferior's terminal modes. */
1183 target_terminal_inferior ();
1184
1185 /* We will get a task spawn event immediately. */
1186 init_wait_for_inferior ();
1187 clear_proceed_status ();
1188 stop_soon_quietly = 1;
1189 wait_for_inferior ();
1190 stop_soon_quietly = 0;
1191 normal_stop ();
1192}
1193
1194
1195/* detach_command --
1196 takes a program previously attached to and detaches it.
1197 The program resumes execution and will no longer stop
1198 on signals, etc. We better not have left any breakpoints
1199 in the program or it'll die when it hits one. For this
1200 to work, it may be necessary for the process to have been
1201 previously attached. It *might* work if the program was
1202 started via the normal ptrace (PTRACE_TRACEME). */
1203
1204static void
1205vx_detach (args, from_tty)
1206 char *args;
1207 int from_tty;
1208{
1209 Rptrace ptrace_in;
1210 Ptrace_return ptrace_out;
1211 int signal = 0;
1212 int status;
1213
1214 if (args)
1215 error ("Argument given to VxWorks \"detach\".");
1216
1217 if (from_tty)
e3af0493 1218 printf ("Detaching pid %s.\n", local_hex_string(inferior_pid));
dd3b648e
RP
1219
1220 if (args) /* FIXME, should be possible to leave suspended */
1221 signal = atoi (args);
1222
1223 bzero ((char *)&ptrace_in, sizeof (ptrace_in));
1224 bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1225 ptrace_in.pid = inferior_pid;
1226
1227 status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
1228 if (status == -1)
1229 error (rpcerr);
1230 if (ptrace_out.status == -1)
1231 {
1232 errno = ptrace_out.errno;
1233 perror_with_name ("Detaching VxWorks process");
1234 }
1235
1236 inferior_pid = 0;
1237 pop_target (); /* go back to non-executing VxWorks connection */
1238}
1239
1240/* vx_kill -- takes a running task and wipes it out. */
1241
1242static void
afc5505f 1243vx_kill ()
dd3b648e
RP
1244{
1245 Rptrace ptrace_in;
1246 Ptrace_return ptrace_out;
1247 int status;
1248
afc5505f 1249 printf ("Killing pid %s.\n", local_hex_string(inferior_pid));
dd3b648e
RP
1250
1251 bzero ((char *)&ptrace_in, sizeof (ptrace_in));
1252 bzero ((char *)&ptrace_out, sizeof (ptrace_out));
1253 ptrace_in.pid = inferior_pid;
1254
1255 status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
1256 if (status == -1)
1257 error (rpcerr);
1258 if (ptrace_out.status == -1)
1259 {
1260 errno = ptrace_out.errno;
1261 perror_with_name ("Killing VxWorks process");
1262 }
1263
1264 /* If it gives good status, the process is *gone*, no events remain. */
1265 inferior_pid = 0;
1266 pop_target (); /* go back to non-executing VxWorks connection */
1267}
1268
1269/* Clean up from the VxWorks process target as it goes away. */
1270
8616205a 1271static void
dd3b648e
RP
1272vx_proc_close (quitting)
1273 int quitting;
1274{
1275 inferior_pid = 0; /* No longer have a process. */
1276 if (vx_running)
1277 free (vx_running);
1278 vx_running = 0;
1279}
1280\f
dd3b648e
RP
1281/* Make an RPC call to the VxWorks target.
1282 Returns RPC status. */
1283
1284static enum clnt_stat
1285net_clnt_call (procNum, inProc, in, outProc, out)
1286 enum ptracereq procNum;
1287 xdrproc_t inProc;
1288 char *in;
1289 xdrproc_t outProc;
1290 char *out;
1291{
1292 enum clnt_stat status;
1293
1294 status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
1295
1296 if (status != RPC_SUCCESS)
1297 clnt_perrno (status);
1298
1299 return status;
1300}
1301
1302/* Clean up before losing control. */
1303
8616205a 1304static void
dd3b648e
RP
1305vx_close (quitting)
1306 int quitting;
1307{
1308 if (pClient)
1309 clnt_destroy (pClient); /* The net connection */
1310 pClient = 0;
1311
1312 if (vx_host)
1313 free (vx_host); /* The hostname */
1314 vx_host = 0;
1315}
1316
70dcc196
JK
1317/* A vxprocess target should be started via "run" not "target". */
1318/*ARGSUSED*/
1319static void
1320vx_proc_open (name, from_tty)
1321 char *name;
1322 int from_tty;
1323{
1324 error ("Use the \"run\" command to start a VxWorks process.");
1325}
dd3b648e
RP
1326
1327/* Target ops structure for accessing memory and such over the net */
1328
1329struct target_ops vx_ops = {
1330 "vxworks", "VxWorks target memory via RPC over TCP/IP",
70dcc196
JK
1331 "Use VxWorks target memory. \n\
1332Specify the name of the machine to connect to.",
dd3b648e
RP
1333 vx_open, vx_close, vx_attach, 0, /* vx_detach, */
1334 0, 0, /* resume, wait */
1335 0, 0, /* read_reg, write_reg */
8616205a 1336 0, host_convert_to_virtual, host_convert_from_virtual, /* prep_to_store, */
dd3b648e
RP
1337 vx_xfer_memory, vx_files_info,
1338 0, 0, /* insert_breakpoint, remove_breakpoint */
1339 0, 0, 0, 0, 0, /* terminal stuff */
1340 0, /* vx_kill, */
8f1f2a72 1341 vx_load_command,
dd3b648e
RP
1342 vx_lookup_symbol,
1343 vx_create_inferior, 0, /* mourn_inferior */
1344 core_stratum, 0, /* next */
1345 1, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */
8f1f2a72 1346 0, 0, /* Section pointers */
dd3b648e
RP
1347 OPS_MAGIC, /* Always the last thing */
1348};
1349
1350/* Target ops structure for accessing VxWorks child processes over the net */
1351
1352struct target_ops vx_run_ops = {
1353 "vxprocess", "VxWorks process",
70dcc196
JK
1354 "VxWorks process, started by the \"run\" command.",
1355 vx_proc_open, vx_proc_close, 0, vx_detach, /* vx_attach */
dd3b648e
RP
1356 vx_resume, vx_wait,
1357 vx_read_register, vx_write_register,
8616205a 1358 vx_prepare_to_store, host_convert_to_virtual, host_convert_from_virtual,
dd3b648e
RP
1359 vx_xfer_memory, vx_run_files_info,
1360 vx_insert_breakpoint, vx_remove_breakpoint,
1361 0, 0, 0, 0, 0, /* terminal stuff */
1362 vx_kill,
8f1f2a72 1363 vx_load_command,
dd3b648e
RP
1364 vx_lookup_symbol,
1365 0, vx_mourn_inferior,
1366 process_stratum, 0, /* next */
1367 0, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1368 /* all_mem is off to avoid spurious msg in "i files" */
8f1f2a72 1369 0, 0, /* Section pointers */
dd3b648e
RP
1370 OPS_MAGIC, /* Always the last thing */
1371};
1372/* ==> Remember when reading at end of file, there are two "ops" structs here. */
1373\f
1374void
1375_initialize_vx ()
1376{
1377 add_target (&vx_ops);
1378 add_target (&vx_run_ops);
1379}
This page took 0.126228 seconds and 4 git commands to generate.