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