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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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