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