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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [gdb/] [remote-vx.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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