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