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