1 /* QNX Neutrino specific low level interface, for the remote server
3 Copyright (C) 2009-2020 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"
30 #include <sys/procfs.h>
32 #include <sys/iomgr.h>
33 #include <sys/neutrino.h>
36 int using_threads
= 1;
38 const struct target_desc
*nto_tdesc
;
41 nto_trace (const char *fmt
, ...)
45 if (debug_threads
== 0)
47 fprintf (stderr
, "nto:");
48 va_start (arg_list
, fmt
);
49 vfprintf (stderr
, fmt
, arg_list
);
53 #define TRACE nto_trace
55 /* Structure holding neutrino specific information about
60 char nto_procfs_path
[PATH_MAX
];
63 int exit_signo
; /* For tracking exit status. */
66 static struct nto_inferior nto_inferior
;
69 init_nto_inferior (struct nto_inferior
*nto_inferior
)
71 memset (nto_inferior
, 0, sizeof (struct nto_inferior
));
72 nto_inferior
->ctl_fd
= -1;
73 nto_inferior
->pid
= -1;
79 if (nto_inferior
.ctl_fd
!= -1)
81 nto_trace ("Closing fd\n");
82 close (nto_inferior
.ctl_fd
);
83 init_nto_inferior (&nto_inferior
);
87 /* Set current thread. Return 1 on success, 0 otherwise. */
90 nto_set_thread (ptid_t ptid
)
94 TRACE ("%s pid: %d tid: %ld\n", __func__
, ptid
.pid (),
96 if (nto_inferior
.ctl_fd
!= -1
98 && ptid
!= minus_one_ptid
)
100 pthread_t tid
= ptid
.lwp ();
102 if (EOK
== devctl (nto_inferior
.ctl_fd
, DCMD_PROC_CURTHREAD
, &tid
,
106 TRACE ("%s: Error: failed to set current thread\n", __func__
);
111 /* This function will determine all alive threads. Note that we do not list
112 dead but unjoined threads even though they are still in the process' thread
115 NTO_INFERIOR must not be NULL. */
118 nto_find_new_threads (struct nto_inferior
*nto_inferior
)
122 TRACE ("%s pid:%d\n", __func__
, nto_inferior
->pid
);
124 if (nto_inferior
->ctl_fd
== -1)
127 for (tid
= 1;; ++tid
)
129 procfs_status status
;
134 err
= devctl (nto_inferior
->ctl_fd
, DCMD_PROC_TIDSTATUS
, &status
,
137 if (err
!= EOK
|| status
.tid
== 0)
140 /* All threads in between are gone. */
141 while (tid
!= status
.tid
|| status
.state
== STATE_DEAD
)
143 struct thread_info
*ti
;
145 ptid
= ptid_t (nto_inferior
->pid
, tid
, 0);
146 ti
= find_thread_ptid (ptid
);
149 TRACE ("Removing thread %d\n", tid
);
152 if (tid
== status
.tid
)
157 if (status
.state
!= STATE_DEAD
)
159 TRACE ("Adding thread %d\n", tid
);
160 ptid
= ptid_t (nto_inferior
->pid
, tid
, 0);
161 if (!find_thread_ptid (ptid
))
162 add_thread (ptid
, NULL
);
167 /* Given pid, open procfs path. */
170 do_attach (pid_t pid
)
172 procfs_status status
;
173 struct sigevent event
;
175 if (nto_inferior
.ctl_fd
!= -1)
177 close (nto_inferior
.ctl_fd
);
178 init_nto_inferior (&nto_inferior
);
180 xsnprintf (nto_inferior
.nto_procfs_path
, PATH_MAX
- 1, "/proc/%d/as", pid
);
181 nto_inferior
.ctl_fd
= open (nto_inferior
.nto_procfs_path
, O_RDWR
);
182 if (nto_inferior
.ctl_fd
== -1)
184 TRACE ("Failed to open %s\n", nto_inferior
.nto_procfs_path
);
185 init_nto_inferior (&nto_inferior
);
188 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STOP
, &status
, sizeof (status
), 0)
194 nto_inferior
.pid
= pid
;
195 /* Define a sigevent for process stopped notification. */
196 event
.sigev_notify
= SIGEV_SIGNAL_THREAD
;
197 event
.sigev_signo
= SIGUSR1
;
198 event
.sigev_code
= 0;
199 event
.sigev_value
.sival_ptr
= NULL
;
200 event
.sigev_priority
= -1;
201 devctl (nto_inferior
.ctl_fd
, DCMD_PROC_EVENT
, &event
, sizeof (event
), 0);
203 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
),
205 && (status
.flags
& _DEBUG_FLAG_STOPPED
))
208 struct process_info
*proc
;
211 ptid
= ptid_t (status
.pid
, status
.tid
, 0);
212 the_low_target
.arch_setup ();
213 proc
= add_process (status
.pid
, 1);
214 proc
->tdesc
= nto_tdesc
;
215 TRACE ("Adding thread: pid=%d tid=%ld\n", status
.pid
,
217 nto_find_new_threads (&nto_inferior
);
228 /* Read or write LEN bytes from/to inferior's MEMADDR memory address
229 into gdbservers's MYADDR buffer. Return number of bytes actually
233 nto_xfer_memory (off_t memaddr
, unsigned char *myaddr
, int len
,
238 if (lseek (nto_inferior
.ctl_fd
, memaddr
, SEEK_SET
) == memaddr
)
241 nbytes
= write (nto_inferior
.ctl_fd
, myaddr
, len
);
243 nbytes
= read (nto_inferior
.ctl_fd
, myaddr
, len
);
250 TRACE ("Error in %s : errno=%d (%s)\n", __func__
, e
, safe_strerror (e
));
255 /* Insert or remove breakpoint or watchpoint at address ADDR.
256 TYPE can be one of Neutrino breakpoint types. SIZE must be 0 for
257 inserting the point, -1 for removing it.
259 Return 0 on success, 1 otherwise. */
262 nto_breakpoint (CORE_ADDR addr
, int type
, int size
)
269 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_BREAK
, &brk
, sizeof (brk
), 0)
275 /* Read auxiliary vector from inferior's initial stack into gdbserver's
276 MYADDR buffer, up to LEN bytes.
278 Return number of bytes read. */
281 nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack
,
282 unsigned char *myaddr
,
287 unsigned int len_read
= 0;
289 /* Skip over argc, argv and envp... Comment from ldd.c:
291 The startup frame is set-up so that we have:
296 envp1 <----- void *frame + (argc + 2) * sizeof(char *)
301 argc <------ void * frame
303 On entry to ldd, frame gives the address of argc on the stack. */
304 if (nto_xfer_memory (initial_stack
, (unsigned char *)&anint
,
305 sizeof (anint
), 0) != sizeof (anint
))
308 /* Size of pointer is assumed to be 4 bytes (32 bit arch. ) */
309 data_ofs
+= (anint
+ 2) * sizeof (void *); /* + 2 comes from argc itself and
310 NULL terminating pointer in
313 /* Now loop over env table: */
314 while (nto_xfer_memory (initial_stack
+ data_ofs
,
315 (unsigned char *)&anint
, sizeof (anint
), 0)
318 data_ofs
+= sizeof (anint
);
322 initial_stack
+= data_ofs
;
324 memset (myaddr
, 0, len
);
325 while (len_read
<= len
- sizeof (auxv_t
))
327 auxv_t
*auxv
= (auxv_t
*)myaddr
;
329 /* Search backwards until we have read AT_PHDR (num. 3),
330 AT_PHENT (num 4), AT_PHNUM (num 5) */
331 if (nto_xfer_memory (initial_stack
, (unsigned char *)auxv
,
332 sizeof (auxv_t
), 0) == sizeof (auxv_t
))
334 if (auxv
->a_type
!= AT_NULL
)
337 len_read
+= sizeof (auxv_t
);
339 if (auxv
->a_type
== AT_PHNUM
) /* That's all we need. */
341 initial_stack
+= sizeof (auxv_t
);
346 TRACE ("auxv: len_read: %d\n", len_read
);
350 /* Start inferior specified by PROGRAM, using PROGRAM_ARGS as its
354 nto_process_target::create_inferior (const char *program
,
355 const std::vector
<char *> &program_args
)
357 struct inheritance inherit
;
360 std::string str_program_args
= stringify_argv (program_args
);
362 TRACE ("%s %s\n", __func__
, program
);
363 /* Clear any pending SIGUSR1's but keep the behavior the same. */
364 signal (SIGUSR1
, signal (SIGUSR1
, SIG_IGN
));
367 sigaddset (&set
, SIGUSR1
);
368 sigprocmask (SIG_UNBLOCK
, &set
, NULL
);
370 memset (&inherit
, 0, sizeof (inherit
));
371 inherit
.flags
|= SPAWN_SETGROUP
| SPAWN_HOLD
;
372 inherit
.pgroup
= SPAWN_NEWPGROUP
;
373 pid
= spawnp (program
, 0, NULL
, &inherit
,
374 (char *) str_program_args
.c_str (), 0);
375 sigprocmask (SIG_BLOCK
, &set
, NULL
);
380 if (do_attach (pid
) != pid
)
386 /* Attach to process PID. */
389 nto_process_target::attach (unsigned long pid
)
391 TRACE ("%s %ld\n", __func__
, pid
);
392 if (do_attach (pid
) != pid
)
393 error ("Unable to attach to %ld\n", pid
);
397 /* Send signal to process PID. */
400 nto_process_target::kill (process_info
*proc
)
404 TRACE ("%s %d\n", __func__
, pid
);
410 /* Detach from process PID. */
413 nto_process_target::detach (process_info
*proc
)
415 TRACE ("%s %d\n", __func__
, proc
->pid
);
421 nto_process_target::mourn (struct process_info
*process
)
423 remove_process (process
);
427 nto_process_target::join (int pid
)
429 error (_("nto target does not implement the join op"));
432 /* Check if the given thread is alive.
434 Return true if alive, false otherwise. */
437 nto_process_target::thread_alive (ptid_t ptid
)
441 TRACE ("%s pid:%d tid:%d\n", __func__
, ptid
.pid (),
443 if (SignalKill (0, ptid
.pid (), ptid
.lwp (),
448 TRACE ("%s: %s\n", __func__
, res
? "yes" : "no");
452 /* Resume inferior's execution. */
455 nto_process_target::resume (thread_resume
*resume_info
, size_t n
)
457 /* We can only work in all-stop mode. */
458 procfs_status status
;
462 TRACE ("%s\n", __func__
);
463 /* Workaround for aliasing rules violation. */
464 sigset_t
*run_fault
= (sigset_t
*) (void *) &run
.fault
;
466 nto_set_thread (resume_info
->thread
);
468 run
.flags
= _DEBUG_RUN_FAULT
| _DEBUG_RUN_TRACE
;
469 if (resume_info
->kind
== resume_step
)
470 run
.flags
|= _DEBUG_RUN_STEP
;
471 run
.flags
|= _DEBUG_RUN_ARM
;
473 sigemptyset (run_fault
);
474 sigaddset (run_fault
, FLTBPT
);
475 sigaddset (run_fault
, FLTTRACE
);
476 sigaddset (run_fault
, FLTILL
);
477 sigaddset (run_fault
, FLTPRIV
);
478 sigaddset (run_fault
, FLTBOUNDS
);
479 sigaddset (run_fault
, FLTIOVF
);
480 sigaddset (run_fault
, FLTIZDIV
);
481 sigaddset (run_fault
, FLTFPE
);
482 sigaddset (run_fault
, FLTPAGE
);
483 sigaddset (run_fault
, FLTSTACK
);
484 sigaddset (run_fault
, FLTACCESS
);
486 sigemptyset (&run
.trace
);
487 if (resume_info
->sig
)
491 devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
),
493 signal_to_pass
= resume_info
->sig
;
494 if (status
.why
& (_DEBUG_WHY_SIGNALLED
| _DEBUG_WHY_FAULTED
))
496 if (signal_to_pass
!= status
.info
.si_signo
)
498 kill (status
.pid
, signal_to_pass
);
499 run
.flags
|= _DEBUG_RUN_CLRFLT
| _DEBUG_RUN_CLRSIG
;
501 else /* Let it kill the program without telling us. */
502 sigdelset (&run
.trace
, signal_to_pass
);
506 run
.flags
|= _DEBUG_RUN_CLRSIG
| _DEBUG_RUN_CLRFLT
;
508 sigfillset (&run
.trace
);
510 regcache_invalidate ();
512 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_RUN
, &run
, sizeof (run
), 0);
514 TRACE ("Error: %d \"%s\"\n", err
, safe_strerror (err
));
517 /* Wait for inferior's event.
519 Return ptid of thread that caused the event. */
522 nto_process_target::wait (ptid_t ptid
, target_waitstatus
*ourstatus
,
527 procfs_status status
;
528 const int trace_mask
= (_DEBUG_FLAG_TRACE_EXEC
| _DEBUG_FLAG_TRACE_RD
529 | _DEBUG_FLAG_TRACE_WR
| _DEBUG_FLAG_TRACE_MODIFY
);
531 TRACE ("%s\n", __func__
);
533 ourstatus
->kind
= TARGET_WAITKIND_SPURIOUS
;
536 sigaddset (&set
, SIGUSR1
);
538 devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
), 0);
539 while (!(status
.flags
& _DEBUG_FLAG_ISTOP
))
541 sigwaitinfo (&set
, &info
);
542 devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
, sizeof (status
),
545 nto_find_new_threads (&nto_inferior
);
547 if (status
.flags
& _DEBUG_FLAG_SSTEP
)
550 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
551 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
553 /* Was it a breakpoint? */
554 else if (status
.flags
& trace_mask
)
557 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
558 ourstatus
->value
.sig
= GDB_SIGNAL_TRAP
;
560 else if (status
.flags
& _DEBUG_FLAG_ISTOP
)
565 case _DEBUG_WHY_SIGNALLED
:
566 TRACE (" SIGNALLED\n");
567 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
568 ourstatus
->value
.sig
=
569 gdb_signal_from_host (status
.info
.si_signo
);
570 nto_inferior
.exit_signo
= ourstatus
->value
.sig
;
572 case _DEBUG_WHY_FAULTED
:
573 TRACE (" FAULTED\n");
574 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
575 if (status
.info
.si_signo
== SIGTRAP
)
577 ourstatus
->value
.sig
= 0;
578 nto_inferior
.exit_signo
= 0;
582 ourstatus
->value
.sig
=
583 gdb_signal_from_host (status
.info
.si_signo
);
584 nto_inferior
.exit_signo
= ourstatus
->value
.sig
;
588 case _DEBUG_WHY_TERMINATED
:
592 TRACE (" TERMINATED\n");
593 waitpid (ptid
.pid (), &waitval
, WNOHANG
);
594 if (nto_inferior
.exit_signo
)
596 /* Abnormal death. */
597 ourstatus
->kind
= TARGET_WAITKIND_SIGNALLED
;
598 ourstatus
->value
.sig
= nto_inferior
.exit_signo
;
603 ourstatus
->kind
= TARGET_WAITKIND_EXITED
;
604 ourstatus
->value
.integer
= WEXITSTATUS (waitval
);
606 nto_inferior
.exit_signo
= 0;
610 case _DEBUG_WHY_REQUESTED
:
611 TRACE ("REQUESTED\n");
612 /* We are assuming a requested stop is due to a SIGINT. */
613 ourstatus
->kind
= TARGET_WAITKIND_STOPPED
;
614 ourstatus
->value
.sig
= GDB_SIGNAL_INT
;
615 nto_inferior
.exit_signo
= 0;
620 return ptid_t (status
.pid
, status
.tid
, 0);
623 /* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
624 If REGNO is -1, fetch all registers, or REGNO register only otherwise. */
627 nto_process_target::fetch_registers (regcache
*regcache
, int regno
)
632 TRACE ("%s (regno=%d)\n", __func__
, regno
);
633 if (regno
>= the_low_target
.num_regs
)
636 if (current_thread
== NULL
)
638 TRACE ("current_thread is NULL\n");
641 ptid_t ptid
= ptid_of (current_thread
);
642 if (!nto_set_thread (ptid
))
645 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_GETGREG
, &greg
, sizeof (greg
),
648 if (regno
== -1) /* All registers. */
650 for (regno
= 0; regno
!= the_low_target
.num_regs
; ++regno
)
652 const unsigned int registeroffset
653 = the_low_target
.register_offset (regno
);
654 supply_register (regcache
, regno
,
655 ((char *)&greg
) + registeroffset
);
660 const unsigned int registeroffset
661 = the_low_target
.register_offset (regno
);
662 if (registeroffset
== -1)
664 supply_register (regcache
, regno
, ((char *)&greg
) + registeroffset
);
668 TRACE ("ERROR reading registers from inferior.\n");
671 /* Store registers for currently selected thread (CURRENT_INFERIOR).
672 We always store all registers, regardless of REGNO. */
675 nto_process_target::store_registers (regcache
*regcache
, int regno
)
680 TRACE ("%s (regno:%d)\n", __func__
, regno
);
682 if (current_thread
== NULL
)
684 TRACE ("current_thread is NULL\n");
687 ptid_t ptid
= ptid_of (current_thread
);
688 if (!nto_set_thread (ptid
))
691 memset (&greg
, 0, sizeof (greg
));
692 for (regno
= 0; regno
!= the_low_target
.num_regs
; ++regno
)
694 const unsigned int regoffset
695 = the_low_target
.register_offset (regno
);
696 collect_register (regcache
, regno
, ((char *)&greg
) + regoffset
);
698 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_SETGREG
, &greg
, sizeof (greg
),
701 TRACE ("Error: setting registers.\n");
704 /* Read LEN bytes from inferior's memory address MEMADDR into
705 gdbserver's MYADDR buffer.
707 Return 0 on success -1 otherwise. */
710 nto_read_memory (CORE_ADDR memaddr
, unsigned char *myaddr
, int len
)
712 TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__
, memaddr
, len
);
714 if (nto_xfer_memory (memaddr
, myaddr
, len
, 0) != len
)
716 TRACE ("Failed to read memory\n");
723 /* Write LEN bytes from gdbserver's buffer MYADDR into inferior's
724 memory at address MEMADDR.
726 Return 0 on success -1 otherwise. */
729 nto_write_memory (CORE_ADDR memaddr
, const unsigned char *myaddr
, int len
)
733 TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__
, memaddr
, len
);
734 if ((len_written
= nto_xfer_memory (memaddr
, (unsigned char *)myaddr
, len
,
738 TRACE ("Wanted to write: %d but written: %d\n", len
, len_written
);
745 /* Stop inferior. We always stop all threads. */
748 nto_request_interrupt (void)
750 TRACE ("%s\n", __func__
);
751 nto_set_thread (ptid_t (nto_inferior
.pid
, 1, 0));
752 if (EOK
!= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STOP
, NULL
, 0, 0))
753 TRACE ("Error stopping inferior.\n");
756 /* Read auxiliary vector from inferior's memory into gdbserver's buffer
757 MYADDR. We always read whole auxv.
759 Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0
763 nto_read_auxv (CORE_ADDR offset
, unsigned char *myaddr
, unsigned int len
)
766 CORE_ADDR initial_stack
;
767 procfs_info procinfo
;
769 TRACE ("%s\n", __func__
);
773 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_INFO
, &procinfo
,
778 initial_stack
= procinfo
.initial_stack
;
780 return nto_read_auxv_from_initial_stack (initial_stack
, myaddr
, len
);
784 nto_supports_z_point_type (char z_type
)
790 case Z_PACKET_WRITE_WP
:
791 case Z_PACKET_READ_WP
:
792 case Z_PACKET_ACCESS_WP
:
799 /* Insert {break/watch}point at address ADDR. SIZE is not used. */
802 nto_insert_point (enum raw_bkpt_type type
, CORE_ADDR addr
,
803 int size
, struct raw_breakpoint
*bp
)
805 int wtype
= _DEBUG_BREAK_HW
; /* Always request HW. */
807 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__
, (int)type
, addr
, size
);
810 case raw_bkpt_type_sw
:
811 wtype
= _DEBUG_BREAK_EXEC
;
813 case raw_bkpt_type_hw
:
814 wtype
|= _DEBUG_BREAK_EXEC
;
816 case raw_bkpt_type_write_wp
:
817 wtype
|= _DEBUG_BREAK_RW
;
819 case raw_bkpt_type_read_wp
:
820 wtype
|= _DEBUG_BREAK_RD
;
822 case raw_bkpt_type_access_wp
:
823 wtype
|= _DEBUG_BREAK_RW
;
826 return 1; /* Not supported. */
828 return nto_breakpoint (addr
, wtype
, 0);
831 /* Remove {break/watch}point at address ADDR. SIZE is not used. */
834 nto_remove_point (enum raw_bkpt_type type
, CORE_ADDR addr
,
835 int size
, struct raw_breakpoint
*bp
)
837 int wtype
= _DEBUG_BREAK_HW
; /* Always request HW. */
839 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__
, (int)type
, addr
, size
);
842 case raw_bkpt_type_sw
:
843 wtype
= _DEBUG_BREAK_EXEC
;
845 case raw_bkpt_type_hw
:
846 wtype
|= _DEBUG_BREAK_EXEC
;
848 case raw_bkpt_type_write_wp
:
849 wtype
|= _DEBUG_BREAK_RW
;
851 case raw_bkpt_type_read_wp
:
852 wtype
|= _DEBUG_BREAK_RD
;
854 case raw_bkpt_type_access_wp
:
855 wtype
|= _DEBUG_BREAK_RW
;
858 return 1; /* Not supported. */
860 return nto_breakpoint (addr
, wtype
, -1);
863 /* Check if the reason of stop for current thread (CURRENT_INFERIOR) is
866 Return 1 if stopped by watchpoint, 0 otherwise. */
869 nto_stopped_by_watchpoint (void)
873 TRACE ("%s\n", __func__
);
874 if (nto_inferior
.ctl_fd
!= -1 && current_thread
!= NULL
)
876 ptid_t ptid
= ptid_of (current_thread
);
877 if (nto_set_thread (ptid
))
879 const int watchmask
= _DEBUG_FLAG_TRACE_RD
| _DEBUG_FLAG_TRACE_WR
880 | _DEBUG_FLAG_TRACE_MODIFY
;
881 procfs_status status
;
884 err
= devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
,
886 if (err
== EOK
&& (status
.flags
& watchmask
))
890 TRACE ("%s: %s\n", __func__
, ret
? "yes" : "no");
894 /* Get instruction pointer for CURRENT_INFERIOR thread.
896 Return inferior's instruction pointer value, or 0 on error. */
899 nto_stopped_data_address (void)
901 CORE_ADDR ret
= (CORE_ADDR
)0;
903 TRACE ("%s\n", __func__
);
904 if (nto_inferior
.ctl_fd
!= -1 && current_thread
!= NULL
)
906 ptid_t ptid
= ptid_of (current_thread
);
908 if (nto_set_thread (ptid
))
910 procfs_status status
;
912 if (devctl (nto_inferior
.ctl_fd
, DCMD_PROC_STATUS
, &status
,
913 sizeof (status
), 0) == EOK
)
917 TRACE ("%s: 0x%08lx\n", __func__
, ret
);
921 /* We do not currently support non-stop. */
924 nto_supports_non_stop (void)
926 TRACE ("%s\n", __func__
);
930 /* Implementation of the target_ops method "sw_breakpoint_from_kind". */
932 static const gdb_byte
*
933 nto_sw_breakpoint_from_kind (int kind
, int *size
)
935 *size
= the_low_target
.breakpoint_len
;
936 return the_low_target
.breakpoint
;
939 /* The QNX Neutrino target ops object. */
941 static nto_process_target the_nto_target
;
943 static process_stratum_target nto_target_ops
= {
946 NULL
, /* nto_look_up_symbols */
947 nto_request_interrupt
,
949 nto_supports_z_point_type
,
952 NULL
, /* stopped_by_sw_breakpoint */
953 NULL
, /* supports_stopped_by_sw_breakpoint */
954 NULL
, /* stopped_by_hw_breakpoint */
955 NULL
, /* supports_stopped_by_hw_breakpoint */
956 target_can_do_hardware_single_step
,
957 nto_stopped_by_watchpoint
,
958 nto_stopped_data_address
,
959 NULL
, /* nto_read_offsets */
960 NULL
, /* thread_db_set_tls_address */
961 hostio_last_error_from_errno
,
962 NULL
, /* nto_qxfer_osdata */
963 NULL
, /* xfer_siginfo */
964 nto_supports_non_stop
,
966 NULL
, /* start_non_stop */
967 NULL
, /* supports_multi_process */
968 NULL
, /* supports_fork_events */
969 NULL
, /* supports_vfork_events */
970 NULL
, /* supports_exec_events */
971 NULL
, /* handle_new_gdb_connection */
972 NULL
, /* handle_monitor_command */
973 NULL
, /* core_of_thread */
974 NULL
, /* read_loadmap */
975 NULL
, /* process_qsupported */
976 NULL
, /* supports_tracepoints */
979 NULL
, /* thread_stopped */
980 NULL
, /* get_tib_address */
981 NULL
, /* pause_all */
982 NULL
, /* unpause_all */
983 NULL
, /* stabilize_threads */
984 NULL
, /* install_fast_tracepoint_jump_pad */
986 NULL
, /* supports_disable_randomization */
987 NULL
, /* get_min_fast_tracepoint_insn_len */
988 NULL
, /* qxfer_libraries_svr4 */
989 NULL
, /* support_agent */
990 NULL
, /* enable_btrace */
991 NULL
, /* disable_btrace */
992 NULL
, /* read_btrace */
993 NULL
, /* read_btrace_conf */
994 NULL
, /* supports_range_stepping */
995 NULL
, /* pid_to_exec_file */
996 NULL
, /* multifs_open */
997 NULL
, /* multifs_unlink */
998 NULL
, /* multifs_readlink */
999 NULL
, /* breakpoint_kind_from_pc */
1000 nto_sw_breakpoint_from_kind
,
1001 NULL
, /* thread_name */
1002 NULL
, /* breakpoint_kind_from_current_state */
1003 NULL
, /* supports_software_single_step */
1004 NULL
, /* supports_catch_syscall */
1005 NULL
, /* get_ipa_tdesc_idx */
1006 NULL
, /* thread_handle */
1011 /* Global function called by server.c. Initializes QNX Neutrino
1015 initialize_low (void)
1019 TRACE ("%s\n", __func__
);
1020 set_target_ops (&nto_target_ops
);
1022 /* We use SIGUSR1 to gain control after we block waiting for a process.
1023 We use sigwaitevent to wait. */
1025 sigaddset (&set
, SIGUSR1
);
1026 sigprocmask (SIG_BLOCK
, &set
, NULL
);