OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [nto-procfs.c] - Blame information for rev 404

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/* Machine independent support for QNX Neutrino /proc (process file system)
2
   for GDB.  Written by Colin Burgess at QNX Software Systems Limited.
3
 
4
   Copyright (C) 2003, 2006, 2007, 2008 Free Software Foundation, Inc.
5
 
6
   Contributed by QNX Software Systems Ltd.
7
 
8
   This file is part of GDB.
9
 
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
 
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
 
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
#include "defs.h"
24
 
25
#include <fcntl.h>
26
#include <spawn.h>
27
#include <sys/debug.h>
28
#include <sys/procfs.h>
29
#include <sys/neutrino.h>
30
#include <sys/syspage.h>
31
#include "gdb_dirent.h"
32
#include <sys/netmgr.h>
33
 
34
#include "exceptions.h"
35
#include "gdb_string.h"
36
#include "gdbcore.h"
37
#include "inferior.h"
38
#include "target.h"
39
#include "objfiles.h"
40
#include "gdbthread.h"
41
#include "nto-tdep.h"
42
#include "command.h"
43
#include "regcache.h"
44
#include "solib.h"
45
 
46
#define NULL_PID                0
47
#define _DEBUG_FLAG_TRACE       (_DEBUG_FLAG_TRACE_EXEC|_DEBUG_FLAG_TRACE_RD|\
48
                _DEBUG_FLAG_TRACE_WR|_DEBUG_FLAG_TRACE_MODIFY)
49
 
50
static struct target_ops procfs_ops;
51
 
52
int ctl_fd;
53
 
54
static void (*ofunc) ();
55
 
56
static procfs_run run;
57
 
58
static void procfs_open (char *, int);
59
 
60
static int procfs_can_run (void);
61
 
62
static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
63
 
64
static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
65
                               struct mem_attrib *attrib,
66
                               struct target_ops *);
67
 
68
static void procfs_fetch_registers (struct regcache *, int);
69
 
70
static void notice_signals (void);
71
 
72
static void init_procfs_ops (void);
73
 
74
static ptid_t do_attach (ptid_t ptid);
75
 
76
static int procfs_can_use_hw_breakpoint (int, int, int);
77
 
78
static int procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type);
79
 
80
static int procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type);
81
 
82
static int procfs_stopped_by_watchpoint (void);
83
 
84
/* These two globals are only ever set in procfs_open(), but are
85
   referenced elsewhere.  'nto_procfs_node' is a flag used to say
86
   whether we are local, or we should get the current node descriptor
87
   for the remote QNX node.  */
88
static char nto_procfs_path[PATH_MAX] = { "/proc" };
89
static unsigned nto_procfs_node = ND_LOCAL_NODE;
90
 
91
/* Return the current QNX Node, or error out.  This is a simple
92
   wrapper for the netmgr_strtond() function.  The reason this
93
   is required is because QNX node descriptors are transient so
94
   we have to re-acquire them every time.  */
95
static unsigned
96
nto_node (void)
97
{
98
  unsigned node;
99
 
100
  if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0)
101
    return ND_LOCAL_NODE;
102
 
103
  node = netmgr_strtond (nto_procfs_path, 0);
104
  if (node == -1)
105
    error (_("Lost the QNX node.  Debug session probably over."));
106
 
107
  return (node);
108
}
109
 
110
static enum gdb_osabi
111
procfs_is_nto_target (bfd *abfd)
112
{
113
  return GDB_OSABI_QNXNTO;
114
}
115
 
116
/* This is called when we call 'target procfs <arg>' from the (gdb) prompt.
117
   For QNX6 (nto), the only valid arg will be a QNX node string,
118
   eg: "/net/some_node".  If arg is not a valid QNX node, we will
119
   default to local.  */
120
static void
121
procfs_open (char *arg, int from_tty)
122
{
123
  char *nodestr;
124
  char *endstr;
125
  char buffer[50];
126
  int fd, total_size;
127
  procfs_sysinfo *sysinfo;
128
 
129
  nto_is_nto_target = procfs_is_nto_target;
130
 
131
  /* Set the default node used for spawning to this one,
132
     and only override it if there is a valid arg.  */
133
 
134
  nto_procfs_node = ND_LOCAL_NODE;
135
  nodestr = arg ? xstrdup (arg) : arg;
136
 
137
  init_thread_list ();
138
 
139
  if (nodestr)
140
    {
141
      nto_procfs_node = netmgr_strtond (nodestr, &endstr);
142
      if (nto_procfs_node == -1)
143
        {
144
          if (errno == ENOTSUP)
145
            printf_filtered ("QNX Net Manager not found.\n");
146
          printf_filtered ("Invalid QNX node %s: error %d (%s).\n", nodestr,
147
                           errno, safe_strerror (errno));
148
          xfree (nodestr);
149
          nodestr = NULL;
150
          nto_procfs_node = ND_LOCAL_NODE;
151
        }
152
      else if (*endstr)
153
        {
154
          if (*(endstr - 1) == '/')
155
            *(endstr - 1) = 0;
156
          else
157
            *endstr = 0;
158
        }
159
    }
160
  snprintf (nto_procfs_path, PATH_MAX - 1, "%s%s", nodestr ? nodestr : "",
161
            "/proc");
162
  if (nodestr)
163
    xfree (nodestr);
164
 
165
  fd = open (nto_procfs_path, O_RDONLY);
166
  if (fd == -1)
167
    {
168
      printf_filtered ("Error opening %s : %d (%s)\n", nto_procfs_path, errno,
169
                       safe_strerror (errno));
170
      error (_("Invalid procfs arg"));
171
    }
172
 
173
  sysinfo = (void *) buffer;
174
  if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, sizeof buffer, 0) != EOK)
175
    {
176
      printf_filtered ("Error getting size: %d (%s)\n", errno,
177
                       safe_strerror (errno));
178
      close (fd);
179
      error (_("Devctl failed."));
180
    }
181
  else
182
    {
183
      total_size = sysinfo->total_size;
184
      sysinfo = alloca (total_size);
185
      if (!sysinfo)
186
        {
187
          printf_filtered ("Memory error: %d (%s)\n", errno,
188
                           safe_strerror (errno));
189
          close (fd);
190
          error (_("alloca failed."));
191
        }
192
      else
193
        {
194
          if (devctl (fd, DCMD_PROC_SYSINFO, sysinfo, total_size, 0) != EOK)
195
            {
196
              printf_filtered ("Error getting sysinfo: %d (%s)\n", errno,
197
                               safe_strerror (errno));
198
              close (fd);
199
              error (_("Devctl failed."));
200
            }
201
          else
202
            {
203
              if (sysinfo->type !=
204
                  nto_map_arch_to_cputype (gdbarch_bfd_arch_info
205
                                           (current_gdbarch)->arch_name))
206
                {
207
                  close (fd);
208
                  error (_("Invalid target CPU."));
209
                }
210
            }
211
        }
212
    }
213
  close (fd);
214
  printf_filtered ("Debugging using %s\n", nto_procfs_path);
215
}
216
 
217
static void
218
procfs_set_thread (ptid_t ptid)
219
{
220
  pid_t tid;
221
 
222
  tid = ptid_get_tid (ptid);
223
  devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0);
224
}
225
 
226
/*  Return nonzero if the thread TH is still alive.  */
227
static int
228
procfs_thread_alive (ptid_t ptid)
229
{
230
  pid_t tid;
231
 
232
  tid = ptid_get_tid (ptid);
233
  if (devctl (ctl_fd, DCMD_PROC_CURTHREAD, &tid, sizeof (tid), 0) == EOK)
234
    return 1;
235
  return 0;
236
}
237
 
238
void
239
procfs_find_new_threads (void)
240
{
241
  procfs_status status;
242
  pid_t pid;
243
  ptid_t ptid;
244
 
245
  if (ctl_fd == -1)
246
    return;
247
 
248
  pid = ptid_get_pid (inferior_ptid);
249
 
250
  for (status.tid = 1;; ++status.tid)
251
    {
252
      if (devctl (ctl_fd, DCMD_PROC_TIDSTATUS, &status, sizeof (status), 0)
253
          != EOK && status.tid != 0)
254
        break;
255
      ptid = ptid_build (pid, 0, status.tid);
256
      if (!in_thread_list (ptid))
257
        add_thread (ptid);
258
    }
259
  return;
260
}
261
 
262
void
263
procfs_pidlist (char *args, int from_tty)
264
{
265
  DIR *dp = NULL;
266
  struct dirent *dirp = NULL;
267
  int fd = -1;
268
  char buf[512];
269
  procfs_info *pidinfo = NULL;
270
  procfs_debuginfo *info = NULL;
271
  procfs_status *status = NULL;
272
  pid_t num_threads = 0;
273
  pid_t pid;
274
  char name[512];
275
 
276
  dp = opendir (nto_procfs_path);
277
  if (dp == NULL)
278
    {
279
      fprintf_unfiltered (gdb_stderr, "failed to opendir \"%s\" - %d (%s)",
280
                          nto_procfs_path, errno, safe_strerror (errno));
281
      return;
282
    }
283
 
284
  /* Start scan at first pid.  */
285
  rewinddir (dp);
286
 
287
  do
288
    {
289
      /* Get the right pid and procfs path for the pid.  */
290
      do
291
        {
292
          dirp = readdir (dp);
293
          if (dirp == NULL)
294
            {
295
              closedir (dp);
296
              return;
297
            }
298
          snprintf (buf, 511, "%s/%s/as", nto_procfs_path, dirp->d_name);
299
          pid = atoi (dirp->d_name);
300
        }
301
      while (pid == 0);
302
 
303
      /* Open the procfs path. */
304
      fd = open (buf, O_RDONLY);
305
      if (fd == -1)
306
        {
307
          fprintf_unfiltered (gdb_stderr, "failed to open %s - %d (%s)\n",
308
                              buf, errno, safe_strerror (errno));
309
          closedir (dp);
310
          return;
311
        }
312
 
313
      pidinfo = (procfs_info *) buf;
314
      if (devctl (fd, DCMD_PROC_INFO, pidinfo, sizeof (buf), 0) != EOK)
315
        {
316
          fprintf_unfiltered (gdb_stderr,
317
                              "devctl DCMD_PROC_INFO failed - %d (%s)\n",
318
                              errno, safe_strerror (errno));
319
          break;
320
        }
321
      num_threads = pidinfo->num_threads;
322
 
323
      info = (procfs_debuginfo *) buf;
324
      if (devctl (fd, DCMD_PROC_MAPDEBUG_BASE, info, sizeof (buf), 0) != EOK)
325
        strcpy (name, "unavailable");
326
      else
327
        strcpy (name, info->path);
328
 
329
      /* Collect state info on all the threads.  */
330
      status = (procfs_status *) buf;
331
      for (status->tid = 1; status->tid <= num_threads; status->tid++)
332
        {
333
          if (devctl (fd, DCMD_PROC_TIDSTATUS, status, sizeof (buf), 0) != EOK
334
              && status->tid != 0)
335
            break;
336
          if (status->tid != 0)
337
            printf_filtered ("%s - %d/%d\n", name, pid, status->tid);
338
        }
339
      close (fd);
340
    }
341
  while (dirp != NULL);
342
 
343
  close (fd);
344
  closedir (dp);
345
  return;
346
}
347
 
348
void
349
procfs_meminfo (char *args, int from_tty)
350
{
351
  procfs_mapinfo *mapinfos = NULL;
352
  static int num_mapinfos = 0;
353
  procfs_mapinfo *mapinfo_p, *mapinfo_p2;
354
  int flags = ~0, err, num, i, j;
355
 
356
  struct
357
  {
358
    procfs_debuginfo info;
359
    char buff[_POSIX_PATH_MAX];
360
  } map;
361
 
362
  struct info
363
  {
364
    unsigned addr;
365
    unsigned size;
366
    unsigned flags;
367
    unsigned debug_vaddr;
368
    unsigned long long offset;
369
  };
370
 
371
  struct printinfo
372
  {
373
    unsigned long long ino;
374
    unsigned dev;
375
    struct info text;
376
    struct info data;
377
    char name[256];
378
  } printme;
379
 
380
  /* Get the number of map entrys.  */
381
  err = devctl (ctl_fd, DCMD_PROC_MAPINFO, NULL, 0, &num);
382
  if (err != EOK)
383
    {
384
      printf ("failed devctl num mapinfos - %d (%s)\n", err,
385
              safe_strerror (err));
386
      return;
387
    }
388
 
389
  mapinfos = xmalloc (num * sizeof (procfs_mapinfo));
390
 
391
  num_mapinfos = num;
392
  mapinfo_p = mapinfos;
393
 
394
  /* Fill the map entrys.  */
395
  err = devctl (ctl_fd, DCMD_PROC_MAPINFO, mapinfo_p, num
396
                * sizeof (procfs_mapinfo), &num);
397
  if (err != EOK)
398
    {
399
      printf ("failed devctl mapinfos - %d (%s)\n", err, safe_strerror (err));
400
      xfree (mapinfos);
401
      return;
402
    }
403
 
404
  num = min (num, num_mapinfos);
405
 
406
  /* Run through the list of mapinfos, and store the data and text info
407
     so we can print it at the bottom of the loop.  */
408
  for (mapinfo_p = mapinfos, i = 0; i < num; i++, mapinfo_p++)
409
    {
410
      if (!(mapinfo_p->flags & flags))
411
        mapinfo_p->ino = 0;
412
 
413
      if (mapinfo_p->ino == 0)   /* Already visited.  */
414
        continue;
415
 
416
      map.info.vaddr = mapinfo_p->vaddr;
417
 
418
      err = devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
419
      if (err != EOK)
420
        continue;
421
 
422
      memset (&printme, 0, sizeof printme);
423
      printme.dev = mapinfo_p->dev;
424
      printme.ino = mapinfo_p->ino;
425
      printme.text.addr = mapinfo_p->vaddr;
426
      printme.text.size = mapinfo_p->size;
427
      printme.text.flags = mapinfo_p->flags;
428
      printme.text.offset = mapinfo_p->offset;
429
      printme.text.debug_vaddr = map.info.vaddr;
430
      strcpy (printme.name, map.info.path);
431
 
432
      /* Check for matching data.  */
433
      for (mapinfo_p2 = mapinfos, j = 0; j < num; j++, mapinfo_p2++)
434
        {
435
          if (mapinfo_p2->vaddr != mapinfo_p->vaddr
436
              && mapinfo_p2->ino == mapinfo_p->ino
437
              && mapinfo_p2->dev == mapinfo_p->dev)
438
            {
439
              map.info.vaddr = mapinfo_p2->vaddr;
440
              err =
441
                devctl (ctl_fd, DCMD_PROC_MAPDEBUG, &map, sizeof (map), 0);
442
              if (err != EOK)
443
                continue;
444
 
445
              if (strcmp (map.info.path, printme.name))
446
                continue;
447
 
448
              /* Lower debug_vaddr is always text, if nessessary, swap.  */
449
              if ((int) map.info.vaddr < (int) printme.text.debug_vaddr)
450
                {
451
                  memcpy (&(printme.data), &(printme.text),
452
                          sizeof (printme.data));
453
                  printme.text.addr = mapinfo_p2->vaddr;
454
                  printme.text.size = mapinfo_p2->size;
455
                  printme.text.flags = mapinfo_p2->flags;
456
                  printme.text.offset = mapinfo_p2->offset;
457
                  printme.text.debug_vaddr = map.info.vaddr;
458
                }
459
              else
460
                {
461
                  printme.data.addr = mapinfo_p2->vaddr;
462
                  printme.data.size = mapinfo_p2->size;
463
                  printme.data.flags = mapinfo_p2->flags;
464
                  printme.data.offset = mapinfo_p2->offset;
465
                  printme.data.debug_vaddr = map.info.vaddr;
466
                }
467
              mapinfo_p2->ino = 0;
468
            }
469
        }
470
      mapinfo_p->ino = 0;
471
 
472
      printf_filtered ("%s\n", printme.name);
473
      printf_filtered ("\ttext=%08x bytes @ 0x%08x\n", printme.text.size,
474
                       printme.text.addr);
475
      printf_filtered ("\t\tflags=%08x\n", printme.text.flags);
476
      printf_filtered ("\t\tdebug=%08x\n", printme.text.debug_vaddr);
477
      printf_filtered ("\t\toffset=%016llx\n", printme.text.offset);
478
      if (printme.data.size)
479
        {
480
          printf_filtered ("\tdata=%08x bytes @ 0x%08x\n", printme.data.size,
481
                           printme.data.addr);
482
          printf_filtered ("\t\tflags=%08x\n", printme.data.flags);
483
          printf_filtered ("\t\tdebug=%08x\n", printme.data.debug_vaddr);
484
          printf_filtered ("\t\toffset=%016llx\n", printme.data.offset);
485
        }
486
      printf_filtered ("\tdev=0x%x\n", printme.dev);
487
      printf_filtered ("\tino=0x%x\n", (unsigned int) printme.ino);
488
    }
489
  xfree (mapinfos);
490
  return;
491
}
492
 
493
/* Print status information about what we're accessing.  */
494
static void
495
procfs_files_info (struct target_ops *ignore)
496
{
497
  printf_unfiltered ("\tUsing the running image of %s %s via %s.\n",
498
                     attach_flag ? "attached" : "child",
499
                     target_pid_to_str (inferior_ptid), nto_procfs_path);
500
}
501
 
502
/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
503
static int
504
procfs_can_run (void)
505
{
506
  return 1;
507
}
508
 
509
/* Attach to process PID, then initialize for debugging it.  */
510
static void
511
procfs_attach (char *args, int from_tty)
512
{
513
  char *exec_file;
514
  int pid;
515
 
516
  if (!args)
517
    error_no_arg (_("process-id to attach"));
518
 
519
  pid = atoi (args);
520
 
521
  if (pid == getpid ())
522
    error (_("Attaching GDB to itself is not a good idea..."));
523
 
524
  if (from_tty)
525
    {
526
      exec_file = (char *) get_exec_file (0);
527
 
528
      if (exec_file)
529
        printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
530
                           target_pid_to_str (pid_to_ptid (pid)));
531
      else
532
        printf_unfiltered ("Attaching to %s\n",
533
                           target_pid_to_str (pid_to_ptid (pid)));
534
 
535
      gdb_flush (gdb_stdout);
536
    }
537
  inferior_ptid = do_attach (pid_to_ptid (pid));
538
  push_target (&procfs_ops);
539
}
540
 
541
static void
542
procfs_post_attach (pid_t pid)
543
{
544
  if (exec_bfd)
545
    solib_create_inferior_hook ();
546
}
547
 
548
static ptid_t
549
do_attach (ptid_t ptid)
550
{
551
  procfs_status status;
552
  struct sigevent event;
553
  char path[PATH_MAX];
554
 
555
  snprintf (path, PATH_MAX - 1, "%s/%d/as", nto_procfs_path, PIDGET (ptid));
556
  ctl_fd = open (path, O_RDWR);
557
  if (ctl_fd == -1)
558
    error (_("Couldn't open proc file %s, error %d (%s)"), path, errno,
559
           safe_strerror (errno));
560
  if (devctl (ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) != EOK)
561
    error (_("Couldn't stop process"));
562
 
563
  /* Define a sigevent for process stopped notification.  */
564
  event.sigev_notify = SIGEV_SIGNAL_THREAD;
565
  event.sigev_signo = SIGUSR1;
566
  event.sigev_code = 0;
567
  event.sigev_value.sival_ptr = NULL;
568
  event.sigev_priority = -1;
569
  devctl (ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
570
 
571
  if (devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0) == EOK
572
      && status.flags & _DEBUG_FLAG_STOPPED)
573
    SignalKill (nto_node (), PIDGET (ptid), 0, SIGCONT, 0, 0);
574
  attach_flag = 1;
575
  nto_init_solib_absolute_prefix ();
576
  return ptid;
577
}
578
 
579
/* Ask the user what to do when an interrupt is received.  */
580
static void
581
interrupt_query (void)
582
{
583
  target_terminal_ours ();
584
 
585
  if (query ("Interrupted while waiting for the program.\n\
586
Give up (and stop debugging it)? "))
587
    {
588
      target_mourn_inferior ();
589
      deprecated_throw_reason (RETURN_QUIT);
590
    }
591
 
592
  target_terminal_inferior ();
593
}
594
 
595
/* The user typed ^C twice.  */
596
static void
597
nto_interrupt_twice (int signo)
598
{
599
  signal (signo, ofunc);
600
  interrupt_query ();
601
  signal (signo, nto_interrupt_twice);
602
}
603
 
604
static void
605
nto_interrupt (int signo)
606
{
607
  /* If this doesn't work, try more severe steps.  */
608
  signal (signo, nto_interrupt_twice);
609
 
610
  target_stop ();
611
}
612
 
613
static ptid_t
614
procfs_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
615
{
616
  sigset_t set;
617
  siginfo_t info;
618
  procfs_status status;
619
  static int exit_signo = 0;     /* To track signals that cause termination.  */
620
 
621
  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
622
 
623
  if (ptid_equal (inferior_ptid, null_ptid))
624
    {
625
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
626
      ourstatus->value.sig = TARGET_SIGNAL_0;
627
      exit_signo = 0;
628
      return null_ptid;
629
    }
630
 
631
  sigemptyset (&set);
632
  sigaddset (&set, SIGUSR1);
633
 
634
  devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
635
  while (!(status.flags & _DEBUG_FLAG_ISTOP))
636
    {
637
      ofunc = (void (*)()) signal (SIGINT, nto_interrupt);
638
      sigwaitinfo (&set, &info);
639
      signal (SIGINT, ofunc);
640
      devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
641
    }
642
 
643
  if (status.flags & _DEBUG_FLAG_SSTEP)
644
    {
645
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
646
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
647
    }
648
  /* Was it a breakpoint?  */
649
  else if (status.flags & _DEBUG_FLAG_TRACE)
650
    {
651
      ourstatus->kind = TARGET_WAITKIND_STOPPED;
652
      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
653
    }
654
  else if (status.flags & _DEBUG_FLAG_ISTOP)
655
    {
656
      switch (status.why)
657
        {
658
        case _DEBUG_WHY_SIGNALLED:
659
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
660
          ourstatus->value.sig =
661
            target_signal_from_host (status.info.si_signo);
662
          exit_signo = 0;
663
          break;
664
        case _DEBUG_WHY_FAULTED:
665
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
666
          if (status.info.si_signo == SIGTRAP)
667
            {
668
              ourstatus->value.sig = 0;
669
              exit_signo = 0;
670
            }
671
          else
672
            {
673
              ourstatus->value.sig =
674
                target_signal_from_host (status.info.si_signo);
675
              exit_signo = ourstatus->value.sig;
676
            }
677
          break;
678
 
679
        case _DEBUG_WHY_TERMINATED:
680
          {
681
            int waitval = 0;
682
 
683
            waitpid (PIDGET (inferior_ptid), &waitval, WNOHANG);
684
            if (exit_signo)
685
              {
686
                /* Abnormal death.  */
687
                ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
688
                ourstatus->value.sig = exit_signo;
689
              }
690
            else
691
              {
692
                /* Normal death.  */
693
                ourstatus->kind = TARGET_WAITKIND_EXITED;
694
                ourstatus->value.integer = WEXITSTATUS (waitval);
695
              }
696
            exit_signo = 0;
697
            break;
698
          }
699
 
700
        case _DEBUG_WHY_REQUESTED:
701
          /* We are assuming a requested stop is due to a SIGINT.  */
702
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
703
          ourstatus->value.sig = TARGET_SIGNAL_INT;
704
          exit_signo = 0;
705
          break;
706
        }
707
    }
708
 
709
  return inferior_ptid;
710
}
711
 
712
/* Read the current values of the inferior's registers, both the
713
   general register set and floating point registers (if supported)
714
   and update gdb's idea of their current values.  */
715
static void
716
procfs_fetch_registers (struct regcache *regcache, int regno)
717
{
718
  union
719
  {
720
    procfs_greg greg;
721
    procfs_fpreg fpreg;
722
    procfs_altreg altreg;
723
  }
724
  reg;
725
  int regsize;
726
 
727
  procfs_set_thread (inferior_ptid);
728
  if (devctl (ctl_fd, DCMD_PROC_GETGREG, &reg, sizeof (reg), &regsize) == EOK)
729
    nto_supply_gregset (regcache, (char *) &reg.greg);
730
  if (devctl (ctl_fd, DCMD_PROC_GETFPREG, &reg, sizeof (reg), &regsize)
731
      == EOK)
732
    nto_supply_fpregset (regcache, (char *) &reg.fpreg);
733
  if (devctl (ctl_fd, DCMD_PROC_GETALTREG, &reg, sizeof (reg), &regsize)
734
      == EOK)
735
    nto_supply_altregset (regcache, (char *) &reg.altreg);
736
}
737
 
738
/* Copy LEN bytes to/from inferior's memory starting at MEMADDR
739
   from/to debugger memory starting at MYADDR.  Copy from inferior
740
   if DOWRITE is zero or to inferior if DOWRITE is nonzero.
741
 
742
   Returns the length copied, which is either the LEN argument or
743
   zero.  This xfer function does not do partial moves, since procfs_ops
744
   doesn't allow memory operations to cross below us in the target stack
745
   anyway.  */
746
static int
747
procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
748
                    struct mem_attrib *attrib, struct target_ops *target)
749
{
750
  int nbytes = 0;
751
 
752
  if (lseek (ctl_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
753
    {
754
      if (dowrite)
755
        nbytes = write (ctl_fd, myaddr, len);
756
      else
757
        nbytes = read (ctl_fd, myaddr, len);
758
      if (nbytes < 0)
759
        nbytes = 0;
760
    }
761
  return (nbytes);
762
}
763
 
764
/* Take a program previously attached to and detaches it.
765
   The program resumes execution and will no longer stop
766
   on signals, etc.  We'd better not have left any breakpoints
767
   in the program or it'll die when it hits one.  */
768
static void
769
procfs_detach (char *args, int from_tty)
770
{
771
  int siggnal = 0;
772
 
773
  if (from_tty)
774
    {
775
      char *exec_file = get_exec_file (0);
776
      if (exec_file == 0)
777
        exec_file = "";
778
      printf_unfiltered ("Detaching from program: %s %s\n",
779
                         exec_file, target_pid_to_str (inferior_ptid));
780
      gdb_flush (gdb_stdout);
781
    }
782
  if (args)
783
    siggnal = atoi (args);
784
 
785
  if (siggnal)
786
    SignalKill (nto_node (), PIDGET (inferior_ptid), 0, siggnal, 0, 0);
787
 
788
  close (ctl_fd);
789
  ctl_fd = -1;
790
  init_thread_list ();
791
  inferior_ptid = null_ptid;
792
  attach_flag = 0;
793
  unpush_target (&procfs_ops);  /* Pop out of handling an inferior.  */
794
}
795
 
796
static int
797
procfs_breakpoint (CORE_ADDR addr, int type, int size)
798
{
799
  procfs_break brk;
800
 
801
  brk.type = type;
802
  brk.addr = addr;
803
  brk.size = size;
804
  errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
805
  if (errno != EOK)
806
    return 1;
807
  return 0;
808
}
809
 
810
static int
811
procfs_insert_breakpoint (struct bp_target_info *bp_tgt)
812
{
813
  return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, 0);
814
}
815
 
816
static int
817
procfs_remove_breakpoint (struct bp_target_info *bp_tgt)
818
{
819
  return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
820
}
821
 
822
static int
823
procfs_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
824
{
825
  return procfs_breakpoint (bp_tgt->placed_address,
826
                            _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, 0);
827
}
828
 
829
static int
830
procfs_remove_hw_breakpoint (struct bp_target_info *bp_tgt)
831
{
832
  return procfs_breakpoint (bp_tgt->placed_address,
833
                            _DEBUG_BREAK_EXEC | _DEBUG_BREAK_HW, -1);
834
}
835
 
836
static void
837
procfs_resume (ptid_t ptid, int step, enum target_signal signo)
838
{
839
  int signal_to_pass;
840
  procfs_status status;
841
 
842
  if (ptid_equal (inferior_ptid, null_ptid))
843
    return;
844
 
845
  procfs_set_thread (ptid_equal (ptid, minus_one_ptid) ? inferior_ptid :
846
                     ptid);
847
 
848
  run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
849
  if (step)
850
    run.flags |= _DEBUG_RUN_STEP;
851
 
852
  sigemptyset ((sigset_t *) &run.fault);
853
  sigaddset ((sigset_t *) &run.fault, FLTBPT);
854
  sigaddset ((sigset_t *) &run.fault, FLTTRACE);
855
  sigaddset ((sigset_t *) &run.fault, FLTILL);
856
  sigaddset ((sigset_t *) &run.fault, FLTPRIV);
857
  sigaddset ((sigset_t *) &run.fault, FLTBOUNDS);
858
  sigaddset ((sigset_t *) &run.fault, FLTIOVF);
859
  sigaddset ((sigset_t *) &run.fault, FLTIZDIV);
860
  sigaddset ((sigset_t *) &run.fault, FLTFPE);
861
  /* Peter V will be changing this at some point.  */
862
  sigaddset ((sigset_t *) &run.fault, FLTPAGE);
863
 
864
  run.flags |= _DEBUG_RUN_ARM;
865
 
866
  sigemptyset (&run.trace);
867
  notice_signals ();
868
  signal_to_pass = target_signal_to_host (signo);
869
 
870
  if (signal_to_pass)
871
    {
872
      devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
873
      signal_to_pass = target_signal_to_host (signo);
874
      if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
875
        {
876
          if (signal_to_pass != status.info.si_signo)
877
            {
878
              SignalKill (nto_node (), PIDGET (inferior_ptid), 0,
879
                          signal_to_pass, 0, 0);
880
              run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
881
            }
882
          else                  /* Let it kill the program without telling us.  */
883
            sigdelset (&run.trace, signal_to_pass);
884
        }
885
    }
886
  else
887
    run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
888
 
889
  errno = devctl (ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
890
  if (errno != EOK)
891
    {
892
      perror ("run error!\n");
893
      return;
894
    }
895
}
896
 
897
static void
898
procfs_mourn_inferior (void)
899
{
900
  if (!ptid_equal (inferior_ptid, null_ptid))
901
    {
902
      SignalKill (nto_node (), PIDGET (inferior_ptid), 0, SIGKILL, 0, 0);
903
      close (ctl_fd);
904
    }
905
  inferior_ptid = null_ptid;
906
  init_thread_list ();
907
  unpush_target (&procfs_ops);
908
  generic_mourn_inferior ();
909
  attach_flag = 0;
910
}
911
 
912
/* This function breaks up an argument string into an argument
913
   vector suitable for passing to execvp().
914
   E.g., on "run a b c d" this routine would get as input
915
   the string "a b c d", and as output it would fill in argv with
916
   the four arguments "a", "b", "c", "d".  The only additional
917
   functionality is simple quoting.  The gdb command:
918
        run a "b c d" f
919
   will fill in argv with the three args "a", "b c d", "e".  */
920
static void
921
breakup_args (char *scratch, char **argv)
922
{
923
  char *pp, *cp = scratch;
924
  char quoting = 0;
925
 
926
  for (;;)
927
    {
928
      /* Scan past leading separators.  */
929
      quoting = 0;
930
      while (*cp == ' ' || *cp == '\t' || *cp == '\n')
931
        cp++;
932
 
933
      /* Break if at end of string.  */
934
      if (*cp == '\0')
935
        break;
936
 
937
      /* Take an arg.  */
938
      if (*cp == '"')
939
        {
940
          cp++;
941
          quoting = strchr (cp, '"') ? 1 : 0;
942
        }
943
 
944
      *argv++ = cp;
945
 
946
      /* Scan for next arg separator.  */
947
      pp = cp;
948
      if (quoting)
949
        cp = strchr (pp, '"');
950
      if ((cp == NULL) || (!quoting))
951
        cp = strchr (pp, ' ');
952
      if (cp == NULL)
953
        cp = strchr (pp, '\t');
954
      if (cp == NULL)
955
        cp = strchr (pp, '\n');
956
 
957
      /* No separators => end of string => break.  */
958
      if (cp == NULL)
959
        {
960
          pp = cp;
961
          break;
962
        }
963
 
964
      /* Replace the separator with a terminator.  */
965
      *cp++ = '\0';
966
    }
967
 
968
  /* Execv requires a null-terminated arg vector.  */
969
  *argv = NULL;
970
}
971
 
972
static void
973
procfs_create_inferior (char *exec_file, char *allargs, char **env,
974
                        int from_tty)
975
{
976
  struct inheritance inherit;
977
  pid_t pid;
978
  int flags, errn;
979
  char **argv, *args;
980
  const char *in = "", *out = "", *err = "";
981
  int fd, fds[3];
982
  sigset_t set;
983
  const char *inferior_io_terminal = get_inferior_io_terminal ();
984
 
985
  argv = xmalloc (((strlen (allargs) + 1) / (unsigned) 2 + 2) *
986
                  sizeof (*argv));
987
  argv[0] = get_exec_file (1);
988
  if (!argv[0])
989
    {
990
      if (exec_file)
991
        argv[0] = exec_file;
992
      else
993
        return;
994
    }
995
 
996
  args = xstrdup (allargs);
997
  breakup_args (args, exec_file ? &argv[1] : &argv[0]);
998
 
999
  argv = nto_parse_redirection (argv, &in, &out, &err);
1000
 
1001
  fds[0] = STDIN_FILENO;
1002
  fds[1] = STDOUT_FILENO;
1003
  fds[2] = STDERR_FILENO;
1004
 
1005
  /* If the user specified I/O via gdb's --tty= arg, use it, but only
1006
     if the i/o is not also being specified via redirection.  */
1007
  if (inferior_io_terminal)
1008
    {
1009
      if (!in[0])
1010
        in = inferior_io_terminal;
1011
      if (!out[0])
1012
        out = inferior_io_terminal;
1013
      if (!err[0])
1014
        err = inferior_io_terminal;
1015
    }
1016
 
1017
  if (in[0])
1018
    {
1019
      fd = open (in, O_RDONLY);
1020
      if (fd == -1)
1021
        perror (in);
1022
      else
1023
        fds[0] = fd;
1024
    }
1025
  if (out[0])
1026
    {
1027
      fd = open (out, O_WRONLY);
1028
      if (fd == -1)
1029
        perror (out);
1030
      else
1031
        fds[1] = fd;
1032
    }
1033
  if (err[0])
1034
    {
1035
      fd = open (err, O_WRONLY);
1036
      if (fd == -1)
1037
        perror (err);
1038
      else
1039
        fds[2] = fd;
1040
    }
1041
 
1042
  /* Clear any pending SIGUSR1's but keep the behavior the same.  */
1043
  signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
1044
 
1045
  sigemptyset (&set);
1046
  sigaddset (&set, SIGUSR1);
1047
  sigprocmask (SIG_UNBLOCK, &set, NULL);
1048
 
1049
  memset (&inherit, 0, sizeof (inherit));
1050
 
1051
  if (ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) != 0)
1052
    {
1053
      inherit.nd = nto_node ();
1054
      inherit.flags |= SPAWN_SETND;
1055
      inherit.flags &= ~SPAWN_EXEC;
1056
    }
1057
  inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
1058
  inherit.pgroup = SPAWN_NEWPGROUP;
1059
  pid = spawnp (argv[0], 3, fds, &inherit, argv,
1060
                ND_NODE_CMP (nto_procfs_node, ND_LOCAL_NODE) == 0 ? env : 0);
1061
  xfree (args);
1062
 
1063
  sigprocmask (SIG_BLOCK, &set, NULL);
1064
 
1065
  if (pid == -1)
1066
    error (_("Error spawning %s: %d (%s)"), argv[0], errno,
1067
           safe_strerror (errno));
1068
 
1069
  if (fds[0] != STDIN_FILENO)
1070
    close (fds[0]);
1071
  if (fds[1] != STDOUT_FILENO)
1072
    close (fds[1]);
1073
  if (fds[2] != STDERR_FILENO)
1074
    close (fds[2]);
1075
 
1076
  inferior_ptid = do_attach (pid_to_ptid (pid));
1077
 
1078
  attach_flag = 0;
1079
  flags = _DEBUG_FLAG_KLC;      /* Kill-on-Last-Close flag.  */
1080
  errn = devctl (ctl_fd, DCMD_PROC_SET_FLAG, &flags, sizeof (flags), 0);
1081
  if (errn != EOK)
1082
    {
1083
      /* FIXME: expected warning?  */
1084
      /* warning( "Failed to set Kill-on-Last-Close flag: errno = %d(%s)\n",
1085
         errn, strerror(errn) ); */
1086
    }
1087
  push_target (&procfs_ops);
1088
  target_terminal_init ();
1089
 
1090
  if (exec_bfd != NULL
1091
      || (symfile_objfile != NULL && symfile_objfile->obfd != NULL))
1092
    solib_create_inferior_hook ();
1093
  stop_soon = 0;
1094
}
1095
 
1096
static void
1097
procfs_stop (void)
1098
{
1099
  devctl (ctl_fd, DCMD_PROC_STOP, NULL, 0, 0);
1100
}
1101
 
1102
static void
1103
procfs_kill_inferior (void)
1104
{
1105
  target_mourn_inferior ();
1106
}
1107
 
1108
/* Store register REGNO, or all registers if REGNO == -1, from the contents
1109
   of REGISTERS.  */
1110
static void
1111
procfs_prepare_to_store (struct regcache *regcache)
1112
{
1113
}
1114
 
1115
/* Fill buf with regset and return devctl cmd to do the setting.  Return
1116
   -1 if we fail to get the regset.  Store size of regset in regsize.  */
1117
static int
1118
get_regset (int regset, char *buf, int bufsize, int *regsize)
1119
{
1120
  int dev_get, dev_set;
1121
  switch (regset)
1122
    {
1123
    case NTO_REG_GENERAL:
1124
      dev_get = DCMD_PROC_GETGREG;
1125
      dev_set = DCMD_PROC_SETGREG;
1126
      break;
1127
 
1128
    case NTO_REG_FLOAT:
1129
      dev_get = DCMD_PROC_GETFPREG;
1130
      dev_set = DCMD_PROC_SETFPREG;
1131
      break;
1132
 
1133
    case NTO_REG_ALT:
1134
      dev_get = DCMD_PROC_GETALTREG;
1135
      dev_set = DCMD_PROC_SETALTREG;
1136
      break;
1137
 
1138
    case NTO_REG_SYSTEM:
1139
    default:
1140
      return -1;
1141
    }
1142
  if (devctl (ctl_fd, dev_get, &buf, bufsize, regsize) != EOK)
1143
    return -1;
1144
 
1145
  return dev_set;
1146
}
1147
 
1148
void
1149
procfs_store_registers (struct regcache *regcache, int regno)
1150
{
1151
  union
1152
  {
1153
    procfs_greg greg;
1154
    procfs_fpreg fpreg;
1155
    procfs_altreg altreg;
1156
  }
1157
  reg;
1158
  unsigned off;
1159
  int len, regset, regsize, dev_set, err;
1160
  char *data;
1161
 
1162
  if (ptid_equal (inferior_ptid, null_ptid))
1163
    return;
1164
  procfs_set_thread (inferior_ptid);
1165
 
1166
  if (regno == -1)
1167
    {
1168
      for (regset = NTO_REG_GENERAL; regset < NTO_REG_END; regset++)
1169
        {
1170
          dev_set = get_regset (regset, (char *) &reg,
1171
                                sizeof (reg), &regsize);
1172
          if (dev_set == -1)
1173
            continue;
1174
 
1175
          if (nto_regset_fill (regcache, regset, (char *) &reg) == -1)
1176
            continue;
1177
 
1178
          err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
1179
          if (err != EOK)
1180
            fprintf_unfiltered (gdb_stderr,
1181
                                "Warning unable to write regset %d: %s\n",
1182
                                regno, safe_strerror (err));
1183
        }
1184
    }
1185
  else
1186
    {
1187
      regset = nto_regset_id (regno);
1188
      if (regset == -1)
1189
        return;
1190
 
1191
      dev_set = get_regset (regset, (char *) &reg, sizeof (reg), &regsize);
1192
      if (dev_set == -1)
1193
        return;
1194
 
1195
      len = nto_register_area (regno, regset, &off);
1196
 
1197
      if (len < 1)
1198
        return;
1199
 
1200
      regcache_raw_collect (regcache, regno, (char *) &reg + off);
1201
 
1202
      err = devctl (ctl_fd, dev_set, &reg, regsize, 0);
1203
      if (err != EOK)
1204
        fprintf_unfiltered (gdb_stderr,
1205
                            "Warning unable to write regset %d: %s\n", regno,
1206
                            safe_strerror (err));
1207
    }
1208
}
1209
 
1210
static void
1211
notice_signals (void)
1212
{
1213
  int signo;
1214
 
1215
  for (signo = 1; signo < NSIG; signo++)
1216
    {
1217
      if (signal_stop_state (target_signal_from_host (signo)) == 0
1218
          && signal_print_state (target_signal_from_host (signo)) == 0
1219
          && signal_pass_state (target_signal_from_host (signo)) == 1)
1220
        sigdelset (&run.trace, signo);
1221
      else
1222
        sigaddset (&run.trace, signo);
1223
    }
1224
}
1225
 
1226
/* When the user changes the state of gdb's signal handling via the
1227
   "handle" command, this function gets called to see if any change
1228
   in the /proc interface is required.  It is also called internally
1229
   by other /proc interface functions to initialize the state of
1230
   the traced signal set.  */
1231
static void
1232
procfs_notice_signals (ptid_t ptid)
1233
{
1234
  sigemptyset (&run.trace);
1235
  notice_signals ();
1236
}
1237
 
1238
static struct tidinfo *
1239
procfs_thread_info (pid_t pid, short tid)
1240
{
1241
/* NYI */
1242
  return NULL;
1243
}
1244
 
1245
char *
1246
procfs_pid_to_str (ptid_t ptid)
1247
{
1248
  static char buf[1024];
1249
  int pid, tid, n;
1250
  struct tidinfo *tip;
1251
 
1252
  pid = ptid_get_pid (ptid);
1253
  tid = ptid_get_tid (ptid);
1254
 
1255
  n = snprintf (buf, 1023, "process %d", pid);
1256
 
1257
#if 0                           /* NYI */
1258
  tip = procfs_thread_info (pid, tid);
1259
  if (tip != NULL)
1260
    snprintf (&buf[n], 1023, " (state = 0x%02x)", tip->state);
1261
#endif
1262
 
1263
  return buf;
1264
}
1265
 
1266
static void
1267
init_procfs_ops (void)
1268
{
1269
  procfs_ops.to_shortname = "procfs";
1270
  procfs_ops.to_longname = "QNX Neutrino procfs child process";
1271
  procfs_ops.to_doc =
1272
    "QNX Neutrino procfs child process (started by the \"run\" command).\n\
1273
        target procfs <node>";
1274
  procfs_ops.to_open = procfs_open;
1275
  procfs_ops.to_attach = procfs_attach;
1276
  procfs_ops.to_post_attach = procfs_post_attach;
1277
  procfs_ops.to_detach = procfs_detach;
1278
  procfs_ops.to_resume = procfs_resume;
1279
  procfs_ops.to_wait = procfs_wait;
1280
  procfs_ops.to_fetch_registers = procfs_fetch_registers;
1281
  procfs_ops.to_store_registers = procfs_store_registers;
1282
  procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
1283
  procfs_ops.deprecated_xfer_memory = procfs_xfer_memory;
1284
  procfs_ops.to_files_info = procfs_files_info;
1285
  procfs_ops.to_insert_breakpoint = procfs_insert_breakpoint;
1286
  procfs_ops.to_remove_breakpoint = procfs_remove_breakpoint;
1287
  procfs_ops.to_can_use_hw_breakpoint = procfs_can_use_hw_breakpoint;
1288
  procfs_ops.to_insert_hw_breakpoint = procfs_insert_hw_breakpoint;
1289
  procfs_ops.to_remove_hw_breakpoint = procfs_remove_breakpoint;
1290
  procfs_ops.to_insert_watchpoint = procfs_insert_hw_watchpoint;
1291
  procfs_ops.to_remove_watchpoint = procfs_remove_hw_watchpoint;
1292
  procfs_ops.to_stopped_by_watchpoint = procfs_stopped_by_watchpoint;
1293
  procfs_ops.to_terminal_init = terminal_init_inferior;
1294
  procfs_ops.to_terminal_inferior = terminal_inferior;
1295
  procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1296
  procfs_ops.to_terminal_ours = terminal_ours;
1297
  procfs_ops.to_terminal_info = child_terminal_info;
1298
  procfs_ops.to_kill = procfs_kill_inferior;
1299
  procfs_ops.to_create_inferior = procfs_create_inferior;
1300
  procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
1301
  procfs_ops.to_can_run = procfs_can_run;
1302
  procfs_ops.to_notice_signals = procfs_notice_signals;
1303
  procfs_ops.to_thread_alive = procfs_thread_alive;
1304
  procfs_ops.to_find_new_threads = procfs_find_new_threads;
1305
  procfs_ops.to_pid_to_str = procfs_pid_to_str;
1306
  procfs_ops.to_stop = procfs_stop;
1307
  procfs_ops.to_stratum = process_stratum;
1308
  procfs_ops.to_has_all_memory = 1;
1309
  procfs_ops.to_has_memory = 1;
1310
  procfs_ops.to_has_stack = 1;
1311
  procfs_ops.to_has_registers = 1;
1312
  procfs_ops.to_has_execution = 1;
1313
  procfs_ops.to_magic = OPS_MAGIC;
1314
  procfs_ops.to_have_continuable_watchpoint = 1;
1315
}
1316
 
1317
#define OSTYPE_NTO 1
1318
 
1319
void
1320
_initialize_procfs (void)
1321
{
1322
  sigset_t set;
1323
 
1324
  init_procfs_ops ();
1325
  add_target (&procfs_ops);
1326
 
1327
  /* We use SIGUSR1 to gain control after we block waiting for a process.
1328
     We use sigwaitevent to wait.  */
1329
  sigemptyset (&set);
1330
  sigaddset (&set, SIGUSR1);
1331
  sigprocmask (SIG_BLOCK, &set, NULL);
1332
 
1333
  /* Set up trace and fault sets, as gdb expects them.  */
1334
  sigemptyset (&run.trace);
1335
 
1336
  /* Stuff some information.  */
1337
  nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags;
1338
  nto_cpuinfo_valid = 1;
1339
 
1340
  add_info ("pidlist", procfs_pidlist, _("pidlist"));
1341
  add_info ("meminfo", procfs_meminfo, _("memory information"));
1342
 
1343
  nto_is_nto_target = procfs_is_nto_target;
1344
}
1345
 
1346
 
1347
static int
1348
procfs_hw_watchpoint (int addr, int len, int type)
1349
{
1350
  procfs_break brk;
1351
 
1352
  switch (type)
1353
    {
1354
    case 1:                     /* Read.  */
1355
      brk.type = _DEBUG_BREAK_RD;
1356
      break;
1357
    case 2:                     /* Read/Write.  */
1358
      brk.type = _DEBUG_BREAK_RW;
1359
      break;
1360
    default:                    /* Modify.  */
1361
/* FIXME: brk.type = _DEBUG_BREAK_RWM gives EINVAL for some reason.  */
1362
      brk.type = _DEBUG_BREAK_RW;
1363
    }
1364
  brk.type |= _DEBUG_BREAK_HW;  /* Always ask for HW.  */
1365
  brk.addr = addr;
1366
  brk.size = len;
1367
 
1368
  errno = devctl (ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0);
1369
  if (errno != EOK)
1370
    {
1371
      perror ("Failed to set hardware watchpoint");
1372
      return -1;
1373
    }
1374
  return 0;
1375
}
1376
 
1377
static int
1378
procfs_can_use_hw_breakpoint (int type, int cnt, int othertype)
1379
{
1380
  return 1;
1381
}
1382
 
1383
static int
1384
procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type)
1385
{
1386
  return procfs_hw_watchpoint (addr, -1, type);
1387
}
1388
 
1389
static int
1390
procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type)
1391
{
1392
  return procfs_hw_watchpoint (addr, len, type);
1393
}
1394
 
1395
static int
1396
procfs_stopped_by_watchpoint (void)
1397
{
1398
  return 0;
1399
}

powered by: WebSVN 2.1.0

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