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