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