update copyright year range in GDB files
[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-2017 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 passing arguments ALLARGS. */
351
352 static int
353 nto_create_inferior (char *program, char **allargs)
354 {
355 struct inheritance inherit;
356 pid_t pid;
357 sigset_t set;
358
359 TRACE ("%s %s\n", __func__, program);
360 /* Clear any pending SIGUSR1's but keep the behavior the same. */
361 signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
362
363 sigemptyset (&set);
364 sigaddset (&set, SIGUSR1);
365 sigprocmask (SIG_UNBLOCK, &set, NULL);
366
367 memset (&inherit, 0, sizeof (inherit));
368 inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
369 inherit.pgroup = SPAWN_NEWPGROUP;
370 pid = spawnp (program, 0, NULL, &inherit, allargs, 0);
371 sigprocmask (SIG_BLOCK, &set, NULL);
372
373 if (pid == -1)
374 return -1;
375
376 if (do_attach (pid) != pid)
377 return -1;
378
379 return pid;
380 }
381
382 /* Attach to process PID. */
383
384 static int
385 nto_attach (unsigned long pid)
386 {
387 TRACE ("%s %ld\n", __func__, pid);
388 if (do_attach (pid) != pid)
389 error ("Unable to attach to %ld\n", pid);
390 return 0;
391 }
392
393 /* Send signal to process PID. */
394
395 static int
396 nto_kill (int pid)
397 {
398 TRACE ("%s %d\n", __func__, pid);
399 kill (pid, SIGKILL);
400 do_detach ();
401 return 0;
402 }
403
404 /* Detach from process PID. */
405
406 static int
407 nto_detach (int pid)
408 {
409 TRACE ("%s %d\n", __func__, pid);
410 do_detach ();
411 return 0;
412 }
413
414 static void
415 nto_mourn (struct process_info *process)
416 {
417 remove_process (process);
418 }
419
420 /* Check if the given thread is alive.
421
422 Return 1 if alive, 0 otherwise. */
423
424 static int
425 nto_thread_alive (ptid_t ptid)
426 {
427 int res;
428
429 TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid),
430 ptid_get_lwp (ptid));
431 if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid),
432 0, 0, 0) == -1)
433 res = 0;
434 else
435 res = 1;
436 TRACE ("%s: %s\n", __func__, res ? "yes" : "no");
437 return res;
438 }
439
440 /* Resume inferior's execution. */
441
442 static void
443 nto_resume (struct thread_resume *resume_info, size_t n)
444 {
445 /* We can only work in all-stop mode. */
446 procfs_status status;
447 procfs_run run;
448 int err;
449
450 TRACE ("%s\n", __func__);
451 /* Workaround for aliasing rules violation. */
452 sigset_t *run_fault = (sigset_t *) (void *) &run.fault;
453
454 nto_set_thread (resume_info->thread);
455
456 run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE;
457 if (resume_info->kind == resume_step)
458 run.flags |= _DEBUG_RUN_STEP;
459 run.flags |= _DEBUG_RUN_ARM;
460
461 sigemptyset (run_fault);
462 sigaddset (run_fault, FLTBPT);
463 sigaddset (run_fault, FLTTRACE);
464 sigaddset (run_fault, FLTILL);
465 sigaddset (run_fault, FLTPRIV);
466 sigaddset (run_fault, FLTBOUNDS);
467 sigaddset (run_fault, FLTIOVF);
468 sigaddset (run_fault, FLTIZDIV);
469 sigaddset (run_fault, FLTFPE);
470 sigaddset (run_fault, FLTPAGE);
471 sigaddset (run_fault, FLTSTACK);
472 sigaddset (run_fault, FLTACCESS);
473
474 sigemptyset (&run.trace);
475 if (resume_info->sig)
476 {
477 int signal_to_pass;
478
479 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
480 0);
481 signal_to_pass = resume_info->sig;
482 if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED))
483 {
484 if (signal_to_pass != status.info.si_signo)
485 {
486 kill (status.pid, signal_to_pass);
487 run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG;
488 }
489 else /* Let it kill the program without telling us. */
490 sigdelset (&run.trace, signal_to_pass);
491 }
492 }
493 else
494 run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT;
495
496 sigfillset (&run.trace);
497
498 regcache_invalidate ();
499
500 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
501 if (err != EOK)
502 TRACE ("Error: %d \"%s\"\n", err, strerror (err));
503 }
504
505 /* Wait for inferior's event.
506
507 Return ptid of thread that caused the event. */
508
509 static ptid_t
510 nto_wait (ptid_t ptid,
511 struct target_waitstatus *ourstatus, int target_options)
512 {
513 sigset_t set;
514 siginfo_t info;
515 procfs_status status;
516 const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD
517 | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY);
518
519 TRACE ("%s\n", __func__);
520
521 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
522
523 sigemptyset (&set);
524 sigaddset (&set, SIGUSR1);
525
526 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
527 while (!(status.flags & _DEBUG_FLAG_ISTOP))
528 {
529 sigwaitinfo (&set, &info);
530 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status),
531 0);
532 }
533 nto_find_new_threads (&nto_inferior);
534
535 if (status.flags & _DEBUG_FLAG_SSTEP)
536 {
537 TRACE ("SSTEP\n");
538 ourstatus->kind = TARGET_WAITKIND_STOPPED;
539 ourstatus->value.sig = GDB_SIGNAL_TRAP;
540 }
541 /* Was it a breakpoint? */
542 else if (status.flags & trace_mask)
543 {
544 TRACE ("STOPPED\n");
545 ourstatus->kind = TARGET_WAITKIND_STOPPED;
546 ourstatus->value.sig = GDB_SIGNAL_TRAP;
547 }
548 else if (status.flags & _DEBUG_FLAG_ISTOP)
549 {
550 TRACE ("ISTOP\n");
551 switch (status.why)
552 {
553 case _DEBUG_WHY_SIGNALLED:
554 TRACE (" SIGNALLED\n");
555 ourstatus->kind = TARGET_WAITKIND_STOPPED;
556 ourstatus->value.sig =
557 gdb_signal_from_host (status.info.si_signo);
558 nto_inferior.exit_signo = ourstatus->value.sig;
559 break;
560 case _DEBUG_WHY_FAULTED:
561 TRACE (" FAULTED\n");
562 ourstatus->kind = TARGET_WAITKIND_STOPPED;
563 if (status.info.si_signo == SIGTRAP)
564 {
565 ourstatus->value.sig = 0;
566 nto_inferior.exit_signo = 0;
567 }
568 else
569 {
570 ourstatus->value.sig =
571 gdb_signal_from_host (status.info.si_signo);
572 nto_inferior.exit_signo = ourstatus->value.sig;
573 }
574 break;
575
576 case _DEBUG_WHY_TERMINATED:
577 {
578 int waitval = 0;
579
580 TRACE (" TERMINATED\n");
581 waitpid (ptid_get_pid (ptid), &waitval, WNOHANG);
582 if (nto_inferior.exit_signo)
583 {
584 /* Abnormal death. */
585 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
586 ourstatus->value.sig = nto_inferior.exit_signo;
587 }
588 else
589 {
590 /* Normal death. */
591 ourstatus->kind = TARGET_WAITKIND_EXITED;
592 ourstatus->value.integer = WEXITSTATUS (waitval);
593 }
594 nto_inferior.exit_signo = 0;
595 break;
596 }
597
598 case _DEBUG_WHY_REQUESTED:
599 TRACE ("REQUESTED\n");
600 /* We are assuming a requested stop is due to a SIGINT. */
601 ourstatus->kind = TARGET_WAITKIND_STOPPED;
602 ourstatus->value.sig = GDB_SIGNAL_INT;
603 nto_inferior.exit_signo = 0;
604 break;
605 }
606 }
607
608 return ptid_build (status.pid, status.tid, 0);
609 }
610
611 /* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
612 If REGNO is -1, fetch all registers, or REGNO register only otherwise. */
613
614 static void
615 nto_fetch_registers (struct regcache *regcache, int regno)
616 {
617 int regsize;
618 procfs_greg greg;
619 ptid_t ptid;
620
621 TRACE ("%s (regno=%d)\n", __func__, regno);
622 if (regno >= the_low_target.num_regs)
623 return;
624
625 if (current_thread == NULL)
626 {
627 TRACE ("current_thread is NULL\n");
628 return;
629 }
630 ptid = thread_to_gdb_id (current_thread);
631 if (!nto_set_thread (ptid))
632 return;
633
634 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg),
635 &regsize) == EOK)
636 {
637 if (regno == -1) /* All registers. */
638 {
639 for (regno = 0; regno != the_low_target.num_regs; ++regno)
640 {
641 const unsigned int registeroffset
642 = the_low_target.register_offset (regno);
643 supply_register (regcache, regno,
644 ((char *)&greg) + registeroffset);
645 }
646 }
647 else
648 {
649 const unsigned int registeroffset
650 = the_low_target.register_offset (regno);
651 if (registeroffset == -1)
652 return;
653 supply_register (regcache, regno, ((char *)&greg) + registeroffset);
654 }
655 }
656 else
657 TRACE ("ERROR reading registers from inferior.\n");
658 }
659
660 /* Store registers for currently selected thread (CURRENT_INFERIOR).
661 We always store all registers, regardless of REGNO. */
662
663 static void
664 nto_store_registers (struct regcache *regcache, int regno)
665 {
666 procfs_greg greg;
667 int err;
668 ptid_t ptid;
669
670 TRACE ("%s (regno:%d)\n", __func__, regno);
671
672 if (current_thread == NULL)
673 {
674 TRACE ("current_thread is NULL\n");
675 return;
676 }
677 ptid = thread_to_gdb_id (current_thread);
678 if (!nto_set_thread (ptid))
679 return;
680
681 memset (&greg, 0, sizeof (greg));
682 for (regno = 0; regno != the_low_target.num_regs; ++regno)
683 {
684 const unsigned int regoffset
685 = the_low_target.register_offset (regno);
686 collect_register (regcache, regno, ((char *)&greg) + regoffset);
687 }
688 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
689 0);
690 if (err != EOK)
691 TRACE ("Error: setting registers.\n");
692 }
693
694 /* Read LEN bytes from inferior's memory address MEMADDR into
695 gdbserver's MYADDR buffer.
696
697 Return 0 on success -1 otherwise. */
698
699 static int
700 nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
701 {
702 TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len);
703
704 if (nto_xfer_memory (memaddr, myaddr, len, 0) != len)
705 {
706 TRACE ("Failed to read memory\n");
707 return -1;
708 }
709
710 return 0;
711 }
712
713 /* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
714 memory at address MEMADDR.
715
716 Return 0 on success -1 otherwise. */
717
718 static int
719 nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
720 {
721 int len_written;
722
723 TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len);
724 if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len,
725 1))
726 != len)
727 {
728 TRACE ("Wanted to write: %d but written: %d\n", len, len_written);
729 return -1;
730 }
731
732 return 0;
733 }
734
735 /* Stop inferior. We always stop all threads. */
736
737 static void
738 nto_request_interrupt (void)
739 {
740 TRACE ("%s\n", __func__);
741 nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
742 if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
743 TRACE ("Error stopping inferior.\n");
744 }
745
746 /* Read auxiliary vector from inferior's memory into gdbserver's buffer
747 MYADDR. We always read whole auxv.
748
749 Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
750 or -1 on error. */
751
752 static int
753 nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
754 {
755 int err;
756 CORE_ADDR initial_stack;
757 procfs_info procinfo;
758
759 TRACE ("%s\n", __func__);
760 if (offset > 0)
761 return 0;
762
763 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo,
764 sizeof procinfo, 0);
765 if (err != EOK)
766 return -1;
767
768 initial_stack = procinfo.initial_stack;
769
770 return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
771 }
772
773 static int
774 nto_supports_z_point_type (char z_type)
775 {
776 switch (z_type)
777 {
778 case Z_PACKET_SW_BP:
779 case Z_PACKET_HW_BP:
780 case Z_PACKET_WRITE_WP:
781 case Z_PACKET_READ_WP:
782 case Z_PACKET_ACCESS_WP:
783 return 1;
784 default:
785 return 0;
786 }
787 }
788
789 /* Insert {break/watch}point at address ADDR. SIZE is not used. */
790
791 static int
792 nto_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
793 int size, struct raw_breakpoint *bp)
794 {
795 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
796
797 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, size);
798 switch (type)
799 {
800 case raw_bkpt_type_sw:
801 wtype = _DEBUG_BREAK_EXEC;
802 break;
803 case raw_bkpt_type_hw:
804 wtype |= _DEBUG_BREAK_EXEC;
805 break;
806 case raw_bkpt_type_write_wp:
807 wtype |= _DEBUG_BREAK_RW;
808 break;
809 case raw_bkpt_type_read_wp:
810 wtype |= _DEBUG_BREAK_RD;
811 break;
812 case raw_bkpt_type_access_wp:
813 wtype |= _DEBUG_BREAK_RW;
814 break;
815 default:
816 return 1; /* Not supported. */
817 }
818 return nto_breakpoint (addr, wtype, 0);
819 }
820
821 /* Remove {break/watch}point at address ADDR. SIZE is not used. */
822
823 static int
824 nto_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
825 int size, struct raw_breakpoint *bp)
826 {
827 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
828
829 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, size);
830 switch (type)
831 {
832 case raw_bkpt_type_sw:
833 wtype = _DEBUG_BREAK_EXEC;
834 break;
835 case raw_bkpt_type_hw:
836 wtype |= _DEBUG_BREAK_EXEC;
837 break;
838 case raw_bkpt_type_write_wp:
839 wtype |= _DEBUG_BREAK_RW;
840 break;
841 case raw_bkpt_type_read_wp:
842 wtype |= _DEBUG_BREAK_RD;
843 break;
844 case raw_bkpt_type_access_wp:
845 wtype |= _DEBUG_BREAK_RW;
846 break;
847 default:
848 return 1; /* Not supported. */
849 }
850 return nto_breakpoint (addr, wtype, -1);
851 }
852
853 /* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
854 a watchpoint.
855
856 Return 1 if stopped by watchpoint, 0 otherwise. */
857
858 static int
859 nto_stopped_by_watchpoint (void)
860 {
861 int ret = 0;
862
863 TRACE ("%s\n", __func__);
864 if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
865 {
866 ptid_t ptid;
867
868 ptid = thread_to_gdb_id (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;
899
900 ptid = thread_to_gdb_id (current_thread);
901
902 if (nto_set_thread (ptid))
903 {
904 procfs_status status;
905
906 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
907 sizeof (status), 0) == EOK)
908 ret = status.ip;
909 }
910 }
911 TRACE ("%s: 0x%08lx\n", __func__, ret);
912 return ret;
913 }
914
915 /* We do not currently support non-stop. */
916
917 static int
918 nto_supports_non_stop (void)
919 {
920 TRACE ("%s\n", __func__);
921 return 0;
922 }
923
924 /* Implementation of the target_ops method "sw_breakpoint_from_kind". */
925
926 static const gdb_byte *
927 nto_sw_breakpoint_from_kind (int kind, int *size)
928 {
929 *size = the_low_target.breakpoint_len;
930 return the_low_target.breakpoint;
931 }
932
933
934 static struct target_ops nto_target_ops = {
935 nto_create_inferior,
936 NULL, /* post_create_inferior */
937 nto_attach,
938 nto_kill,
939 nto_detach,
940 nto_mourn,
941 NULL, /* nto_join */
942 nto_thread_alive,
943 nto_resume,
944 nto_wait,
945 nto_fetch_registers,
946 nto_store_registers,
947 NULL, /* prepare_to_access_memory */
948 NULL, /* done_accessing_memory */
949 nto_read_memory,
950 nto_write_memory,
951 NULL, /* nto_look_up_symbols */
952 nto_request_interrupt,
953 nto_read_auxv,
954 nto_supports_z_point_type,
955 nto_insert_point,
956 nto_remove_point,
957 NULL, /* stopped_by_sw_breakpoint */
958 NULL, /* supports_stopped_by_sw_breakpoint */
959 NULL, /* stopped_by_hw_breakpoint */
960 NULL, /* supports_stopped_by_hw_breakpoint */
961 target_can_do_hardware_single_step,
962 nto_stopped_by_watchpoint,
963 nto_stopped_data_address,
964 NULL, /* nto_read_offsets */
965 NULL, /* thread_db_set_tls_address */
966 NULL,
967 hostio_last_error_from_errno,
968 NULL, /* nto_qxfer_osdata */
969 NULL, /* xfer_siginfo */
970 nto_supports_non_stop,
971 NULL, /* async */
972 NULL, /* start_non_stop */
973 NULL, /* supports_multi_process */
974 NULL, /* supports_fork_events */
975 NULL, /* supports_vfork_events */
976 NULL, /* supports_exec_events */
977 NULL, /* handle_new_gdb_connection */
978 NULL, /* handle_monitor_command */
979 NULL, /* core_of_thread */
980 NULL, /* read_loadmap */
981 NULL, /* process_qsupported */
982 NULL, /* supports_tracepoints */
983 NULL, /* read_pc */
984 NULL, /* write_pc */
985 NULL, /* thread_stopped */
986 NULL, /* get_tib_address */
987 NULL, /* pause_all */
988 NULL, /* unpause_all */
989 NULL, /* stabilize_threads */
990 NULL, /* install_fast_tracepoint_jump_pad */
991 NULL, /* emit_ops */
992 NULL, /* supports_disable_randomization */
993 NULL, /* get_min_fast_tracepoint_insn_len */
994 NULL, /* qxfer_libraries_svr4 */
995 NULL, /* support_agent */
996 NULL, /* support_btrace */
997 NULL, /* enable_btrace */
998 NULL, /* disable_btrace */
999 NULL, /* read_btrace */
1000 NULL, /* read_btrace_conf */
1001 NULL, /* supports_range_stepping */
1002 NULL, /* pid_to_exec_file */
1003 NULL, /* multifs_open */
1004 NULL, /* multifs_unlink */
1005 NULL, /* multifs_readlink */
1006 NULL, /* breakpoint_kind_from_pc */
1007 nto_sw_breakpoint_from_kind,
1008 };
1009
1010
1011 /* Global function called by server.c. Initializes QNX Neutrino
1012 gdbserver. */
1013
1014 void
1015 initialize_low (void)
1016 {
1017 sigset_t set;
1018
1019 TRACE ("%s\n", __func__);
1020 set_target_ops (&nto_target_ops);
1021
1022 /* We use SIGUSR1 to gain control after we block waiting for a process.
1023 We use sigwaitevent to wait. */
1024 sigemptyset (&set);
1025 sigaddset (&set, SIGUSR1);
1026 sigprocmask (SIG_BLOCK, &set, NULL);
1027 }
1028
This page took 0.064793 seconds and 5 git commands to generate.