1 /* QNX Neutrino specific low level interface, for the remote server
3 Copyright (C) 2009-2013 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
22 #include "gdbthread.h"
28 #include <sys/procfs.h>
31 #include <sys/iomgr.h>
32 #include <sys/neutrino.h>
35 extern int using_threads
;
36 int using_threads
= 1;
39 nto_trace (const char *fmt
, ...)
43 if (debug_threads
== 0)
45 fprintf (stderr
, "nto:");
46 va_start (arg_list
, fmt
);
47 vfprintf (stderr
, fmt
, arg_list
);
51 #define TRACE nto_trace
53 /* Structure holding neutrino specific information about
58 char nto_procfs_path
[PATH_MAX
];
61 int exit_signo
; /* For tracking exit status. */
64 static struct nto_inferior nto_inferior
;
67 init_nto_inferior (struct nto_inferior
*nto_inferior
)
69 memset (nto_inferior
, 0, sizeof (struct nto_inferior
));
70 nto_inferior
->ctl_fd
= -1;
71 nto_inferior
->pid
= -1;
77 if (nto_inferior
.ctl_fd
!= -1)
79 nto_trace ("Closing fd\n");
80 close (nto_inferior
.ctl_fd
);
81 init_nto_inferior (&nto_inferior
);
85 /* Set current thread. Return 1 on success, 0 otherwise. */
88 nto_set_thread (ptid_t ptid
)
92 TRACE ("%s pid: %d tid: %ld\n", __func__
, ptid_get_pid (ptid
),
94 if (nto_inferior
.ctl_fd
!= -1
95 && !ptid_equal (ptid
, null_ptid
)
96 && !ptid_equal (ptid
, minus_one_ptid
))
98 pthread_t tid
= ptid_get_lwp (ptid
);
100 if (EOK
== devctl (nto_inferior
.ctl_fd
, DCMD_PROC_CURTHREAD
, &tid
,
104 TRACE ("%s: Error: failed to set current thread\n", __func__
);
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
113 NTO_INFERIOR must not be NULL. */
116 nto_find_new_threads (struct nto_inferior
*nto_inferior
)
120 TRACE ("%s pid:%d\n", __func__
, nto_inferior
->pid
);
122 if (nto_inferior
->ctl_fd
== -1)
125 for (tid
= 1;; ++tid
)
127 procfs_status status
;
132 err
= devctl (nto_inferior
->ctl_fd
, DCMD_PROC_TIDSTATUS
, &status
,
135 if (err
!= EOK
|| status
.tid
== 0)
138 /* All threads in between are gone. */
139 while (tid
!= status
.tid
|| status
.state
== STATE_DEAD
)
141 struct thread_info
*ti
;
143 ptid
= ptid_build (nto_inferior
->pid
, tid
, 0);
144 ti
= find_thread_ptid (ptid
);
147 TRACE ("Removing thread %d\n", tid
);
150 if (tid
== status
.tid
)
155 if (status
.state
!= STATE_DEAD
)
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
);
165 /* Given pid, open procfs path. */
168 do_attach (pid_t pid
)
170 procfs_status status
;
171 struct sigevent event
;
173 if (nto_inferior
.ctl_fd
!= -1)
175 close (nto_inferior
.ctl_fd
);
176 init_nto_inferior (&nto_inferior
);
178 xsnprintf (nto_inferior
.nto_procfs_path
, PATH_MAX
- 1, "/proc/%d/as", pid
);
179 nto_inferior
.ctl_fd
= open (nto_inferior
.nto_procfs_path
, O_RDWR
);
180 if (nto_inferior
.ctl_fd
== -1)
182 TRACE ("Failed to open %s\n", nto_inferior
.nto_procfs_path
);
183 init_nto_inferior (&nto_inferior
);
186 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STOP
, &status
, sizeof (status
), 0)
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);
201 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
),
203 && (status
.flags
& _DEBUG_FLAG_STOPPED
))
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
);
224 /* Read or write LEN bytes from/to inferior's MEMADDR memory address
225 into gdbservers's MYADDR buffer. Return number of bytes actually
229 nto_xfer_memory (off_t memaddr
, unsigned char *myaddr
, int len
,
234 if (lseek (nto_inferior
.ctl_fd
, memaddr
, SEEK_SET
) == memaddr
)
237 nbytes
= write (nto_inferior
.ctl_fd
, myaddr
, len
);
239 nbytes
= read (nto_inferior
.ctl_fd
, myaddr
, len
);
246 TRACE ("Error in %s : errno=%d (%s)\n", __func__
, e
, strerror (e
));
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.
255 Return 0 on success, 1 otherwise. */
258 nto_breakpoint (CORE_ADDR addr
, int type
, int size
)
265 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_BREAK
, &brk
, sizeof (brk
), 0)
271 /* Read auxiliary vector from inferior's initial stack into gdbserver's
272 MYADDR buffer, up to LEN bytes.
274 Return number of bytes read. */
277 nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack
,
278 unsigned char *myaddr
,
283 unsigned int len_read
= 0;
285 /* Skip over argc, argv and envp... Comment from ldd.c:
287 The startup frame is set-up so that we have:
292 envp1 <----- void *frame + (argc + 2) * sizeof(char *)
297 argc <------ void * frame
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
))
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
309 /* Now loop over env table: */
310 while (nto_xfer_memory (initial_stack
+ data_ofs
,
311 (unsigned char *)&anint
, sizeof (anint
), 0)
314 data_ofs
+= sizeof (anint
);
318 initial_stack
+= data_ofs
;
320 memset (myaddr
, 0, len
);
321 while (len_read
<= len
- sizeof (auxv_t
))
323 auxv_t
*auxv
= (auxv_t
*)myaddr
;
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
))
330 if (auxv
->a_type
!= AT_NULL
)
333 len_read
+= sizeof (auxv_t
);
335 if (auxv
->a_type
== AT_PHNUM
) /* That's all we need. */
337 initial_stack
+= sizeof (auxv_t
);
342 TRACE ("auxv: len_read: %d\n", len_read
);
346 /* Start inferior specified by PROGRAM passing arguments ALLARGS. */
349 nto_create_inferior (char *program
, char **allargs
)
351 struct inheritance inherit
;
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
));
360 sigaddset (&set
, SIGUSR1
);
361 sigprocmask (SIG_UNBLOCK
, &set
, NULL
);
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
);
372 if (do_attach (pid
) != pid
)
378 /* Attach to process PID. */
381 nto_attach (unsigned long pid
)
383 TRACE ("%s %ld\n", __func__
, pid
);
384 if (do_attach (pid
) != pid
)
385 error ("Unable to attach to %ld\n", pid
);
389 /* Send signal to process PID. */
394 TRACE ("%s %d\n", __func__
, pid
);
400 /* Detach from process PID. */
405 TRACE ("%s %d\n", __func__
, pid
);
411 nto_mourn (struct process_info
*process
)
413 remove_process (process
);
416 /* Check if the given thread is alive.
418 Return 1 if alive, 0 otherwise. */
421 nto_thread_alive (ptid_t ptid
)
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
),
432 TRACE ("%s: %s\n", __func__
, res
? "yes" : "no");
436 /* Resume inferior's execution. */
439 nto_resume (struct thread_resume
*resume_info
, size_t n
)
441 /* We can only work in all-stop mode. */
442 procfs_status status
;
446 TRACE ("%s\n", __func__
);
447 /* Workaround for aliasing rules violation. */
448 sigset_t
*run_fault
= (sigset_t
*) (void *) &run
.fault
;
450 nto_set_thread (resume_info
->thread
);
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
;
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
);
470 sigemptyset (&run
.trace
);
471 if (resume_info
->sig
)
475 devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
),
477 signal_to_pass
= resume_info
->sig
;
478 if (status
.why
& (_DEBUG_WHY_SIGNALLED
| _DEBUG_WHY_FAULTED
))
480 if (signal_to_pass
!= status
.info
.si_signo
)
482 kill (status
.pid
, signal_to_pass
);
483 run
.flags
|= _DEBUG_RUN_CLRFLT
| _DEBUG_RUN_CLRSIG
;
485 else /* Let it kill the program without telling us. */
486 sigdelset (&run
.trace
, signal_to_pass
);
490 run
.flags
|= _DEBUG_RUN_CLRSIG
| _DEBUG_RUN_CLRFLT
;
492 sigfillset (&run
.trace
);
494 regcache_invalidate ();
496 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_RUN
, &run
, sizeof (run
), 0);
498 TRACE ("Error: %d \"%s\"\n", err
, strerror (err
));
501 /* Wait for inferior's event.
503 Return ptid of thread that caused the event. */
506 nto_wait (ptid_t ptid
,
507 struct target_waitstatus
*ourstatus
, int target_options
)
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
);
515 TRACE ("%s\n", __func__
);
517 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
520 sigaddset (&set
, SIGUSR1
);
522 devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
), 0);
523 while (!(status
.flags
& _DEBUG_FLAG_ISTOP
))
525 sigwaitinfo (&set
, &info
);
526 devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
),
529 nto_find_new_threads (&nto_inferior
);
531 if (status
.flags
& _DEBUG_FLAG_SSTEP
)
534 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
535 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
537 /* Was it a breakpoint? */
538 else if (status
.flags
& trace_mask
)
541 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
542 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
544 else if (status
.flags
& _DEBUG_FLAG_ISTOP
)
549 case _DEBUG_WHY_SIGNALLED
:
550 TRACE (" SIGNALLED\n");
551 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
552 ourstatus
->value
.sig
=
553 gdb_signal_from_host (status
.info
.si_signo
);
554 nto_inferior
.exit_signo
= ourstatus
->value
.sig
;
556 case _DEBUG_WHY_FAULTED
:
557 TRACE (" FAULTED\n");
558 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
559 if (status
.info
.si_signo
== SIGTRAP
)
561 ourstatus
->value
.sig
= 0;
562 nto_inferior
.exit_signo
= 0;
566 ourstatus
->value
.sig
=
567 gdb_signal_from_host (status
.info
.si_signo
);
568 nto_inferior
.exit_signo
= ourstatus
->value
.sig
;
572 case _DEBUG_WHY_TERMINATED
:
576 TRACE (" TERMINATED\n");
577 waitpid (ptid_get_pid (ptid
), &waitval
, WNOHANG
);
578 if (nto_inferior
.exit_signo
)
580 /* Abnormal death. */
581 ourstatus
->kind
= TARGET_WAITKIND_SIGNALLED
;
582 ourstatus
->value
.sig
= nto_inferior
.exit_signo
;
587 ourstatus
->kind
= TARGET_WAITKIND_EXITED
;
588 ourstatus
->value
.integer
= WEXITSTATUS (waitval
);
590 nto_inferior
.exit_signo
= 0;
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
;
598 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
599 nto_inferior
.exit_signo
= 0;
604 return ptid_build (status
.pid
, status
.tid
, 0);
607 /* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
608 If REGNO is -1, fetch all registers, or REGNO register only otherwise. */
611 nto_fetch_registers (struct regcache
*regcache
, int regno
)
617 TRACE ("%s (regno=%d)\n", __func__
, regno
);
618 if (regno
>= the_low_target
.num_regs
)
621 if (current_inferior
== NULL
)
623 TRACE ("current_inferior is NULL\n");
626 ptid
= thread_to_gdb_id (current_inferior
);
627 if (!nto_set_thread (ptid
))
630 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_GETGREG
, &greg
, sizeof (greg
),
633 if (regno
== -1) /* All registers. */
635 for (regno
= 0; regno
!= the_low_target
.num_regs
; ++regno
)
637 const unsigned int registeroffset
638 = the_low_target
.register_offset (regno
);
639 supply_register (regcache
, regno
,
640 ((char *)&greg
) + registeroffset
);
645 const unsigned int registeroffset
646 = the_low_target
.register_offset (regno
);
647 if (registeroffset
== -1)
649 supply_register (regcache
, regno
, ((char *)&greg
) + registeroffset
);
653 TRACE ("ERROR reading registers from inferior.\n");
656 /* Store registers for currently selected thread (CURRENT_INFERIOR).
657 We always store all registers, regardless of REGNO. */
660 nto_store_registers (struct regcache
*regcache
, int regno
)
666 TRACE ("%s (regno:%d)\n", __func__
, regno
);
668 if (current_inferior
== NULL
)
670 TRACE ("current_inferior is NULL\n");
673 ptid
= thread_to_gdb_id (current_inferior
);
674 if (!nto_set_thread (ptid
))
677 memset (&greg
, 0, sizeof (greg
));
678 for (regno
= 0; regno
!= the_low_target
.num_regs
; ++regno
)
680 const unsigned int regoffset
681 = the_low_target
.register_offset (regno
);
682 collect_register (regcache
, regno
, ((char *)&greg
) + regoffset
);
684 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_SETGREG
, &greg
, sizeof (greg
),
687 TRACE ("Error: setting registers.\n");
690 /* Read LEN bytes from inferior's memory address MEMADDR into
691 gdbserver's MYADDR buffer.
693 Return 0 on success -1 otherwise. */
696 nto_read_memory (CORE_ADDR memaddr
, unsigned char *myaddr
, int len
)
698 TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__
, memaddr
, len
);
700 if (nto_xfer_memory (memaddr
, myaddr
, len
, 0) != len
)
702 TRACE ("Failed to read memory\n");
709 /* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
710 memory at address MEMADDR.
712 Return 0 on success -1 otherwise. */
715 nto_write_memory (CORE_ADDR memaddr
, const unsigned char *myaddr
, int len
)
719 TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__
, memaddr
, len
);
720 if ((len_written
= nto_xfer_memory (memaddr
, (unsigned char *)myaddr
, len
,
724 TRACE ("Wanted to write: %d but written: %d\n", len
, len_written
);
731 /* Stop inferior. We always stop all threads. */
734 nto_request_interrupt (void)
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");
742 /* Read auxiliary vector from inferior's memory into gdbserver's buffer
743 MYADDR. We always read whole auxv.
745 Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
749 nto_read_auxv (CORE_ADDR offset
, unsigned char *myaddr
, unsigned int len
)
752 CORE_ADDR initial_stack
;
753 procfs_info procinfo
;
755 TRACE ("%s\n", __func__
);
759 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_INFO
, &procinfo
,
764 initial_stack
= procinfo
.initial_stack
;
766 return nto_read_auxv_from_initial_stack (initial_stack
, myaddr
, len
);
769 /* Insert {break/watch}point at address ADDR.
770 TYPE must be in '0'..'4' range. LEN is not used. */
773 nto_insert_point (char type
, CORE_ADDR addr
, int len
)
775 int wtype
= _DEBUG_BREAK_HW
; /* Always request HW. */
777 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__
, (int)type
, addr
, len
);
780 case '0': /* software-breakpoint */
781 wtype
= _DEBUG_BREAK_EXEC
;
783 case '1': /* hardware-breakpoint */
784 wtype
|= _DEBUG_BREAK_EXEC
;
786 case '2': /* write watchpoint */
787 wtype
|= _DEBUG_BREAK_RW
;
789 case '3': /* read watchpoint */
790 wtype
|= _DEBUG_BREAK_RD
;
792 case '4': /* access watchpoint */
793 wtype
|= _DEBUG_BREAK_RW
;
796 return 1; /* Not supported. */
798 return nto_breakpoint (addr
, wtype
, 0);
801 /* Remove {break/watch}point at address ADDR.
802 TYPE must be in '0'..'4' range. LEN is not used. */
805 nto_remove_point (char type
, CORE_ADDR addr
, int len
)
807 int wtype
= _DEBUG_BREAK_HW
; /* Always request HW. */
809 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__
, (int)type
, addr
, len
);
812 case '0': /* software-breakpoint */
813 wtype
= _DEBUG_BREAK_EXEC
;
815 case '1': /* hardware-breakpoint */
816 wtype
|= _DEBUG_BREAK_EXEC
;
818 case '2': /* write watchpoint */
819 wtype
|= _DEBUG_BREAK_RW
;
821 case '3': /* read watchpoint */
822 wtype
|= _DEBUG_BREAK_RD
;
824 case '4': /* access watchpoint */
825 wtype
|= _DEBUG_BREAK_RW
;
828 return 1; /* Not supported. */
830 return nto_breakpoint (addr
, wtype
, -1);
833 /* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
836 Return 1 if stopped by watchpoint, 0 otherwise. */
839 nto_stopped_by_watchpoint (void)
843 TRACE ("%s\n", __func__
);
844 if (nto_inferior
.ctl_fd
!= -1 && current_inferior
!= NULL
)
848 ptid
= thread_to_gdb_id (current_inferior
);
849 if (nto_set_thread (ptid
))
851 const int watchmask
= _DEBUG_FLAG_TRACE_RD
| _DEBUG_FLAG_TRACE_WR
852 | _DEBUG_FLAG_TRACE_MODIFY
;
853 procfs_status status
;
856 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
,
858 if (err
== EOK
&& (status
.flags
& watchmask
))
862 TRACE ("%s: %s\n", __func__
, ret
? "yes" : "no");
866 /* Get instruction pointer for CURRENT_INFERIOR thread.
868 Return inferior's instruction pointer value, or 0 on error. */
871 nto_stopped_data_address (void)
873 CORE_ADDR ret
= (CORE_ADDR
)0;
875 TRACE ("%s\n", __func__
);
876 if (nto_inferior
.ctl_fd
!= -1 && current_inferior
!= NULL
)
880 ptid
= thread_to_gdb_id (current_inferior
);
882 if (nto_set_thread (ptid
))
884 procfs_status status
;
886 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
,
887 sizeof (status
), 0) == EOK
)
891 TRACE ("%s: 0x%08lx\n", __func__
, ret
);
895 /* We do not currently support non-stop. */
898 nto_supports_non_stop (void)
900 TRACE ("%s\n", __func__
);
906 static struct target_ops nto_target_ops
= {
918 NULL
, /* prepare_to_access_memory */
919 NULL
, /* done_accessing_memory */
922 NULL
, /* nto_look_up_symbols */
923 nto_request_interrupt
,
927 nto_stopped_by_watchpoint
,
928 nto_stopped_data_address
,
929 NULL
, /* nto_read_offsets */
930 NULL
, /* thread_db_set_tls_address */
932 hostio_last_error_from_errno
,
933 NULL
, /* nto_qxfer_osdata */
934 NULL
, /* xfer_siginfo */
935 nto_supports_non_stop
,
937 NULL
/* start_non_stop */
941 /* Global function called by server.c. Initializes QNX Neutrino
945 initialize_low (void)
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
);
954 /* We use SIGUSR1 to gain control after we block waiting for a process.
955 We use sigwaitevent to wait. */
957 sigaddset (&set
, SIGUSR1
);
958 sigprocmask (SIG_BLOCK
, &set
, NULL
);