GDBserver disconnected tracing support.
[deliverable/binutils-gdb.git] / gdb / gdbserver / nto-low.c
1 /* QNX Neutrino specific low level interface, for the remote server
2 for GDB.
3 Copyright (C) 2009, 2010 Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>. */
19
20
21 #include "server.h"
22 #include "nto-low.h"
23
24 #include <limits.h>
25 #include <fcntl.h>
26 #include <spawn.h>
27 #include <sys/procfs.h>
28 #include <sys/auxv.h>
29 #include <stdarg.h>
30 #include <sys/iomgr.h>
31 #include <sys/neutrino.h>
32
33
34 extern int using_threads;
35 int using_threads = 1;
36
37 static void
38 nto_trace (const char *fmt, ...)
39 {
40 va_list arg_list;
41
42 if (debug_threads == 0)
43 return;
44 fprintf (stderr, "nto:");
45 va_start (arg_list, fmt);
46 vfprintf (stderr, fmt, arg_list);
47 va_end (arg_list);
48 }
49
50 #define TRACE nto_trace
51
52 /* Structure holding neutrino specific information about
53 inferior. */
54
55 struct nto_inferior
56 {
57 char nto_procfs_path[PATH_MAX];
58 int ctl_fd;
59 pid_t pid;
60 int exit_signo; /* For tracking exit status. */
61 };
62
63 static struct nto_inferior nto_inferior;
64
65 static void
66 init_nto_inferior (struct nto_inferior *nto_inferior)
67 {
68 memset (nto_inferior, 0, sizeof (struct nto_inferior));
69 nto_inferior->ctl_fd = -1;
70 nto_inferior->pid = -1;
71 }
72
73 static void
74 do_detach (void)
75 {
76 if (nto_inferior.ctl_fd != -1)
77 {
78 nto_trace ("Closing fd\n");
79 close (nto_inferior.ctl_fd);
80 init_nto_inferior (&nto_inferior);
81 }
82 }
83
84 /* Set current thread. Return 1 on success, 0 otherwise. */
85
86 static int
87 nto_set_thread (ptid_t ptid)
88 {
89 int res = 0;
90
91 TRACE ("%s pid: %d tid: %ld\n", __func__, ptid_get_pid (ptid),
92 ptid_get_lwp (ptid));
93 if (nto_inferior.ctl_fd != -1
94 && !ptid_equal (ptid, null_ptid)
95 && !ptid_equal (ptid, minus_one_ptid))
96 {
97 pthread_t tid = ptid_get_lwp (ptid);
98
99 if (EOK == devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid,
100 sizeof (tid), 0))
101 res = 1;
102 else
103 TRACE ("%s: Error: failed to set current thread\n", __func__);
104 }
105 return res;
106 }
107
108 /* This function will determine all alive threads. Note that we do not list
109 dead but unjoined threads even though they are still in the process' thread
110 list.
111
112 NTO_INFERIOR must not be NULL. */
113
114 static void
115 nto_find_new_threads (struct nto_inferior *nto_inferior)
116 {
117 pthread_t tid;
118
119 TRACE ("%s pid:%d\n", __func__, nto_inferior->pid);
120
121 if (nto_inferior->ctl_fd == -1)
122 return;
123
124 for (tid = 1;; ++tid)
125 {
126 procfs_status status;
127 ptid_t ptid;
128 int err;
129
130 status.tid = tid;
131 err = devctl (nto_inferior->ctl_fd, DCMD_PROC_TIDSTATUS, &status,
132 sizeof (status), 0);
133
134 if (err != EOK || status.tid == 0)
135 break;
136
137 /* All threads in between are gone. */
138 while (tid != status.tid || status.state == STATE_DEAD)
139 {
140 struct thread_info *ti;
141
142 ptid = ptid_build (nto_inferior->pid, tid, 0);
143 ti = find_thread_ptid (ptid);
144 if (ti != NULL)
145 {
146 TRACE ("Removing thread %d\n", tid);
147 remove_thread (ti);
148 }
149 if (tid == status.tid)
150 break;
151 ++tid;
152 }
153
154 if (status.state != STATE_DEAD)
155 {
156 TRACE ("Adding thread %d\n", tid);
157 ptid = ptid_build (nto_inferior->pid, tid, 0);
158 if (!find_thread_ptid (ptid))
159 add_thread (ptid, NULL);
160 }
161 }
162 }
163
164 /* Given pid, open procfs path. */
165
166 static pid_t
167 do_attach (pid_t pid)
168 {
169 procfs_status status;
170 struct sigevent event;
171
172 if (nto_inferior.ctl_fd != -1)
173 {
174 close (nto_inferior.ctl_fd);
175 init_nto_inferior (&nto_inferior);
176 }
177 snprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
178 nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR);
179 if (nto_inferior.ctl_fd == -1)
180 {
181 TRACE ("Failed to open %s\n", nto_inferior.nto_procfs_path);
182 init_nto_inferior (&nto_inferior);
183 return -1;
184 }
185 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0)
186 != EOK)
187 {
188 do_detach ();
189 return -1;
190 }
191 nto_inferior.pid = pid;
192 /* Define a sigevent for process stopped notification. */
193 event.sigev_notify = SIGEV_SIGNAL_THREAD;
194 event.sigev_signo = SIGUSR1;
195 event.sigev_code = 0;
196 event.sigev_value.sival_ptr = NULL;
197 event.sigev_priority = -1;
198 devctl (nto_inferior.ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0);
199
200 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
201 0) == EOK
202 && (status.flags & _DEBUG_FLAG_STOPPED))
203 {
204 ptid_t ptid;
205
206 kill (pid, SIGCONT);
207 ptid = ptid_build (status.pid, status.tid, 0);
208 the_low_target.arch_setup ();
209 add_process (status.pid, 1);
210 TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid,
211 ptid_get_lwp (ptid));
212 nto_find_new_threads (&nto_inferior);
213 }
214 else
215 {
216 do_detach ();
217 return -1;
218 }
219
220 return pid;
221 }
222
223 /* Read or write LEN bytes from/to inferior's MEMADDR memory address
224 into gdbservers's MYADDR buffer. Return number of bytes actually
225 transfered. */
226
227 static int
228 nto_xfer_memory (off_t memaddr, unsigned char *myaddr, int len,
229 int dowrite)
230 {
231 int nbytes = 0;
232
233 if (lseek (nto_inferior.ctl_fd, memaddr, SEEK_SET) == memaddr)
234 {
235 if (dowrite)
236 nbytes = write (nto_inferior.ctl_fd, myaddr, len);
237 else
238 nbytes = read (nto_inferior.ctl_fd, myaddr, len);
239 if (nbytes < 0)
240 nbytes = 0;
241 }
242 if (nbytes == 0)
243 {
244 int e = errno;
245 TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, strerror (e));
246 }
247 return nbytes;
248 }
249
250 /* Insert or remove breakpoint or watchpoint at address ADDR.
251 TYPE can be one of Neutrino breakpoint types. SIZE must be 0 for
252 inserting the point, -1 for removing it.
253
254 Return 0 on success, 1 otherwise. */
255
256 static int
257 nto_breakpoint (CORE_ADDR addr, int type, int size)
258 {
259 procfs_break brk;
260
261 brk.type = type;
262 brk.addr = addr;
263 brk.size = size;
264 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0)
265 != EOK)
266 return 1;
267 return 0;
268 }
269
270 /* Read auxiliary vector from inferior's initial stack into gdbserver's
271 MYADDR buffer, up to LEN bytes.
272
273 Return number of bytes read. */
274
275 static int
276 nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack,
277 unsigned char *myaddr,
278 unsigned int len)
279 {
280 int data_ofs = 0;
281 int anint;
282 unsigned int len_read = 0;
283
284 /* Skip over argc, argv and envp... Comment from ldd.c:
285
286 The startup frame is set-up so that we have:
287 auxv
288 NULL
289 ...
290 envp2
291 envp1 <----- void *frame + (argc + 2) * sizeof(char *)
292 NULL
293 ...
294 argv2
295 argv1
296 argc <------ void * frame
297
298 On entry to ldd, frame gives the address of argc on the stack. */
299 if (nto_xfer_memory (initial_stack, (unsigned char *)&anint,
300 sizeof (anint), 0) != sizeof (anint))
301 return 0;
302
303 /* Size of pointer is assumed to be 4 bytes (32 bit arch. ) */
304 data_ofs += (anint + 2) * sizeof (void *); /* + 2 comes from argc itself and
305 NULL terminating pointer in
306 argv. */
307
308 /* Now loop over env table: */
309 while (nto_xfer_memory (initial_stack + data_ofs,
310 (unsigned char *)&anint, sizeof (anint), 0)
311 == sizeof (anint))
312 {
313 data_ofs += sizeof (anint);
314 if (anint == 0)
315 break;
316 }
317 initial_stack += data_ofs;
318
319 memset (myaddr, 0, len);
320 while (len_read <= len - sizeof (auxv_t))
321 {
322 auxv_t *auxv = (auxv_t *)myaddr;
323
324 /* Search backwards until we have read AT_PHDR (num. 3),
325 AT_PHENT (num 4), AT_PHNUM (num 5) */
326 if (nto_xfer_memory (initial_stack, (unsigned char *)auxv,
327 sizeof (auxv_t), 0) == sizeof (auxv_t))
328 {
329 if (auxv->a_type != AT_NULL)
330 {
331 auxv++;
332 len_read += sizeof (auxv_t);
333 }
334 if (auxv->a_type == AT_PHNUM) /* That's all we need. */
335 break;
336 initial_stack += sizeof (auxv_t);
337 }
338 else
339 break;
340 }
341 TRACE ("auxv: len_read: %d\n", len_read);
342 return len_read;
343 }
344
345 /* Start inferior specified by PROGRAM passing arguments ALLARGS. */
346
347 static int
348 nto_create_inferior (char *program, char **allargs)
349 {
350 struct inheritance inherit;
351 pid_t pid;
352 sigset_t set;
353
354 TRACE ("%s %s\n", __func__, program);
355 /* Clear any pending SIGUSR1's but keep the behavior the same. */
356 signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
357
358 sigemptyset (&set);
359 sigaddset (&set, SIGUSR1);
360 sigprocmask (SIG_UNBLOCK, &set, NULL);
361
362 memset (&inherit, 0, sizeof (inherit));
363 inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
364 inherit.pgroup = SPAWN_NEWPGROUP;
365 pid = spawnp (program, 0, NULL, &inherit, allargs, 0);
366 sigprocmask (SIG_BLOCK, &set, NULL);
367
368 if (pid == -1)
369 return -1;
370
371 if (do_attach (pid) != pid)
372 return -1;
373
374 return pid;
375 }
376
377 /* Attach to process PID. */
378
379 static int
380 nto_attach (unsigned long pid)
381 {
382 TRACE ("%s %ld\n", __func__, pid);
383 if (do_attach (pid) != pid)
384 error ("Unable to attach to %ld\n", pid);
385 return 0;
386 }
387
388 /* Send signal to process PID. */
389
390 static int
391 nto_kill (int pid)
392 {
393 TRACE ("%s %d\n", __func__, pid);
394 kill (pid, SIGKILL);
395 do_detach ();
396 return 0;
397 }
398
399 /* Detach from process PID. */
400
401 static int
402 nto_detach (int pid)
403 {
404 TRACE ("%s %d\n", __func__, pid);
405 do_detach ();
406 return 0;
407 }
408
409 /* Check if the given thread is alive.
410
411 Return 1 if alive, 0 otherwise. */
412
413 static int
414 nto_thread_alive (ptid_t ptid)
415 {
416 int res;
417
418 TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid),
419 ptid_get_lwp (ptid));
420 if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid),
421 0, 0, 0) == -1)
422 res = 0;
423 else
424 res = 1;
425 TRACE ("%s: %s\n", __func__, res ? "yes" : "no");
426 return res;
427 }
428
429 /* Resume inferior's execution. */
430
431 static void
432 nto_resume (struct thread_resume *resume_info, size_t n)
433 {
434 /* We can only work in all-stop mode. */
435 procfs_status status;
436 procfs_run run;
437 int err;
438
439 TRACE ("%s\n", __func__);
440 /* Workaround for aliasing rules violation. */
441 sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
442
443 nto_set_thread (resume_info->thread);
444
445 run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
446 if (resume_info->kind == resume_step)
447 run.flags |= _DEBUG_RUN_STEP;
448 run.flags |= _DEBUG_RUN_ARM;
449
450 sigemptyset (run_fault);
451 sigaddset (run_fault, FLTBPT);
452 sigaddset (run_fault, FLTTRACE);
453 sigaddset (run_fault, FLTILL);
454 sigaddset (run_fault, FLTPRIV);
455 sigaddset (run_fault, FLTBOUNDS);
456 sigaddset (run_fault, FLTIOVF);
457 sigaddset (run_fault, FLTIZDIV);
458 sigaddset (run_fault, FLTFPE);
459 sigaddset (run_fault, FLTPAGE);
460 sigaddset (run_fault, FLTSTACK);
461 sigaddset (run_fault, FLTACCESS);
462
463 sigemptyset (&run.trace);
464 if (resume_info->sig)
465 {
466 int signal_to_pass;
467
468 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
469 0);
470 signal_to_pass = resume_info->sig;
471 if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
472 {
473 if (signal_to_pass != status.info.si_signo)
474 {
475 kill (status.pid, signal_to_pass);
476 run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
477 }
478 else /* Let it kill the program without telling us. */
479 sigdelset (&run.trace, signal_to_pass);
480 }
481 }
482 else
483 run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
484
485 sigfillset (&run.trace);
486
487 regcache_invalidate ();
488
489 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
490 if (err != EOK)
491 TRACE ("Error: %d \"%s\"\n", err, strerror (err));
492 }
493
494 /* Wait for inferior's event.
495
496 Return ptid of thread that caused the event. */
497
498 static ptid_t
499 nto_wait (ptid_t ptid,
500 struct target_waitstatus *ourstatus, int target_options)
501 {
502 sigset_t set;
503 siginfo_t info;
504 procfs_status status;
505 const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD
506 | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY);
507
508 TRACE ("%s\n", __func__);
509
510 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
511
512 sigemptyset (&set);
513 sigaddset (&set, SIGUSR1);
514
515 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
516 while (!(status.flags & _DEBUG_FLAG_ISTOP))
517 {
518 sigwaitinfo (&set, &info);
519 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
520 0);
521 }
522 nto_find_new_threads (&nto_inferior);
523
524 if (status.flags & _DEBUG_FLAG_SSTEP)
525 {
526 TRACE ("SSTEP\n");
527 ourstatus->kind = TARGET_WAITKIND_STOPPED;
528 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
529 }
530 /* Was it a breakpoint? */
531 else if (status.flags & trace_mask)
532 {
533 TRACE ("STOPPED\n");
534 ourstatus->kind = TARGET_WAITKIND_STOPPED;
535 ourstatus->value.sig = TARGET_SIGNAL_TRAP;
536 }
537 else if (status.flags & _DEBUG_FLAG_ISTOP)
538 {
539 TRACE ("ISTOP\n");
540 switch (status.why)
541 {
542 case _DEBUG_WHY_SIGNALLED:
543 TRACE (" SIGNALLED\n");
544 ourstatus->kind = TARGET_WAITKIND_STOPPED;
545 ourstatus->value.sig =
546 target_signal_from_host (status.info.si_signo);
547 nto_inferior.exit_signo = ourstatus->value.sig;
548 break;
549 case _DEBUG_WHY_FAULTED:
550 TRACE (" FAULTED\n");
551 ourstatus->kind = TARGET_WAITKIND_STOPPED;
552 if (status.info.si_signo == SIGTRAP)
553 {
554 ourstatus->value.sig = 0;
555 nto_inferior.exit_signo = 0;
556 }
557 else
558 {
559 ourstatus->value.sig =
560 target_signal_from_host (status.info.si_signo);
561 nto_inferior.exit_signo = ourstatus->value.sig;
562 }
563 break;
564
565 case _DEBUG_WHY_TERMINATED:
566 {
567 int waitval = 0;
568
569 TRACE (" TERMINATED\n");
570 waitpid (ptid_get_pid (ptid), &waitval, WNOHANG);
571 if (nto_inferior.exit_signo)
572 {
573 /* Abnormal death. */
574 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
575 ourstatus->value.sig = nto_inferior.exit_signo;
576 }
577 else
578 {
579 /* Normal death. */
580 ourstatus->kind = TARGET_WAITKIND_EXITED;
581 ourstatus->value.integer = WEXITSTATUS (waitval);
582 }
583 nto_inferior.exit_signo = 0;
584 break;
585 }
586
587 case _DEBUG_WHY_REQUESTED:
588 TRACE ("REQUESTED\n");
589 /* We are assuming a requested stop is due to a SIGINT. */
590 ourstatus->kind = TARGET_WAITKIND_STOPPED;
591 ourstatus->value.sig = TARGET_SIGNAL_INT;
592 nto_inferior.exit_signo = 0;
593 break;
594 }
595 }
596
597 return ptid_build (status.pid, status.tid, 0);
598 }
599
600 /* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
601 If REGNO is -1, fetch all registers, or REGNO register only otherwise. */
602
603 static void
604 nto_fetch_registers (struct regcache *regcache, int regno)
605 {
606 int regsize;
607 procfs_greg greg;
608 ptid_t ptid;
609
610 TRACE ("%s (regno=%d)\n", __func__, regno);
611 if (regno >= the_low_target.num_regs)
612 return;
613
614 if (current_inferior == NULL)
615 {
616 TRACE ("current_inferior is NULL\n");
617 return;
618 }
619 ptid = thread_to_gdb_id (current_inferior);
620 if (!nto_set_thread (ptid))
621 return;
622
623 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg),
624 &regsize) == EOK)
625 {
626 if (regno == -1) /* All registers. */
627 {
628 for (regno = 0; regno != the_low_target.num_regs; ++regno)
629 {
630 const unsigned int registeroffset
631 = the_low_target.register_offset (regno);
632 supply_register (regcache, regno, ((char *)&greg) + registeroffset);
633 }
634 }
635 else
636 {
637 const unsigned int registeroffset
638 = the_low_target.register_offset (regno);
639 if (registeroffset == -1)
640 return;
641 supply_register (regcache, regno, ((char *)&greg) + registeroffset);
642 }
643 }
644 else
645 TRACE ("ERROR reading registers from inferior.\n");
646 }
647
648 /* Store registers for currently selected thread (CURRENT_INFERIOR).
649 We always store all registers, regardless of REGNO. */
650
651 static void
652 nto_store_registers (struct regcache *regcache, int regno)
653 {
654 procfs_greg greg;
655 int err;
656 ptid_t ptid;
657
658 TRACE ("%s (regno:%d)\n", __func__, regno);
659
660 if (current_inferior == NULL)
661 {
662 TRACE ("current_inferior is NULL\n");
663 return;
664 }
665 ptid = thread_to_gdb_id (current_inferior);
666 if (!nto_set_thread (ptid))
667 return;
668
669 memset (&greg, 0, sizeof (greg));
670 for (regno = 0; regno != the_low_target.num_regs; ++regno)
671 {
672 const unsigned int regoffset
673 = the_low_target.register_offset (regno);
674 collect_register (regcache, regno, ((char *)&greg) + regoffset);
675 }
676 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
677 0);
678 if (err != EOK)
679 TRACE ("Error: setting registers.\n");
680 }
681
682 /* Read LEN bytes from inferior's memory address MEMADDR into
683 gdbserver's MYADDR buffer.
684
685 Return 0 on success -1 otherwise. */
686
687 static int
688 nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
689 {
690 TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len);
691
692 if (nto_xfer_memory (memaddr, myaddr, len, 0) != len)
693 {
694 TRACE ("Failed to read memory\n");
695 return -1;
696 }
697
698 return 0;
699 }
700
701 /* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
702 memory at address MEMADDR.
703
704 Return 0 on success -1 otherwise. */
705
706 static int
707 nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
708 {
709 int len_written;
710
711 TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len);
712 if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len,
713 1))
714 != len)
715 {
716 TRACE ("Wanted to write: %d but written: %d\n", len, len_written);
717 return -1;
718 }
719
720 return 0;
721 }
722
723 /* Stop inferior. We always stop all threads. */
724
725 static void
726 nto_request_interrupt (void)
727 {
728 TRACE ("%s\n", __func__);
729 nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
730 if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
731 TRACE ("Error stopping inferior.\n");
732 }
733
734 /* Read auxiliary vector from inferior's memory into gdbserver's buffer
735 MYADDR. We always read whole auxv.
736
737 Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
738 or -1 on error. */
739
740 static int
741 nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
742 {
743 int err;
744 CORE_ADDR initial_stack;
745 procfs_info procinfo;
746
747 TRACE ("%s\n", __func__);
748 if (offset > 0)
749 return 0;
750
751 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo,
752 sizeof procinfo, 0);
753 if (err != EOK)
754 return -1;
755
756 initial_stack = procinfo.initial_stack;
757
758 return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
759 }
760
761 /* Insert {break/watch}point at address ADDR.
762 TYPE must be in '0'..'4' range. LEN is not used. */
763
764 static int
765 nto_insert_point (char type, CORE_ADDR addr, int len)
766 {
767 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
768
769 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
770 switch (type)
771 {
772 case '0': /* software-breakpoint */
773 wtype = _DEBUG_BREAK_EXEC;
774 break;
775 case '1': /* hardware-breakpoint */
776 wtype |= _DEBUG_BREAK_EXEC;
777 break;
778 case '2': /* write watchpoint */
779 wtype |= _DEBUG_BREAK_RW;
780 break;
781 case '3': /* read watchpoint */
782 wtype |= _DEBUG_BREAK_RD;
783 break;
784 case '4': /* access watchpoint */
785 wtype |= _DEBUG_BREAK_RW;
786 break;
787 default:
788 return 1; /* Not supported. */
789 }
790 return nto_breakpoint (addr, wtype, 0);
791 }
792
793 /* Remove {break/watch}point at address ADDR.
794 TYPE must be in '0'..'4' range. LEN is not used. */
795
796 static int
797 nto_remove_point (char type, CORE_ADDR addr, int len)
798 {
799 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
800
801 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
802 switch (type)
803 {
804 case '0': /* software-breakpoint */
805 wtype = _DEBUG_BREAK_EXEC;
806 break;
807 case '1': /* hardware-breakpoint */
808 wtype |= _DEBUG_BREAK_EXEC;
809 break;
810 case '2': /* write watchpoint */
811 wtype |= _DEBUG_BREAK_RW;
812 break;
813 case '3': /* read watchpoint */
814 wtype |= _DEBUG_BREAK_RD;
815 break;
816 case '4': /* access watchpoint */
817 wtype |= _DEBUG_BREAK_RW;
818 break;
819 default:
820 return 1; /* Not supported. */
821 }
822 return nto_breakpoint (addr, wtype, -1);
823 }
824
825 /* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
826 a watchpoint.
827
828 Return 1 if stopped by watchpoint, 0 otherwise. */
829
830 static int
831 nto_stopped_by_watchpoint (void)
832 {
833 int ret = 0;
834
835 TRACE ("%s\n", __func__);
836 if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
837 {
838 ptid_t ptid;
839
840 ptid = thread_to_gdb_id (current_inferior);
841 if (nto_set_thread (ptid))
842 {
843 const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
844 | _DEBUG_FLAG_TRACE_MODIFY;
845 procfs_status status;
846 int err;
847
848 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
849 sizeof (status), 0);
850 if (err == EOK && (status.flags & watchmask))
851 ret = 1;
852 }
853 }
854 TRACE ("%s: %s\n", __func__, ret ? "yes" : "no");
855 return ret;
856 }
857
858 /* Get instruction pointer for CURRENT_INFERIOR thread.
859
860 Return inferior's instruction pointer value, or 0 on error. */
861
862 static CORE_ADDR
863 nto_stopped_data_address (void)
864 {
865 CORE_ADDR ret = (CORE_ADDR)0;
866
867 TRACE ("%s\n", __func__);
868 if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
869 {
870 ptid_t ptid;
871
872 ptid = thread_to_gdb_id (current_inferior);
873
874 if (nto_set_thread (ptid))
875 {
876 procfs_status status;
877
878 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
879 sizeof (status), 0) == EOK)
880 ret = status.ip;
881 }
882 }
883 TRACE ("%s: 0x%08lx\n", __func__, ret);
884 return ret;
885 }
886
887 /* We do not currently support non-stop. */
888
889 static int
890 nto_supports_non_stop (void)
891 {
892 TRACE ("%s\n", __func__);
893 return 0;
894 }
895
896
897
898 static struct target_ops nto_target_ops = {
899 nto_create_inferior,
900 nto_attach,
901 nto_kill,
902 nto_detach,
903 NULL, /* nto_mourn */
904 NULL, /* nto_join */
905 nto_thread_alive,
906 nto_resume,
907 nto_wait,
908 nto_fetch_registers,
909 nto_store_registers,
910 nto_read_memory,
911 nto_write_memory,
912 NULL, /* nto_look_up_symbols */
913 nto_request_interrupt,
914 nto_read_auxv,
915 nto_insert_point,
916 nto_remove_point,
917 nto_stopped_by_watchpoint,
918 nto_stopped_data_address,
919 NULL, /* nto_read_offsets */
920 NULL, /* thread_db_set_tls_address */
921 NULL,
922 hostio_last_error_from_errno,
923 NULL, /* nto_qxfer_osdata */
924 NULL, /* xfer_siginfo */
925 nto_supports_non_stop,
926 NULL, /* async */
927 NULL /* start_non_stop */
928 };
929
930
931 /* Global function called by server.c. Initializes QNX Neutrino
932 gdbserver. */
933
934 void
935 initialize_low (void)
936 {
937 sigset_t set;
938
939 TRACE ("%s\n", __func__);
940 set_target_ops (&nto_target_ops);
941 set_breakpoint_data (the_low_target.breakpoint,
942 the_low_target.breakpoint_len);
943
944 /* We use SIGUSR1 to gain control after we block waiting for a process.
945 We use sigwaitevent to wait. */
946 sigemptyset (&set);
947 sigaddset (&set, SIGUSR1);
948 sigprocmask (SIG_BLOCK, &set, NULL);
949 }
950
This page took 0.049513 seconds and 5 git commands to generate.