OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [remote-vx.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Memory-access and commands for remote VxWorks processes, for GDB.
2
 
3
   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1998, 1999,
4
   2000, 2001, 2002 Free Software Foundation, Inc.
5
 
6
   Contributed by Wind River Systems and Cygnus Support.
7
 
8
   This file is part of GDB.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 2 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program; if not, write to the Free Software
22
   Foundation, Inc., 59 Temple Place - Suite 330,
23
   Boston, MA 02111-1307, USA.  */
24
 
25
#include "defs.h"
26
#include "frame.h"
27
#include "inferior.h"
28
#include "target.h"
29
#include "gdbcore.h"
30
#include "command.h"
31
#include "symtab.h"
32
#include "complaints.h"
33
#include "gdbcmd.h"
34
#include "bfd.h"                /* Required by objfiles.h.  */
35
#include "symfile.h"
36
#include "objfiles.h"
37
#include "gdb-stabs.h"
38
#include "regcache.h"
39
 
40
#include "gdb_string.h"
41
#include <errno.h>
42
#include <signal.h>
43
#include <fcntl.h>
44
#include <sys/types.h>
45
#include <sys/socket.h>
46
#define malloc bogon_malloc     /* Sun claims "char *malloc()" not void * */
47
#define free bogon_free         /* Sun claims "int free()" not void */
48
#define realloc bogon_realloc   /* Sun claims "char *realloc()", not void * */
49
#include <rpc/rpc.h>
50
#undef malloc
51
#undef free
52
#undef realloc
53
#include <sys/time.h>           /* UTek's <rpc/rpc.h> doesn't #incl this */
54
#include <netdb.h>
55
#include "vx-share/ptrace.h"
56
#include "vx-share/xdr_ptrace.h"
57
#include "vx-share/xdr_ld.h"
58
#include "vx-share/xdr_rdb.h"
59
#include "vx-share/dbgRpcLib.h"
60
 
61
#include <symtab.h>
62
 
63
/* Maximum number of bytes to transfer in a single
64
   PTRACE_{READ,WRITE}DATA request.  */
65
#define VX_MEMXFER_MAX 4096
66
 
67
extern void vx_read_register ();
68
extern void vx_write_register ();
69
extern void symbol_file_command ();
70
extern int stop_soon_quietly;   /* for wait_for_inferior */
71
 
72
static int net_step ();
73
static int net_ptrace_clnt_call ();     /* Forward decl */
74
static enum clnt_stat net_clnt_call ();         /* Forward decl */
75
 
76
/* Target ops structure for accessing memory and such over the net */
77
 
78
static struct target_ops vx_ops;
79
 
80
/* Target ops structure for accessing VxWorks child processes over the net */
81
 
82
static struct target_ops vx_run_ops;
83
 
84
/* Saved name of target host and called function for "info files".
85
   Both malloc'd.  */
86
 
87
static char *vx_host;
88
static char *vx_running;        /* Called function */
89
 
90
/* Nonzero means target that is being debugged remotely has a floating
91
   point processor.  */
92
 
93
int target_has_fp;
94
 
95
/* Default error message when the network is forking up.  */
96
 
97
static const char rpcerr[] = "network target debugging:  rpc error";
98
 
99
CLIENT *pClient;                /* client used in net debugging */
100
static int ptraceSock = RPC_ANYSOCK;
101
 
102
enum clnt_stat net_clnt_call ();
103
static void parse_args ();
104
 
105
static struct timeval rpcTimeout =
106
{10, 0};
107
 
108
static char *skip_white_space ();
109
static char *find_white_space ();
110
 
111
/* Tell the VxWorks target system to download a file.
112
   The load addresses of the text, data, and bss segments are
113
   stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively).
114
   Returns 0 for success, -1 for failure.  */
115
 
116
static int
117
net_load (char *filename, CORE_ADDR *pTextAddr, CORE_ADDR *pDataAddr,
118
          CORE_ADDR *pBssAddr)
119
{
120
  enum clnt_stat status;
121
  struct ldfile ldstruct;
122
  struct timeval load_timeout;
123
 
124
  memset ((char *) &ldstruct, '\0', sizeof (ldstruct));
125
 
126
  /* We invoke clnt_call () here directly, instead of through
127
     net_clnt_call (), because we need to set a large timeout value.
128
     The load on the target side can take quite a while, easily
129
     more than 10 seconds.  The user can kill this call by typing
130
     CTRL-C if there really is a problem with the load.
131
 
132
     Do not change the tv_sec value without checking -- select() imposes
133
     a limit of 10**8 on it for no good reason that I can see...  */
134
 
135
  load_timeout.tv_sec = 99999999;       /* A large number, effectively inf. */
136
  load_timeout.tv_usec = 0;
137
 
138
  status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
139
                      &ldstruct, load_timeout);
140
 
141
  if (status == RPC_SUCCESS)
142
    {
143
      if (*ldstruct.name == 0)   /* load failed on VxWorks side */
144
        return -1;
145
      *pTextAddr = ldstruct.txt_addr;
146
      *pDataAddr = ldstruct.data_addr;
147
      *pBssAddr = ldstruct.bss_addr;
148
      return 0;
149
    }
150
  else
151
    return -1;
152
}
153
 
154
/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
155
 
156
static int
157
net_break (int addr, u_long procnum)
158
{
159
  enum clnt_stat status;
160
  int break_status;
161
  Rptrace ptrace_in;            /* XXX This is stupid.  It doesn't need to be a ptrace
162
                                   structure.  How about something smaller? */
163
 
164
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
165
  break_status = 0;
166
 
167
  ptrace_in.addr = addr;
168
  ptrace_in.pid = PIDGET (inferior_ptid);
169
 
170
  status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
171
                          &break_status);
172
 
173
  if (status != RPC_SUCCESS)
174
    return errno;
175
 
176
  if (break_status == -1)
177
    return ENOMEM;
178
  return break_status;          /* probably (FIXME) zero */
179
}
180
 
181
/* returns 0 if successful, errno otherwise */
182
 
183
static int
184
vx_insert_breakpoint (int addr)
185
{
186
  return net_break (addr, VX_BREAK_ADD);
187
}
188
 
189
/* returns 0 if successful, errno otherwise */
190
 
191
static int
192
vx_remove_breakpoint (int addr)
193
{
194
  return net_break (addr, VX_BREAK_DELETE);
195
}
196
 
197
/* Start an inferior process and sets inferior_ptid to its pid.
198
   EXEC_FILE is the file to run.
199
   ALLARGS is a string containing the arguments to the program.
200
   ENV is the environment vector to pass.
201
   Returns process id.  Errors reported with error().
202
   On VxWorks, we ignore exec_file.  */
203
 
204
static void
205
vx_create_inferior (char *exec_file, char *args, char **env)
206
{
207
  enum clnt_stat status;
208
  arg_array passArgs;
209
  TASK_START taskStart;
210
 
211
  memset ((char *) &passArgs, '\0', sizeof (passArgs));
212
  memset ((char *) &taskStart, '\0', sizeof (taskStart));
213
 
214
  /* parse arguments, put them in passArgs */
215
 
216
  parse_args (args, &passArgs);
217
 
218
  if (passArgs.arg_array_len == 0)
219
    error ("You must specify a function name to run, and arguments if any");
220
 
221
  status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
222
                          xdr_TASK_START, &taskStart);
223
 
224
  if ((status != RPC_SUCCESS) || (taskStart.status == -1))
225
    error ("Can't create process on remote target machine");
226
 
227
  /* Save the name of the running function */
228
  vx_running = savestring (passArgs.arg_array_val[0],
229
                           strlen (passArgs.arg_array_val[0]));
230
 
231
  push_target (&vx_run_ops);
232
  inferior_ptid = pid_to_ptid (taskStart.pid);
233
 
234
  /* We will get a trace trap after one instruction.
235
     Insert breakpoints and continue.  */
236
 
237
  init_wait_for_inferior ();
238
 
239
  /* Set up the "saved terminal modes" of the inferior
240
     based on what modes we are starting it with.  */
241
  target_terminal_init ();
242
 
243
  /* Install inferior's terminal modes.  */
244
  target_terminal_inferior ();
245
 
246
  stop_soon_quietly = 1;
247
  wait_for_inferior ();         /* Get the task spawn event */
248
  stop_soon_quietly = 0;
249
 
250
  /* insert_step_breakpoint ();  FIXME, do we need this?  */
251
  proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
252
}
253
 
254
/* Fill ARGSTRUCT in argc/argv form with the arguments from the
255
   argument string ARGSTRING.  */
256
 
257
static void
258
parse_args (register char *arg_string, arg_array *arg_struct)
259
{
260
  register int arg_count = 0;    /* number of arguments */
261
  register int arg_index = 0;
262
  register char *p0;
263
 
264
  memset ((char *) arg_struct, '\0', sizeof (arg_array));
265
 
266
  /* first count how many arguments there are */
267
 
268
  p0 = arg_string;
269
  while (*p0 != '\0')
270
    {
271
      if (*(p0 = skip_white_space (p0)) == '\0')
272
        break;
273
      p0 = find_white_space (p0);
274
      arg_count++;
275
    }
276
 
277
  arg_struct->arg_array_len = arg_count;
278
  arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
279
                                                 * sizeof (char *));
280
 
281
  /* now copy argument strings into arg_struct.  */
282
 
283
  while (*(arg_string = skip_white_space (arg_string)))
284
    {
285
      p0 = find_white_space (arg_string);
286
      arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
287
                                                           p0 - arg_string);
288
      arg_string = p0;
289
    }
290
 
291
  arg_struct->arg_array_val[arg_count] = NULL;
292
}
293
 
294
/* Advance a string pointer across whitespace and return a pointer
295
   to the first non-white character.  */
296
 
297
static char *
298
skip_white_space (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
 
309
static char *
310
find_white_space (register char *p)
311
{
312
  register int c;
313
 
314
  while ((c = *p) != ' ' && c != '\t' && c)
315
    {
316
      if (c == '\'' || c == '"')
317
        {
318
          while (*++p != c && *p)
319
            {
320
              if (*p == '\\')
321
                p++;
322
            }
323
          if (!*p)
324
            break;
325
        }
326
      p++;
327
    }
328
  return p;
329
}
330
 
331
/* Poll the VxWorks target system for an event related
332
   to the debugged task.
333
   Returns -1 if remote wait failed, task status otherwise.  */
334
 
335
static int
336
net_wait (RDB_EVENT *pEvent)
337
{
338
  int pid;
339
  enum clnt_stat status;
340
 
341
  memset ((char *) pEvent, '\0', sizeof (RDB_EVENT));
342
 
343
  pid = PIDGET (inferior_ptid);
344
  status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT,
345
                          pEvent);
346
 
347
  /* return (status == RPC_SUCCESS)? pEvent->status: -1; */
348
  if (status == RPC_SUCCESS)
349
    return ((pEvent->status) ? 1 : 0);
350
  else if (status == RPC_TIMEDOUT)
351
    return (1);
352
  else
353
    return (-1);
354
}
355
 
356
/* Suspend the remote task.
357
   Returns -1 if suspend fails on target system, 0 otherwise.  */
358
 
359
static int
360
net_quit (void)
361
{
362
  int pid;
363
  int quit_status;
364
  enum clnt_stat status;
365
 
366
  quit_status = 0;
367
 
368
  /* don't let rdbTask suspend itself by passing a pid of 0 */
369
 
370
  if ((pid = PIDGET (inferior_ptid)) == 0)
371
    return -1;
372
 
373
  status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
374
                          &quit_status);
375
 
376
  return (status == RPC_SUCCESS) ? quit_status : -1;
377
}
378
 
379
/* Read a register or registers from the remote system.  */
380
 
381
void
382
net_read_registers (char *reg_buf, int len, u_long procnum)
383
{
384
  int status;
385
  Rptrace ptrace_in;
386
  Ptrace_return ptrace_out;
387
  C_bytes out_data;
388
  char message[100];
389
 
390
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
391
  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
392
 
393
  /* Initialize RPC input argument structure.  */
394
 
395
  ptrace_in.pid = PIDGET (inferior_ptid);
396
  ptrace_in.info.ttype = NOINFO;
397
 
398
  /* Initialize RPC return value structure.  */
399
 
400
  out_data.bytes = reg_buf;
401
  out_data.len = len;
402
  ptrace_out.info.more_data = (caddr_t) & out_data;
403
 
404
  /* Call RPC; take an error exit if appropriate.  */
405
 
406
  status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
407
  if (status)
408
    error (rpcerr);
409
  if (ptrace_out.status == -1)
410
    {
411
      errno = ptrace_out.errno_num;
412
      sprintf (message, "reading %s registers", (procnum == PTRACE_GETREGS)
413
               ? "general-purpose"
414
               : "floating-point");
415
      perror_with_name (message);
416
    }
417
}
418
 
419
/* Write register values to a VxWorks target.  REG_BUF points to a buffer
420
   containing the raw register values, LEN is the length of REG_BUF in
421
   bytes, and PROCNUM is the RPC procedure number (PTRACE_SETREGS or
422
   PTRACE_SETFPREGS).  An error exit is taken if the RPC call fails or
423
   if an error status is returned by the remote debug server.  This is
424
   a utility routine used by vx_write_register ().  */
425
 
426
void
427
net_write_registers (char *reg_buf, int len, u_long procnum)
428
{
429
  int status;
430
  Rptrace ptrace_in;
431
  Ptrace_return ptrace_out;
432
  C_bytes in_data;
433
  char message[100];
434
 
435
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
436
  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
437
 
438
  /* Initialize RPC input argument structure.  */
439
 
440
  in_data.bytes = reg_buf;
441
  in_data.len = len;
442
 
443
  ptrace_in.pid = PIDGET (inferior_ptid);
444
  ptrace_in.info.ttype = DATA;
445
  ptrace_in.info.more_data = (caddr_t) & in_data;
446
 
447
  /* Call RPC; take an error exit if appropriate.  */
448
 
449
  status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
450
  if (status)
451
    error (rpcerr);
452
  if (ptrace_out.status == -1)
453
    {
454
      errno = ptrace_out.errno_num;
455
      sprintf (message, "writing %s registers", (procnum == PTRACE_SETREGS)
456
               ? "general-purpose"
457
               : "floating-point");
458
      perror_with_name (message);
459
    }
460
}
461
 
462
/* Prepare to store registers.  Since we will store all of them,
463
   read out their current values now.  */
464
 
465
static void
466
vx_prepare_to_store (void)
467
{
468
  /* Fetch all registers, if any of them are not yet fetched.  */
469
  read_register_bytes (0, NULL, REGISTER_BYTES);
470
}
471
 
472
/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
473
   to debugger memory starting at MYADDR.  WRITE is true if writing to the
474
   inferior.  TARGET is unused.
475
   Result is the number of bytes written or read (zero if error).  The
476
   protocol allows us to return a negative count, indicating that we can't
477
   handle the current address but can handle one N bytes further, but
478
   vxworks doesn't give us that information.  */
479
 
480
static int
481
vx_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
482
                struct mem_attrib *attrib, struct target_ops *target)
483
{
484
  int status;
485
  Rptrace ptrace_in;
486
  Ptrace_return ptrace_out;
487
  C_bytes data;
488
  enum ptracereq request;
489
  int nleft, nxfer;
490
 
491
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
492
  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
493
 
494
  ptrace_in.pid = PIDGET (inferior_ptid); /* XXX pid unnecessary for READDATA */
495
  ptrace_in.addr = (int) memaddr;       /* Where from */
496
  ptrace_in.data = len;         /* How many bytes */
497
 
498
  if (write)
499
    {
500
      ptrace_in.info.ttype = DATA;
501
      ptrace_in.info.more_data = (caddr_t) & data;
502
 
503
      data.bytes = (caddr_t) myaddr;    /* Where from */
504
      data.len = len;           /* How many bytes (again, for XDR) */
505
      request = PTRACE_WRITEDATA;
506
    }
507
  else
508
    {
509
      ptrace_out.info.more_data = (caddr_t) & data;
510
      request = PTRACE_READDATA;
511
    }
512
  /* Loop until the entire request has been satisfied, transferring
513
     at most VX_MEMXFER_MAX bytes per iteration.  Break from the loop
514
     if an error status is returned by the remote debug server.  */
515
 
516
  nleft = len;
517
  status = 0;
518
 
519
  while (nleft > 0 && status == 0)
520
    {
521
      nxfer = min (nleft, VX_MEMXFER_MAX);
522
 
523
      ptrace_in.addr = (int) memaddr;
524
      ptrace_in.data = nxfer;
525
      data.bytes = (caddr_t) myaddr;
526
      data.len = nxfer;
527
 
528
      /* Request a block from the remote debug server; if RPC fails,
529
         report an error and return to debugger command level.  */
530
 
531
      if (net_ptrace_clnt_call (request, &ptrace_in, &ptrace_out))
532
        error (rpcerr);
533
 
534
      status = ptrace_out.status;
535
      if (status == 0)
536
        {
537
          memaddr += nxfer;
538
          myaddr += nxfer;
539
          nleft -= nxfer;
540
        }
541
      else
542
        {
543
          /* A target-side error has ocurred.  Set errno to the error
544
             code chosen by the target so that a later perror () will
545
             say something meaningful.  */
546
 
547
          errno = ptrace_out.errno_num;
548
        }
549
    }
550
 
551
  /* Return the number of bytes transferred.  */
552
 
553
  return (len - nleft);
554
}
555
 
556
static void
557
vx_files_info (void)
558
{
559
  printf_unfiltered ("\tAttached to host `%s'", vx_host);
560
  printf_unfiltered (", which has %sfloating point", target_has_fp ? "" : "no ");
561
  printf_unfiltered (".\n");
562
}
563
 
564
static void
565
vx_run_files_info (void)
566
{
567
  printf_unfiltered ("\tRunning %s VxWorks process %s",
568
                     vx_running ? "child" : "attached",
569
                     local_hex_string (PIDGET (inferior_ptid)));
570
  if (vx_running)
571
    printf_unfiltered (", function `%s'", vx_running);
572
  printf_unfiltered (".\n");
573
}
574
 
575
static void
576
vx_resume (ptid_t ptid, int step, enum target_signal siggnal)
577
{
578
  int status;
579
  Rptrace ptrace_in;
580
  Ptrace_return ptrace_out;
581
  CORE_ADDR cont_addr;
582
 
583
  if (ptid_equal (ptid, minus_one_ptid))
584
    ptid = inferior_ptid;
585
 
586
  if (siggnal != 0 && siggnal != stop_signal)
587
    error ("Cannot send signals to VxWorks processes");
588
 
589
  /* Set CONT_ADDR to the address at which we are continuing,
590
     or to 1 if we are continuing from where the program stopped.
591
     This conforms to traditional ptrace () usage, but at the same
592
     time has special meaning for the VxWorks remote debug server.
593
     If the address is not 1, the server knows that the target
594
     program is jumping to a new address, which requires special
595
     handling if there is a breakpoint at the new address.  */
596
 
597
  cont_addr = read_register (PC_REGNUM);
598
  if (cont_addr == stop_pc)
599
    cont_addr = 1;
600
 
601
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
602
  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
603
 
604
  ptrace_in.pid = PIDGET (ptid);
605
  ptrace_in.addr = cont_addr;   /* Target side insists on this, or it panics.  */
606
 
607
  if (step)
608
    status = net_step ();
609
  else
610
    status = net_ptrace_clnt_call (PTRACE_CONT, &ptrace_in, &ptrace_out);
611
 
612
  if (status)
613
    error (rpcerr);
614
  if (ptrace_out.status == -1)
615
    {
616
      errno = ptrace_out.errno_num;
617
      perror_with_name ("Resuming remote process");
618
    }
619
}
620
 
621
static void
622
vx_mourn_inferior (void)
623
{
624
  pop_target ();                /* Pop back to no-child state */
625
  generic_mourn_inferior ();
626
}
627
 
628
 
629
static void vx_add_symbols (char *, int, CORE_ADDR, CORE_ADDR, CORE_ADDR);
630
 
631
struct find_sect_args
632
  {
633
    CORE_ADDR text_start;
634
    CORE_ADDR data_start;
635
    CORE_ADDR bss_start;
636
  };
637
 
638
static void find_sect (bfd *, asection *, void *);
639
 
640
static void
641
find_sect (bfd *abfd, asection *sect, PTR obj)
642
{
643
  struct find_sect_args *args = (struct find_sect_args *) obj;
644
 
645
  if (bfd_get_section_flags (abfd, sect) & (SEC_CODE & SEC_READONLY))
646
    args->text_start = bfd_get_section_vma (abfd, sect);
647
  else if (bfd_get_section_flags (abfd, sect) & SEC_ALLOC)
648
    {
649
      if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
650
        {
651
          /* Exclude .ctor and .dtor sections which have SEC_CODE set but not
652
             SEC_DATA.  */
653
          if (bfd_get_section_flags (abfd, sect) & SEC_DATA)
654
            args->data_start = bfd_get_section_vma (abfd, sect);
655
        }
656
      else
657
        args->bss_start = bfd_get_section_vma (abfd, sect);
658
    }
659
}
660
 
661
static void
662
vx_add_symbols (char *name, int from_tty, CORE_ADDR text_addr,
663
                CORE_ADDR data_addr, CORE_ADDR bss_addr)
664
{
665
  struct section_offsets *offs;
666
  struct objfile *objfile;
667
  struct find_sect_args ss;
668
 
669
  /* It might be nice to suppress the breakpoint_re_set which happens here
670
     because we are going to do one again after the objfile_relocate.  */
671
  objfile = symbol_file_add (name, from_tty, NULL, 0, 0);
672
 
673
  /* This is a (slightly cheesy) way of superceding the old symbols.  A less
674
     cheesy way would be to find the objfile with the same name and
675
     free_objfile it.  */
676
  objfile_to_front (objfile);
677
 
678
  offs = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
679
  memcpy (offs, objfile->section_offsets, SIZEOF_SECTION_OFFSETS);
680
 
681
  ss.text_start = 0;
682
  ss.data_start = 0;
683
  ss.bss_start = 0;
684
  bfd_map_over_sections (objfile->obfd, find_sect, &ss);
685
 
686
  /* Both COFF and b.out frontends use these SECT_OFF_* values.  */
687
  offs->offsets[SECT_OFF_TEXT (objfile)]  = text_addr - ss.text_start;
688
  offs->offsets[SECT_OFF_DATA (objfile)] = data_addr - ss.data_start;
689
  offs->offsets[SECT_OFF_BSS (objfile)] = bss_addr - ss.bss_start;
690
  objfile_relocate (objfile, offs);
691
}
692
 
693
/* This function allows the addition of incrementally linked object files.  */
694
 
695
static void
696
vx_load_command (char *arg_string, int from_tty)
697
{
698
  CORE_ADDR text_addr;
699
  CORE_ADDR data_addr;
700
  CORE_ADDR bss_addr;
701
 
702
  if (arg_string == 0)
703
    error ("The load command takes a file name");
704
 
705
  arg_string = tilde_expand (arg_string);
706
  make_cleanup (xfree, arg_string);
707
 
708
  dont_repeat ();
709
 
710
  /* Refuse to load the module if a debugged task is running.  Doing so
711
     can have a number of unpleasant consequences to the running task.  */
712
 
713
  if (PIDGET (inferior_ptid) != 0 && target_has_execution)
714
    {
715
      if (query ("You may not load a module while the target task is running.\n\
716
Kill the target task? "))
717
        target_kill ();
718
      else
719
        error ("Load canceled.");
720
    }
721
 
722
  QUIT;
723
  immediate_quit++;
724
  if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
725
    error ("Load failed on target machine");
726
  immediate_quit--;
727
 
728
  vx_add_symbols (arg_string, from_tty, text_addr, data_addr, bss_addr);
729
 
730
  /* Getting new symbols may change our opinion about what is
731
     frameless.  */
732
  reinit_frame_cache ();
733
}
734
 
735
/* Single step the target program at the source or machine level.
736
   Takes an error exit if rpc fails.
737
   Returns -1 if remote single-step operation fails, else 0.  */
738
 
739
static int
740
net_step (void)
741
{
742
  enum clnt_stat status;
743
  int step_status;
744
  SOURCE_STEP source_step;
745
 
746
  source_step.taskId = PIDGET (inferior_ptid);
747
 
748
  if (step_range_end)
749
    {
750
      source_step.startAddr = step_range_start;
751
      source_step.endAddr = step_range_end;
752
    }
753
  else
754
    {
755
      source_step.startAddr = 0;
756
      source_step.endAddr = 0;
757
    }
758
 
759
  status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
760
                          xdr_int, &step_status);
761
 
762
  if (status == RPC_SUCCESS)
763
    return step_status;
764
  else
765
    error (rpcerr);
766
}
767
 
768
/* Emulate ptrace using RPC calls to the VxWorks target system.
769
   Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise.  */
770
 
771
static int
772
net_ptrace_clnt_call (enum ptracereq request, 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
 
792
static int
793
net_get_boot_file (char **pBootFile)
794
{
795
  enum clnt_stat status;
796
 
797
  status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
798
                          xdr_wrapstring, pBootFile);
799
  return (status == RPC_SUCCESS) ? 0 : -1;
800
}
801
 
802
/* Fetch a list of loaded object modules from the VxWorks target
803
   and store in PLOADTABLE.
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
 
808
static int
809
net_get_symbols (ldtabl *pLoadTable)
810
{
811
  enum clnt_stat status;
812
 
813
  memset ((char *) pLoadTable, '\0', sizeof (struct ldtabl));
814
 
815
  status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
816
  return (status == RPC_SUCCESS) ? 0 : -1;
817
}
818
 
819
/* Look up a symbol in the VxWorks target's symbol table.
820
   Returns status of symbol read on target side (0=success, -1=fail)
821
   Returns -1 and complain()s if rpc fails.  */
822
 
823
struct complaint cant_contact_target =
824
{"Lost contact with VxWorks target", 0, 0};
825
 
826
static int
827
vx_lookup_symbol (char *name,   /* symbol name */
828
                  CORE_ADDR *pAddr)
829
{
830
  enum clnt_stat status;
831
  SYMBOL_ADDR symbolAddr;
832
 
833
  *pAddr = 0;
834
  memset ((char *) &symbolAddr, '\0', sizeof (symbolAddr));
835
 
836
  status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
837
                          xdr_SYMBOL_ADDR, &symbolAddr);
838
  if (status != RPC_SUCCESS)
839
    {
840
      complain (&cant_contact_target);
841
      return -1;
842
    }
843
 
844
  *pAddr = symbolAddr.addr;
845
  return symbolAddr.status;
846
}
847
 
848
/* Check to see if the VxWorks target has a floating point coprocessor.
849
   Returns 1 if target has floating point processor, 0 otherwise.
850
   Calls error() if rpc fails.  */
851
 
852
static int
853
net_check_for_fp (void)
854
{
855
  enum clnt_stat status;
856
  bool_t fp = 0;         /* true if fp processor is present on target board */
857
 
858
  status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
859
  if (status != RPC_SUCCESS)
860
    error (rpcerr);
861
 
862
  return (int) fp;
863
}
864
 
865
/* Establish an RPC connection with the VxWorks target system.
866
   Calls error () if unable to establish connection.  */
867
 
868
static void
869
net_connect (char *host)
870
{
871
  struct sockaddr_in destAddr;
872
  struct hostent *destHost;
873
  unsigned long addr;
874
 
875
  /* Get the internet address for the given host.  Allow a numeric
876
     IP address or a hostname.  */
877
 
878
  addr = inet_addr (host);
879
  if (addr == -1)
880
    {
881
      destHost = (struct hostent *) gethostbyname (host);
882
      if (destHost == NULL)
883
        /* FIXME: Probably should include hostname here in quotes.
884
           For example if the user types "target vxworks vx960 " it should
885
           say "Invalid host `vx960 '." not just "Invalid hostname".  */
886
        error ("Invalid hostname.  Couldn't find remote host address.");
887
      addr = *(unsigned long *) destHost->h_addr;
888
    }
889
 
890
  memset (&destAddr, '\0', sizeof (destAddr));
891
 
892
  destAddr.sin_addr.s_addr = addr;
893
  destAddr.sin_family = AF_INET;
894
  destAddr.sin_port = 0; /* set to actual port that remote
895
                                   ptrace is listening on.  */
896
 
897
  /* Create a tcp client transport on which to issue
898
     calls to the remote ptrace server.  */
899
 
900
  ptraceSock = RPC_ANYSOCK;
901
  pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
902
  /* FIXME, here is where we deal with different version numbers of the
903
     proto */
904
 
905
  if (pClient == NULL)
906
    {
907
      clnt_pcreateerror ("\tnet_connect");
908
      error ("Couldn't connect to remote target.");
909
    }
910
}
911
 
912
/* Sleep for the specified number of milliseconds
913
 * (assumed to be less than 1000).
914
 * If select () is interrupted, returns immediately;
915
 * takes an error exit if select () fails for some other reason.
916
 */
917
 
918
static void
919
sleep_ms (long ms)
920
{
921
  struct timeval select_timeout;
922
  int status;
923
 
924
  select_timeout.tv_sec = 0;
925
  select_timeout.tv_usec = ms * 1000;
926
 
927
  status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0,
928
                   &select_timeout);
929
 
930
  if (status < 0 && errno != EINTR)
931
    perror_with_name ("select");
932
}
933
 
934
static ptid_t
935
vx_wait (ptid_t ptid_to_wait_for, struct target_waitstatus *status)
936
{
937
  register int pid;
938
  RDB_EVENT rdbEvent;
939
  int quit_failed;
940
 
941
  do
942
    {
943
      /* If CTRL-C is hit during this loop,
944
         suspend the inferior process.  */
945
 
946
      quit_failed = 0;
947
      if (quit_flag)
948
        {
949
          quit_failed = (net_quit () == -1);
950
          quit_flag = 0;
951
        }
952
 
953
      /* If a net_quit () or net_wait () call has failed,
954
         allow the user to break the connection with the target.
955
         We can't simply error () out of this loop, since the
956
         data structures representing the state of the inferior
957
         are in an inconsistent state.  */
958
 
959
      if (quit_failed || net_wait (&rdbEvent) == -1)
960
        {
961
          terminal_ours ();
962
          if (query ("Can't %s.  Disconnect from target system? ",
963
                     (quit_failed) ? "suspend remote task"
964
                     : "get status of remote task"))
965
            {
966
              target_mourn_inferior ();
967
              error ("Use the \"target\" command to reconnect.");
968
            }
969
          else
970
            {
971
              terminal_inferior ();
972
              continue;
973
            }
974
        }
975
 
976
      pid = rdbEvent.taskId;
977
      if (pid == 0)
978
        {
979
          sleep_ms (200);       /* FIXME Don't kill the network too badly */
980
        }
981
      else if (pid != PIDGET (inferior_ptid))
982
        internal_error (__FILE__, __LINE__,
983
                        "Bad pid for debugged task: %s\n",
984
                        local_hex_string ((unsigned long) pid));
985
    }
986
  while (pid == 0);
987
 
988
  /* The mostly likely kind.  */
989
  status->kind = TARGET_WAITKIND_STOPPED;
990
 
991
  switch (rdbEvent.eventType)
992
    {
993
    case EVENT_EXIT:
994
      status->kind = TARGET_WAITKIND_EXITED;
995
      /* FIXME is it possible to distinguish between a
996
         normal vs abnormal exit in VxWorks? */
997
      status->value.integer = 0;
998
      break;
999
 
1000
    case EVENT_START:
1001
      /* Task was just started. */
1002
      status->value.sig = TARGET_SIGNAL_TRAP;
1003
      break;
1004
 
1005
    case EVENT_STOP:
1006
      status->value.sig = TARGET_SIGNAL_TRAP;
1007
      /* XXX was it stopped by a signal?  act accordingly */
1008
      break;
1009
 
1010
    case EVENT_BREAK:           /* Breakpoint was hit. */
1011
      status->value.sig = TARGET_SIGNAL_TRAP;
1012
      break;
1013
 
1014
    case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */
1015
      status->value.sig = TARGET_SIGNAL_INT;
1016
      break;
1017
 
1018
    case EVENT_BUS_ERR: /* Task made evil nasty reference. */
1019
      status->value.sig = TARGET_SIGNAL_BUS;
1020
      break;
1021
 
1022
    case EVENT_ZERO_DIV:        /* Division by zero */
1023
      status->value.sig = TARGET_SIGNAL_FPE;
1024
      break;
1025
 
1026
    case EVENT_SIGNAL:
1027
#ifdef I80960
1028
      status->value.sig = i960_fault_to_signal (rdbEvent.sigType);
1029
#else
1030
      /* Back in the old days, before enum target_signal, this code used
1031
         to add NSIG to the signal number and claim that PRINT_RANDOM_SIGNAL
1032
         would take care of it.  But PRINT_RANDOM_SIGNAL has never been
1033
         defined except on the i960, so I don't really know what we are
1034
         supposed to do on other architectures.  */
1035
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
1036
#endif
1037
      break;
1038
    }                           /* switch */
1039
  return pid_to_ptid (pid);
1040
}
1041
 
1042
static int
1043
symbol_stub (char *arg)
1044
{
1045
  symbol_file_add_main (arg, 0);
1046
  return 1;
1047
}
1048
 
1049
static int
1050
add_symbol_stub (char *arg)
1051
{
1052
  struct ldfile *pLoadFile = (struct ldfile *) arg;
1053
 
1054
  printf_unfiltered ("\t%s: ", pLoadFile->name);
1055
  vx_add_symbols (pLoadFile->name, 0, pLoadFile->txt_addr,
1056
                  pLoadFile->data_addr, pLoadFile->bss_addr);
1057
  printf_unfiltered ("ok\n");
1058
  return 1;
1059
}
1060
/* Target command for VxWorks target systems.
1061
 
1062
   Used in vxgdb.  Takes the name of a remote target machine
1063
   running vxWorks and connects to it to initialize remote network
1064
   debugging.  */
1065
 
1066
static void
1067
vx_open (char *args, int from_tty)
1068
{
1069
  extern int close ();
1070
  char *bootFile;
1071
  extern char *source_path;
1072
  struct ldtabl loadTable;
1073
  struct ldfile *pLoadFile;
1074
  int i;
1075
  extern CLIENT *pClient;
1076
  int symbols_added = 0;
1077
 
1078
  if (!args)
1079
    error_no_arg ("target machine name");
1080
 
1081
  target_preopen (from_tty);
1082
 
1083
  unpush_target (&vx_ops);
1084
  printf_unfiltered ("Attaching remote machine across net...\n");
1085
  gdb_flush (gdb_stdout);
1086
 
1087
  /* Allow the user to kill the connect attempt by typing ^C.
1088
     Wait until the call to target_has_fp () completes before
1089
     disallowing an immediate quit, since even if net_connect ()
1090
     is successful, the remote debug server might be hung.  */
1091
 
1092
  immediate_quit++;
1093
 
1094
  net_connect (args);
1095
  target_has_fp = net_check_for_fp ();
1096
  printf_filtered ("Connected to %s.\n", args);
1097
 
1098
  immediate_quit--;
1099
 
1100
  push_target (&vx_ops);
1101
 
1102
  /* Save a copy of the target host's name.  */
1103
  vx_host = savestring (args, strlen (args));
1104
 
1105
  /* Find out the name of the file from which the target was booted
1106
     and load its symbol table.  */
1107
 
1108
  printf_filtered ("Looking in Unix path for all loaded modules:\n");
1109
  bootFile = NULL;
1110
  if (!net_get_boot_file (&bootFile))
1111
    {
1112
      if (*bootFile)
1113
        {
1114
          printf_filtered ("\t%s: ", bootFile);
1115
          /* This assumes that the kernel is never relocated.  Hope that is an
1116
             accurate assumption.  */
1117
          if (catch_errors
1118
              (symbol_stub,
1119
               bootFile,
1120
               "Error while reading symbols from boot file:\n",
1121
               RETURN_MASK_ALL))
1122
            puts_filtered ("ok\n");
1123
        }
1124
      else if (from_tty)
1125
        printf_unfiltered ("VxWorks kernel symbols not loaded.\n");
1126
    }
1127
  else
1128
    error ("Can't retrieve boot file name from target machine.");
1129
 
1130
  clnt_freeres (pClient, xdr_wrapstring, &bootFile);
1131
 
1132
  if (net_get_symbols (&loadTable) != 0)
1133
    error ("Can't read loaded modules from target machine");
1134
 
1135
  i = 0 - 1;
1136
  while (++i < loadTable.tbl_size)
1137
    {
1138
      QUIT;                     /* FIXME, avoids clnt_freeres below:  mem leak */
1139
      pLoadFile = &loadTable.tbl_ent[i];
1140
#ifdef WRS_ORIG
1141
      {
1142
        register int desc;
1143
        struct cleanup *old_chain;
1144
        char *fullname = NULL;
1145
 
1146
        desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
1147
        if (desc < 0)
1148
          perror_with_name (pLoadFile->name);
1149
        old_chain = make_cleanup (close, desc);
1150
        add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
1151
                          pLoadFile->bss_addr);
1152
        do_cleanups (old_chain);
1153
      }
1154
#else
1155
      /* FIXME: Is there something better to search than the PATH? (probably
1156
         not the source path, since source might be in different directories
1157
         than objects.  */
1158
 
1159
      if (catch_errors (add_symbol_stub, (char *) pLoadFile, (char *) 0,
1160
                        RETURN_MASK_ALL))
1161
        symbols_added = 1;
1162
#endif
1163
    }
1164
  printf_filtered ("Done.\n");
1165
 
1166
  clnt_freeres (pClient, xdr_ldtabl, &loadTable);
1167
 
1168
  /* Getting new symbols may change our opinion about what is
1169
     frameless.  */
1170
  if (symbols_added)
1171
    reinit_frame_cache ();
1172
}
1173
 
1174
/* Takes a task started up outside of gdb and ``attaches'' to it.
1175
   This stops it cold in its tracks and allows us to start tracing it.  */
1176
 
1177
static void
1178
vx_attach (char *args, int from_tty)
1179
{
1180
  unsigned long pid;
1181
  char *cptr = 0;
1182
  Rptrace ptrace_in;
1183
  Ptrace_return ptrace_out;
1184
  int status;
1185
 
1186
  if (!args)
1187
    error_no_arg ("process-id to attach");
1188
 
1189
  pid = strtoul (args, &cptr, 0);
1190
  if ((cptr == args) || (*cptr != '\0'))
1191
    error ("Invalid process-id -- give a single number in decimal or 0xhex");
1192
 
1193
  if (from_tty)
1194
    printf_unfiltered ("Attaching pid %s.\n",
1195
                       local_hex_string ((unsigned long) pid));
1196
 
1197
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
1198
  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
1199
  ptrace_in.pid = pid;
1200
 
1201
  status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
1202
  if (status == -1)
1203
    error (rpcerr);
1204
  if (ptrace_out.status == -1)
1205
    {
1206
      errno = ptrace_out.errno_num;
1207
      perror_with_name ("Attaching remote process");
1208
    }
1209
 
1210
  /* It worked... */
1211
 
1212
  inferior_ptid = pid_to_ptid (pid);
1213
  push_target (&vx_run_ops);
1214
 
1215
  if (vx_running)
1216
    xfree (vx_running);
1217
  vx_running = 0;
1218
}
1219
 
1220
/* detach_command --
1221
   takes a program previously attached to and detaches it.
1222
   The program resumes execution and will no longer stop
1223
   on signals, etc.  We better not have left any breakpoints
1224
   in the program or it'll die when it hits one.  For this
1225
   to work, it may be necessary for the process to have been
1226
   previously attached.  It *might* work if the program was
1227
   started via the normal ptrace (PTRACE_TRACEME).  */
1228
 
1229
static void
1230
vx_detach (char *args, int from_tty)
1231
{
1232
  Rptrace ptrace_in;
1233
  Ptrace_return ptrace_out;
1234
  int signal = 0;
1235
  int status;
1236
 
1237
  if (args)
1238
    error ("Argument given to VxWorks \"detach\".");
1239
 
1240
  if (from_tty)
1241
    printf_unfiltered ("Detaching pid %s.\n",
1242
                       local_hex_string (
1243
                         (unsigned long) PIDGET (inferior_ptid)));
1244
 
1245
  if (args)                     /* FIXME, should be possible to leave suspended */
1246
    signal = atoi (args);
1247
 
1248
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
1249
  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
1250
  ptrace_in.pid = PIDGET (inferior_ptid);
1251
 
1252
  status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
1253
  if (status == -1)
1254
    error (rpcerr);
1255
  if (ptrace_out.status == -1)
1256
    {
1257
      errno = ptrace_out.errno_num;
1258
      perror_with_name ("Detaching VxWorks process");
1259
    }
1260
 
1261
  inferior_ptid = null_ptid;
1262
  pop_target ();                /* go back to non-executing VxWorks connection */
1263
}
1264
 
1265
/* vx_kill -- takes a running task and wipes it out.  */
1266
 
1267
static void
1268
vx_kill (void)
1269
{
1270
  Rptrace ptrace_in;
1271
  Ptrace_return ptrace_out;
1272
  int status;
1273
 
1274
  printf_unfiltered ("Killing pid %s.\n", local_hex_string ((unsigned long) PIDGET (inferior_ptid)));
1275
 
1276
  memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
1277
  memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
1278
  ptrace_in.pid = PIDGET (inferior_ptid);
1279
 
1280
  status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
1281
  if (status == -1)
1282
    warning (rpcerr);
1283
  else if (ptrace_out.status == -1)
1284
    {
1285
      errno = ptrace_out.errno_num;
1286
      perror_with_name ("Killing VxWorks process");
1287
    }
1288
 
1289
  /* If it gives good status, the process is *gone*, no events remain.
1290
     If the kill failed, assume the process is gone anyhow.  */
1291
  inferior_ptid = null_ptid;
1292
  pop_target ();                /* go back to non-executing VxWorks connection */
1293
}
1294
 
1295
/* Clean up from the VxWorks process target as it goes away.  */
1296
 
1297
static void
1298
vx_proc_close (int quitting)
1299
{
1300
  inferior_ptid = null_ptid;    /* No longer have a process.  */
1301
  if (vx_running)
1302
    xfree (vx_running);
1303
  vx_running = 0;
1304
}
1305
 
1306
/* Make an RPC call to the VxWorks target.
1307
   Returns RPC status.  */
1308
 
1309
static enum clnt_stat
1310
net_clnt_call (enum ptracereq procNum, xdrproc_t inProc, char *in,
1311
               xdrproc_t outProc, char *out)
1312
{
1313
  enum clnt_stat status;
1314
 
1315
  status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
1316
 
1317
  if (status != RPC_SUCCESS)
1318
    clnt_perrno (status);
1319
 
1320
  return status;
1321
}
1322
 
1323
/* Clean up before losing control.  */
1324
 
1325
static void
1326
vx_close (int quitting)
1327
{
1328
  if (pClient)
1329
    clnt_destroy (pClient);     /* The net connection */
1330
  pClient = 0;
1331
 
1332
  if (vx_host)
1333
    xfree (vx_host);            /* The hostname */
1334
  vx_host = 0;
1335
}
1336
 
1337
/* A vxprocess target should be started via "run" not "target".  */
1338
/*ARGSUSED */
1339
static void
1340
vx_proc_open (char *name, int from_tty)
1341
{
1342
  error ("Use the \"run\" command to start a VxWorks process.");
1343
}
1344
 
1345
static void
1346
init_vx_ops (void)
1347
{
1348
  vx_ops.to_shortname = "vxworks";
1349
  vx_ops.to_longname = "VxWorks target memory via RPC over TCP/IP";
1350
  vx_ops.to_doc = "Use VxWorks target memory.  \n\
1351
Specify the name of the machine to connect to.";
1352
  vx_ops.to_open = vx_open;
1353
  vx_ops.to_close = vx_close;
1354
  vx_ops.to_attach = vx_attach;
1355
  vx_ops.to_xfer_memory = vx_xfer_memory;
1356
  vx_ops.to_files_info = vx_files_info;
1357
  vx_ops.to_load = vx_load_command;
1358
  vx_ops.to_lookup_symbol = vx_lookup_symbol;
1359
  vx_ops.to_create_inferior = vx_create_inferior;
1360
  vx_ops.to_stratum = core_stratum;
1361
  vx_ops.to_has_all_memory = 1;
1362
  vx_ops.to_has_memory = 1;
1363
  vx_ops.to_magic = OPS_MAGIC;  /* Always the last thing */
1364
};
1365
 
1366
static void
1367
init_vx_run_ops (void)
1368
{
1369
  vx_run_ops.to_shortname = "vxprocess";
1370
  vx_run_ops.to_longname = "VxWorks process";
1371
  vx_run_ops.to_doc = "VxWorks process; started by the \"run\" command.";
1372
  vx_run_ops.to_open = vx_proc_open;
1373
  vx_run_ops.to_close = vx_proc_close;
1374
  vx_run_ops.to_detach = vx_detach;
1375
  vx_run_ops.to_resume = vx_resume;
1376
  vx_run_ops.to_wait = vx_wait;
1377
  vx_run_ops.to_fetch_registers = vx_read_register;
1378
  vx_run_ops.to_store_registers = vx_write_register;
1379
  vx_run_ops.to_prepare_to_store = vx_prepare_to_store;
1380
  vx_run_ops.to_xfer_memory = vx_xfer_memory;
1381
  vx_run_ops.to_files_info = vx_run_files_info;
1382
  vx_run_ops.to_insert_breakpoint = vx_insert_breakpoint;
1383
  vx_run_ops.to_remove_breakpoint = vx_remove_breakpoint;
1384
  vx_run_ops.to_kill = vx_kill;
1385
  vx_run_ops.to_load = vx_load_command;
1386
  vx_run_ops.to_lookup_symbol = vx_lookup_symbol;
1387
  vx_run_ops.to_mourn_inferior = vx_mourn_inferior;
1388
  vx_run_ops.to_stratum = process_stratum;
1389
  vx_run_ops.to_has_memory = 1;
1390
  vx_run_ops.to_has_stack = 1;
1391
  vx_run_ops.to_has_registers = 1;
1392
  vx_run_ops.to_has_execution = 1;
1393
  vx_run_ops.to_magic = OPS_MAGIC;
1394
}
1395
 
1396
void
1397
_initialize_vx (void)
1398
{
1399
  init_vx_ops ();
1400
  add_target (&vx_ops);
1401
  init_vx_run_ops ();
1402
  add_target (&vx_run_ops);
1403
 
1404
  add_show_from_set
1405
    (add_set_cmd ("vxworks-timeout", class_support, var_uinteger,
1406
                  (char *) &rpcTimeout.tv_sec,
1407
                  "Set seconds to wait for rpc calls to return.\n\
1408
Set the number of seconds to wait for rpc calls to return.", &setlist),
1409
     &showlist);
1410
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.