GDBserver

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