/* QNX Neutrino specific low level interface, for the remote server
for GDB.
- Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "server.h"
+#include "gdbthread.h"
#include "nto-low.h"
+#include "hostio.h"
+#include "debug.h"
#include <limits.h>
#include <fcntl.h>
#include <spawn.h>
#include <sys/procfs.h>
#include <sys/auxv.h>
-#include <stdarg.h>
#include <sys/iomgr.h>
#include <sys/neutrino.h>
-extern int using_threads;
int using_threads = 1;
+const struct target_desc *nto_tdesc;
+
static void
nto_trace (const char *fmt, ...)
{
{
int res = 0;
- TRACE ("%s pid: %d tid: %ld\n", __func__, ptid_get_pid (ptid),
- ptid_get_lwp (ptid));
+ TRACE ("%s pid: %d tid: %ld\n", __func__, ptid.pid (),
+ ptid.lwp ());
if (nto_inferior.ctl_fd != -1
- && !ptid_equal (ptid, null_ptid)
- && !ptid_equal (ptid, minus_one_ptid))
+ && ptid != null_ptid
+ && ptid != minus_one_ptid)
{
- pthread_t tid = ptid_get_lwp (ptid);
+ pthread_t tid = ptid.lwp ();
if (EOK == devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid,
sizeof (tid), 0))
{
struct thread_info *ti;
- ptid = ptid_build (nto_inferior->pid, tid, 0);
+ ptid = ptid_t (nto_inferior->pid, tid, 0);
ti = find_thread_ptid (ptid);
if (ti != NULL)
{
if (status.state != STATE_DEAD)
{
TRACE ("Adding thread %d\n", tid);
- ptid = ptid_build (nto_inferior->pid, tid, 0);
+ ptid = ptid_t (nto_inferior->pid, tid, 0);
if (!find_thread_ptid (ptid))
add_thread (ptid, NULL);
}
close (nto_inferior.ctl_fd);
init_nto_inferior (&nto_inferior);
}
- snprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
+ xsnprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR);
if (nto_inferior.ctl_fd == -1)
{
&& (status.flags & _DEBUG_FLAG_STOPPED))
{
ptid_t ptid;
+ struct process_info *proc;
kill (pid, SIGCONT);
- ptid = ptid_build (status.pid, status.tid, 0);
+ ptid = ptid_t (status.pid, status.tid, 0);
the_low_target.arch_setup ();
- add_process (status.pid, 1);
+ proc = add_process (status.pid, 1);
+ proc->tdesc = nto_tdesc;
TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid,
- ptid_get_lwp (ptid));
+ ptid.lwp ());
nto_find_new_threads (&nto_inferior);
}
else
if (nbytes == 0)
{
int e = errno;
- TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, strerror (e));
+ TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, safe_strerror (e));
}
return nbytes;
}
return len_read;
}
-/* Start inferior specified by PROGRAM passing arguments ALLARGS. */
+/* Start inferior specified by PROGRAM, using PROGRAM_ARGS as its
+ arguments. */
static int
-nto_create_inferior (char *program, char **allargs)
+nto_create_inferior (const char *program,
+ const std::vector<char *> &program_args)
{
struct inheritance inherit;
pid_t pid;
sigset_t set;
+ std::string str_program_args = stringify_argv (program_args);
TRACE ("%s %s\n", __func__, program);
/* Clear any pending SIGUSR1's but keep the behavior the same. */
memset (&inherit, 0, sizeof (inherit));
inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
inherit.pgroup = SPAWN_NEWPGROUP;
- pid = spawnp (program, 0, NULL, &inherit, allargs, 0);
+ pid = spawnp (program, 0, NULL, &inherit,
+ (char *) str_program_args.c_str (), 0);
sigprocmask (SIG_BLOCK, &set, NULL);
if (pid == -1)
/* Send signal to process PID. */
static int
-nto_kill (int pid)
+nto_kill (process_info *proc)
{
+ int pid = proc->pid;
+
TRACE ("%s %d\n", __func__, pid);
kill (pid, SIGKILL);
do_detach ();
/* Detach from process PID. */
static int
-nto_detach (int pid)
+nto_detach (process_info *proc)
{
- TRACE ("%s %d\n", __func__, pid);
+ TRACE ("%s %d\n", __func__, proc->pid);
do_detach ();
return 0;
}
+static void
+nto_mourn (struct process_info *process)
+{
+ remove_process (process);
+}
+
/* Check if the given thread is alive.
Return 1 if alive, 0 otherwise. */
{
int res;
- TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid),
- ptid_get_lwp (ptid));
- if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid),
+ TRACE ("%s pid:%d tid:%d\n", __func__, ptid.pid (),
+ ptid.lwp ());
+ if (SignalKill (0, ptid.pid (), ptid.lwp (),
0, 0, 0) == -1)
res = 0;
else
err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0);
if (err != EOK)
- TRACE ("Error: %d \"%s\"\n", err, strerror (err));
+ TRACE ("Error: %d \"%s\"\n", err, safe_strerror (err));
}
/* Wait for inferior's event.
{
TRACE ("SSTEP\n");
ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+ ourstatus->value.sig = GDB_SIGNAL_TRAP;
}
/* Was it a breakpoint? */
else if (status.flags & trace_mask)
{
TRACE ("STOPPED\n");
ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+ ourstatus->value.sig = GDB_SIGNAL_TRAP;
}
else if (status.flags & _DEBUG_FLAG_ISTOP)
{
TRACE (" SIGNALLED\n");
ourstatus->kind = TARGET_WAITKIND_STOPPED;
ourstatus->value.sig =
- target_signal_from_host (status.info.si_signo);
+ gdb_signal_from_host (status.info.si_signo);
nto_inferior.exit_signo = ourstatus->value.sig;
break;
case _DEBUG_WHY_FAULTED:
else
{
ourstatus->value.sig =
- target_signal_from_host (status.info.si_signo);
+ gdb_signal_from_host (status.info.si_signo);
nto_inferior.exit_signo = ourstatus->value.sig;
}
break;
int waitval = 0;
TRACE (" TERMINATED\n");
- waitpid (ptid_get_pid (ptid), &waitval, WNOHANG);
+ waitpid (ptid.pid (), &waitval, WNOHANG);
if (nto_inferior.exit_signo)
{
/* Abnormal death. */
TRACE ("REQUESTED\n");
/* We are assuming a requested stop is due to a SIGINT. */
ourstatus->kind = TARGET_WAITKIND_STOPPED;
- ourstatus->value.sig = TARGET_SIGNAL_INT;
+ ourstatus->value.sig = GDB_SIGNAL_INT;
nto_inferior.exit_signo = 0;
break;
}
}
- return ptid_build (status.pid, status.tid, 0);
+ return ptid_t (status.pid, status.tid, 0);
}
/* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR).
{
int regsize;
procfs_greg greg;
- ptid_t ptid;
TRACE ("%s (regno=%d)\n", __func__, regno);
if (regno >= the_low_target.num_regs)
return;
- if (current_inferior == NULL)
+ if (current_thread == NULL)
{
- TRACE ("current_inferior is NULL\n");
+ TRACE ("current_thread is NULL\n");
return;
}
- ptid = thread_to_gdb_id (current_inferior);
+ ptid_t ptid = ptid_of (current_thread);
if (!nto_set_thread (ptid))
return;
{
const unsigned int registeroffset
= the_low_target.register_offset (regno);
- supply_register (regcache, regno, ((char *)&greg) + registeroffset);
+ supply_register (regcache, regno,
+ ((char *)&greg) + registeroffset);
}
}
else
{
procfs_greg greg;
int err;
- ptid_t ptid;
TRACE ("%s (regno:%d)\n", __func__, regno);
- if (current_inferior == NULL)
+ if (current_thread == NULL)
{
- TRACE ("current_inferior is NULL\n");
+ TRACE ("current_thread is NULL\n");
return;
}
- ptid = thread_to_gdb_id (current_inferior);
+ ptid_t ptid = ptid_of (current_thread);
if (!nto_set_thread (ptid))
return;
nto_request_interrupt (void)
{
TRACE ("%s\n", __func__);
- nto_set_thread (ptid_build (nto_inferior.pid, 1, 0));
+ nto_set_thread (ptid_t (nto_inferior.pid, 1, 0));
if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0))
TRACE ("Error stopping inferior.\n");
}
return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
}
-/* Insert {break/watch}point at address ADDR.
- TYPE must be in '0'..'4' range. LEN is not used. */
+static int
+nto_supports_z_point_type (char z_type)
+{
+ switch (z_type)
+ {
+ case Z_PACKET_SW_BP:
+ case Z_PACKET_HW_BP:
+ case Z_PACKET_WRITE_WP:
+ case Z_PACKET_READ_WP:
+ case Z_PACKET_ACCESS_WP:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Insert {break/watch}point at address ADDR. SIZE is not used. */
static int
-nto_insert_point (char type, CORE_ADDR addr, int len)
+nto_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+ int size, struct raw_breakpoint *bp)
{
int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
- TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
+ TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, size);
switch (type)
{
- case '0': /* software-breakpoint */
+ case raw_bkpt_type_sw:
wtype = _DEBUG_BREAK_EXEC;
break;
- case '1': /* hardware-breakpoint */
+ case raw_bkpt_type_hw:
wtype |= _DEBUG_BREAK_EXEC;
break;
- case '2': /* write watchpoint */
+ case raw_bkpt_type_write_wp:
wtype |= _DEBUG_BREAK_RW;
break;
- case '3': /* read watchpoint */
+ case raw_bkpt_type_read_wp:
wtype |= _DEBUG_BREAK_RD;
break;
- case '4': /* access watchpoint */
+ case raw_bkpt_type_access_wp:
wtype |= _DEBUG_BREAK_RW;
break;
default:
return nto_breakpoint (addr, wtype, 0);
}
-/* Remove {break/watch}point at address ADDR.
- TYPE must be in '0'..'4' range. LEN is not used. */
+/* Remove {break/watch}point at address ADDR. SIZE is not used. */
static int
-nto_remove_point (char type, CORE_ADDR addr, int len)
+nto_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+ int size, struct raw_breakpoint *bp)
{
int wtype = _DEBUG_BREAK_HW; /* Always request HW. */
- TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
+ TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, size);
switch (type)
{
- case '0': /* software-breakpoint */
+ case raw_bkpt_type_sw:
wtype = _DEBUG_BREAK_EXEC;
break;
- case '1': /* hardware-breakpoint */
+ case raw_bkpt_type_hw:
wtype |= _DEBUG_BREAK_EXEC;
break;
- case '2': /* write watchpoint */
+ case raw_bkpt_type_write_wp:
wtype |= _DEBUG_BREAK_RW;
break;
- case '3': /* read watchpoint */
+ case raw_bkpt_type_read_wp:
wtype |= _DEBUG_BREAK_RD;
break;
- case '4': /* access watchpoint */
+ case raw_bkpt_type_access_wp:
wtype |= _DEBUG_BREAK_RW;
break;
default:
int ret = 0;
TRACE ("%s\n", __func__);
- if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
+ if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
{
- ptid_t ptid;
-
- ptid = thread_to_gdb_id (current_inferior);
+ ptid_t ptid = ptid_of (current_thread);
if (nto_set_thread (ptid))
{
const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
CORE_ADDR ret = (CORE_ADDR)0;
TRACE ("%s\n", __func__);
- if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
+ if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
{
- ptid_t ptid;
-
- ptid = thread_to_gdb_id (current_inferior);
+ ptid_t ptid = ptid_of (current_thread);
if (nto_set_thread (ptid))
{
return 0;
}
+/* Implementation of the target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+nto_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = the_low_target.breakpoint_len;
+ return the_low_target.breakpoint;
+}
-static struct target_ops nto_target_ops = {
+static process_stratum_target nto_target_ops = {
nto_create_inferior,
+ NULL, /* post_create_inferior */
nto_attach,
nto_kill,
nto_detach,
- NULL, /* nto_mourn */
+ nto_mourn,
NULL, /* nto_join */
nto_thread_alive,
nto_resume,
nto_wait,
nto_fetch_registers,
nto_store_registers,
+ NULL, /* prepare_to_access_memory */
+ NULL, /* done_accessing_memory */
nto_read_memory,
nto_write_memory,
NULL, /* nto_look_up_symbols */
nto_request_interrupt,
nto_read_auxv,
+ nto_supports_z_point_type,
nto_insert_point,
nto_remove_point,
+ NULL, /* stopped_by_sw_breakpoint */
+ NULL, /* supports_stopped_by_sw_breakpoint */
+ NULL, /* stopped_by_hw_breakpoint */
+ NULL, /* supports_stopped_by_hw_breakpoint */
+ target_can_do_hardware_single_step,
nto_stopped_by_watchpoint,
nto_stopped_data_address,
NULL, /* nto_read_offsets */
NULL, /* thread_db_set_tls_address */
- NULL,
hostio_last_error_from_errno,
NULL, /* nto_qxfer_osdata */
NULL, /* xfer_siginfo */
nto_supports_non_stop,
NULL, /* async */
- NULL /* start_non_stop */
+ NULL, /* start_non_stop */
+ NULL, /* supports_multi_process */
+ NULL, /* supports_fork_events */
+ NULL, /* supports_vfork_events */
+ NULL, /* supports_exec_events */
+ NULL, /* handle_new_gdb_connection */
+ NULL, /* handle_monitor_command */
+ NULL, /* core_of_thread */
+ NULL, /* read_loadmap */
+ NULL, /* process_qsupported */
+ NULL, /* supports_tracepoints */
+ NULL, /* read_pc */
+ NULL, /* write_pc */
+ NULL, /* thread_stopped */
+ NULL, /* get_tib_address */
+ NULL, /* pause_all */
+ NULL, /* unpause_all */
+ NULL, /* stabilize_threads */
+ NULL, /* install_fast_tracepoint_jump_pad */
+ NULL, /* emit_ops */
+ NULL, /* supports_disable_randomization */
+ NULL, /* get_min_fast_tracepoint_insn_len */
+ NULL, /* qxfer_libraries_svr4 */
+ NULL, /* support_agent */
+ NULL, /* enable_btrace */
+ NULL, /* disable_btrace */
+ NULL, /* read_btrace */
+ NULL, /* read_btrace_conf */
+ NULL, /* supports_range_stepping */
+ NULL, /* pid_to_exec_file */
+ NULL, /* multifs_open */
+ NULL, /* multifs_unlink */
+ NULL, /* multifs_readlink */
+ NULL, /* breakpoint_kind_from_pc */
+ nto_sw_breakpoint_from_kind,
};
TRACE ("%s\n", __func__);
set_target_ops (&nto_target_ops);
- set_breakpoint_data (the_low_target.breakpoint,
- the_low_target.breakpoint_len);
/* We use SIGUSR1 to gain control after we block waiting for a process.
We use sigwaitevent to wait. */