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