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