daily update
[deliverable/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.
4c38e0a4 3 Copyright (C) 2009, 2010 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 }
177 snprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
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);
442ea881 638 supply_register (regcache, regno, ((char *)&greg) + registeroffset);
ac8c974e
AR
639 }
640 }
641 else
642 {
643 const unsigned int registeroffset
644 = the_low_target.register_offset (regno);
645 if (registeroffset == -1)
646 return;
442ea881 647 supply_register (regcache, regno, ((char *)&greg) + registeroffset);
ac8c974e
AR
648 }
649 }
650 else
651 TRACE ("ERROR reading registers from inferior.\n");
652}
653
654/* Store registers for currently selected thread (CURRENT_INFERIOR).
655 We always store all registers, regardless of REGNO. */
656
657static void
442ea881 658nto_store_registers (struct regcache *regcache, int regno)
ac8c974e
AR
659{
660 procfs_greg greg;
661 int err;
662 ptid_t ptid;
663
664 TRACE ("%s (regno:%d)\n", __func__, regno);
665
666 if (current_inferior == NULL)
667 {
668 TRACE ("current_inferior is NULL\n");
669 return;
670 }
671 ptid = thread_to_gdb_id (current_inferior);
672 if (!nto_set_thread (ptid))
673 return;
674
675 memset (&greg, 0, sizeof (greg));
676 for (regno = 0; regno != the_low_target.num_regs; ++regno)
677 {
678 const unsigned int regoffset
679 = the_low_target.register_offset (regno);
442ea881 680 collect_register (regcache, regno, ((char *)&greg) + regoffset);
ac8c974e
AR
681 }
682 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
683 0);
684 if (err != EOK)
685 TRACE ("Error: setting registers.\n");
686}
687
688/* Read LEN bytes from inferior's memory address MEMADDR into
689 gdbserver's MYADDR buffer.
690
691 Return 0 on success -1 otherwise. */
692
693static int
694nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
695{
696 TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len);
697
698 if (nto_xfer_memory (memaddr, myaddr, len, 0) != len)
699 {
700 TRACE ("Failed to read memory\n");
701 return -1;
702 }
703
704 return 0;
705}
706
707/* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
708 memory at address MEMADDR.
709
710 Return 0 on success -1 otherwise. */
711
712static int
713nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
714{
715 int len_written;
716
717 TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len);
718 if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len,
719 1))
720 != len)
721 {
722 TRACE ("Wanted to write: %d but written: %d\n", len, len_written);
723 return -1;
724 }
725
726 return 0;
727}
728
729/* Stop inferior. We always stop all threads. */
730
731static void
732nto_request_interrupt (void)
733{
734 TRACE ("%s\n", __func__);
735 nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
736 if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
737 TRACE ("Error stopping inferior.\n");
738}
739
740/* Read auxiliary vector from inferior's memory into gdbserver's buffer
741 MYADDR. We always read whole auxv.
742
743 Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
744 or -1 on error. */
745
746static int
747nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
748{
749 int err;
750 CORE_ADDR initial_stack;
751 procfs_info procinfo;
752
753 TRACE ("%s\n", __func__);
754 if (offset > 0)
755 return 0;
756
757 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo,
758 sizeof procinfo, 0);
759 if (err != EOK)
760 return -1;
761
762 initial_stack = procinfo.initial_stack;
763
764 return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
765}
766
767/* Insert {break/watch}point at address ADDR.
768 TYPE must be in '0'..'4' range. LEN is not used. */
769
770static int
771nto_insert_point (char type, CORE_ADDR addr, int len)
772{
773 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
774
775 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
776 switch (type)
777 {
778 case '0': /* software-breakpoint */
779 wtype = _DEBUG_BREAK_EXEC;
780 break;
781 case '1': /* hardware-breakpoint */
782 wtype |= _DEBUG_BREAK_EXEC;
783 break;
784 case '2': /* write watchpoint */
785 wtype |= _DEBUG_BREAK_RW;
786 break;
787 case '3': /* read watchpoint */
788 wtype |= _DEBUG_BREAK_RD;
789 break;
790 case '4': /* access watchpoint */
791 wtype |= _DEBUG_BREAK_RW;
792 break;
793 default:
794 return 1; /* Not supported. */
795 }
796 return nto_breakpoint (addr, wtype, 0);
797}
798
799/* Remove {break/watch}point at address ADDR.
800 TYPE must be in '0'..'4' range. LEN is not used. */
801
802static int
803nto_remove_point (char type, CORE_ADDR addr, int len)
804{
805 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
806
807 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
808 switch (type)
809 {
810 case '0': /* software-breakpoint */
811 wtype = _DEBUG_BREAK_EXEC;
812 break;
813 case '1': /* hardware-breakpoint */
814 wtype |= _DEBUG_BREAK_EXEC;
815 break;
816 case '2': /* write watchpoint */
817 wtype |= _DEBUG_BREAK_RW;
818 break;
819 case '3': /* read watchpoint */
820 wtype |= _DEBUG_BREAK_RD;
821 break;
822 case '4': /* access watchpoint */
823 wtype |= _DEBUG_BREAK_RW;
824 break;
825 default:
826 return 1; /* Not supported. */
827 }
828 return nto_breakpoint (addr, wtype, -1);
829}
830
831/* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
832 a watchpoint.
833
834 Return 1 if stopped by watchpoint, 0 otherwise. */
835
836static int
837nto_stopped_by_watchpoint (void)
838{
839 int ret = 0;
840
841 TRACE ("%s\n", __func__);
842 if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
843 {
844 ptid_t ptid;
845
846 ptid = thread_to_gdb_id (current_inferior);
847 if (nto_set_thread (ptid))
848 {
849 const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
850 | _DEBUG_FLAG_TRACE_MODIFY;
851 procfs_status status;
852 int err;
853
854 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
855 sizeof (status), 0);
856 if (err == EOK && (status.flags & watchmask))
857 ret = 1;
858 }
859 }
860 TRACE ("%s: %s\n", __func__, ret ? "yes" : "no");
861 return ret;
862}
863
864/* Get instruction pointer for CURRENT_INFERIOR thread.
865
866 Return inferior's instruction pointer value, or 0 on error. */
867
868static CORE_ADDR
869nto_stopped_data_address (void)
870{
871 CORE_ADDR ret = (CORE_ADDR)0;
872
873 TRACE ("%s\n", __func__);
874 if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
875 {
876 ptid_t ptid;
877
878 ptid = thread_to_gdb_id (current_inferior);
879
880 if (nto_set_thread (ptid))
881 {
882 procfs_status status;
883
884 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status,
885 sizeof (status), 0) == EOK)
886 ret = status.ip;
887 }
888 }
889 TRACE ("%s: 0x%08lx\n", __func__, ret);
890 return ret;
891}
892
893/* We do not currently support non-stop. */
894
895static int
896nto_supports_non_stop (void)
897{
898 TRACE ("%s\n", __func__);
899 return 0;
900}
901
902
903
904static struct target_ops nto_target_ops = {
905 nto_create_inferior,
906 nto_attach,
907 nto_kill,
908 nto_detach,
505106cd 909 nto_mourn,
ac8c974e
AR
910 NULL, /* nto_join */
911 nto_thread_alive,
912 nto_resume,
913 nto_wait,
914 nto_fetch_registers,
915 nto_store_registers,
90d74c30
PA
916 NULL, /* prepare_to_access_memory */
917 NULL, /* unprepare_to_access_memory */
ac8c974e
AR
918 nto_read_memory,
919 nto_write_memory,
920 NULL, /* nto_look_up_symbols */
921 nto_request_interrupt,
922 nto_read_auxv,
923 nto_insert_point,
924 nto_remove_point,
925 nto_stopped_by_watchpoint,
926 nto_stopped_data_address,
927 NULL, /* nto_read_offsets */
928 NULL, /* thread_db_set_tls_address */
929 NULL,
930 hostio_last_error_from_errno,
931 NULL, /* nto_qxfer_osdata */
932 NULL, /* xfer_siginfo */
933 nto_supports_non_stop,
934 NULL, /* async */
935 NULL /* start_non_stop */
936};
937
938
939/* Global function called by server.c. Initializes QNX Neutrino
940 gdbserver. */
941
942void
943initialize_low (void)
944{
945 sigset_t set;
946
947 TRACE ("%s\n", __func__);
948 set_target_ops (&nto_target_ops);
949 set_breakpoint_data (the_low_target.breakpoint,
950 the_low_target.breakpoint_len);
951
952 /* We use SIGUSR1 to gain control after we block waiting for a process.
953 We use sigwaitevent to wait. */
954 sigemptyset (&set);
955 sigaddset (&set, SIGUSR1);
956 sigprocmask (SIG_BLOCK, &set, NULL);
957}
958
This page took 0.242366 seconds and 4 git commands to generate.