#include <sys/uio.h>
#include "gdbsupport/filestuff.h"
#include "tracepoint.h"
-#include "hostio.h"
#include <inttypes.h>
#include "gdbsupport/common-inferior.h"
#include "nat/fork-inferior.h"
#endif
#endif
+#if (defined(__UCLIBC__) \
+ && defined(HAS_NOMMU) \
+ && defined(PT_TEXT_ADDR) \
+ && defined(PT_DATA_ADDR) \
+ && defined(PT_TEXT_END_ADDR))
+#define SUPPORTS_READ_OFFSETS
+#endif
+
#ifdef HAVE_LINUX_BTRACE
# include "nat/linux-btrace.h"
# include "gdbsupport/btrace-common.h"
int *wstat, int options);
static int linux_wait_for_event (ptid_t ptid, int *wstat, int options);
static struct lwp_info *add_lwp (ptid_t ptid);
-static int linux_stopped_by_watchpoint (void);
static void mark_lwp_dead (struct lwp_info *lwp, int wstat);
static int lwp_is_marked_dead (struct lwp_info *lwp);
static void proceed_all_lwps (void);
#endif
/* Stabilize threads (move out of jump pads). */
- stabilize_threads ();
+ target_stabilize_threads ();
/* Detach from the clone lwps first. If the thread group exits just
while we're detaching, we must reap the clone lwps before we're
since for something else in the new run, the thread would now
execute the wrong / random instructions. */
-static void
-linux_stabilize_threads (void)
+void
+linux_process_target::stabilize_threads ()
{
thread_info *thread_stuck = find_thread (stuck_in_jump_pad_callback);
/* Stabilize threads (move out of jump pads). */
if (!non_stop)
- stabilize_threads ();
+ target_stabilize_threads ();
}
else
{
#endif
-static void
-linux_fetch_registers (struct regcache *regcache, int regno)
+void
+linux_process_target::fetch_registers (regcache *regcache, int regno)
{
int use_regsets;
int all = 0;
}
}
-static void
-linux_store_registers (struct regcache *regcache, int regno)
+void
+linux_process_target::store_registers (regcache *regcache, int regno)
{
int use_regsets;
int all = 0;
}
-/* Copy LEN bytes from inferior's memory starting at MEMADDR
- to debugger memory starting at MYADDR. */
+/* A wrapper for the read_memory target op. */
static int
linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
+{
+ return the_target->pt->read_memory (memaddr, myaddr, len);
+}
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+int
+linux_process_target::read_memory (CORE_ADDR memaddr,
+ unsigned char *myaddr, int len)
{
int pid = lwpid_of (current_thread);
PTRACE_XFER_TYPE *buffer;
memory at MEMADDR. On failure (cannot write to the inferior)
returns the value of errno. Always succeeds if LEN is zero. */
-static int
-linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
+int
+linux_process_target::write_memory (CORE_ADDR memaddr,
+ const unsigned char *myaddr, int len)
{
int i;
/* Round starting address down to longword boundary. */
return 0;
}
-static void
-linux_look_up_symbols (void)
+void
+linux_process_target::look_up_symbols ()
{
#ifdef USE_THREAD_DB
struct process_info *proc = current_process ();
#endif
}
-static void
-linux_request_interrupt (void)
+void
+linux_process_target::request_interrupt ()
{
/* Send a SIGINT to the process group. This acts just like the user
typed a ^C on the controlling terminal. */
- kill (-signal_pid, SIGINT);
+ ::kill (-signal_pid, SIGINT);
+}
+
+bool
+linux_process_target::supports_read_auxv ()
+{
+ return true;
}
/* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET
to debugger memory starting at MYADDR. */
-static int
-linux_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
+int
+linux_process_target::read_auxv (CORE_ADDR offset, unsigned char *myaddr,
+ unsigned int len)
{
char filename[PATH_MAX];
int fd, n;
pass on the function call if the target has registered a
corresponding function. */
-static int
-linux_supports_z_point_type (char z_type)
+bool
+linux_process_target::supports_z_point_type (char z_type)
{
return (the_low_target.supports_z_point_type != NULL
&& the_low_target.supports_z_point_type (z_type));
}
-static int
-linux_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
- int size, struct raw_breakpoint *bp)
+int
+linux_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+ int size, raw_breakpoint *bp)
{
if (type == raw_bkpt_type_sw)
return insert_memory_breakpoint (bp);
return 1;
}
-static int
-linux_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
- int size, struct raw_breakpoint *bp)
+int
+linux_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+ int size, raw_breakpoint *bp)
{
if (type == raw_bkpt_type_sw)
return remove_memory_breakpoint (bp);
return 1;
}
-/* Implement the to_stopped_by_sw_breakpoint target_ops
+/* Implement the stopped_by_sw_breakpoint target_ops
method. */
-static int
-linux_stopped_by_sw_breakpoint (void)
+bool
+linux_process_target::stopped_by_sw_breakpoint ()
{
struct lwp_info *lwp = get_thread_lwp (current_thread);
return (lwp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT);
}
-/* Implement the to_supports_stopped_by_sw_breakpoint target_ops
+/* Implement the supports_stopped_by_sw_breakpoint target_ops
method. */
-static int
-linux_supports_stopped_by_sw_breakpoint (void)
+bool
+linux_process_target::supports_stopped_by_sw_breakpoint ()
{
return USE_SIGTRAP_SIGINFO;
}
-/* Implement the to_stopped_by_hw_breakpoint target_ops
+/* Implement the stopped_by_hw_breakpoint target_ops
method. */
-static int
-linux_stopped_by_hw_breakpoint (void)
+bool
+linux_process_target::stopped_by_hw_breakpoint ()
{
struct lwp_info *lwp = get_thread_lwp (current_thread);
return (lwp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT);
}
-/* Implement the to_supports_stopped_by_hw_breakpoint target_ops
+/* Implement the supports_stopped_by_hw_breakpoint target_ops
method. */
-static int
-linux_supports_stopped_by_hw_breakpoint (void)
+bool
+linux_process_target::supports_stopped_by_hw_breakpoint ()
{
return USE_SIGTRAP_SIGINFO;
}
/* Implement the supports_hardware_single_step target_ops method. */
-static int
-linux_supports_hardware_single_step (void)
+bool
+linux_process_target::supports_hardware_single_step ()
{
return can_hardware_single_step ();
}
return can_software_single_step ();
}
-static int
-linux_stopped_by_watchpoint (void)
+bool
+linux_process_target::stopped_by_watchpoint ()
{
struct lwp_info *lwp = get_thread_lwp (current_thread);
return lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
}
-static CORE_ADDR
-linux_stopped_data_address (void)
+CORE_ADDR
+linux_process_target::stopped_data_address ()
{
struct lwp_info *lwp = get_thread_lwp (current_thread);
return lwp->stopped_data_address;
}
-#if defined(__UCLIBC__) && defined(HAS_NOMMU) \
- && defined(PT_TEXT_ADDR) && defined(PT_DATA_ADDR) \
- && defined(PT_TEXT_END_ADDR)
-
/* This is only used for targets that define PT_TEXT_ADDR,
PT_DATA_ADDR and PT_TEXT_END_ADDR. If those are not defined, supposedly
the target has different ways of acquiring this information, like
loadmaps. */
+bool
+linux_process_target::supports_read_offsets ()
+{
+#ifdef SUPPORTS_READ_OFFSETS
+ return true;
+#else
+ return false;
+#endif
+}
+
/* Under uClinux, programs are loaded at non-zero offsets, which we need
to tell gdb about. */
-static int
-linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p)
+int
+linux_process_target::read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p)
{
+#ifdef SUPPORTS_READ_OFFSETS
unsigned long text, text_end, data;
int pid = lwpid_of (current_thread);
return 1;
}
- return 0;
+ return 0;
+#else
+ gdb_assert_not_reached ("target op read_offsets not supported");
+#endif
}
+
+bool
+linux_process_target::supports_get_tls_address ()
+{
+#ifdef USE_THREAD_DB
+ return true;
+#else
+ return false;
#endif
+}
-static int
-linux_qxfer_osdata (const char *annex,
- unsigned char *readbuf, unsigned const char *writebuf,
- CORE_ADDR offset, int len)
+int
+linux_process_target::get_tls_address (thread_info *thread,
+ CORE_ADDR offset,
+ CORE_ADDR load_module,
+ CORE_ADDR *address)
+{
+#ifdef USE_THREAD_DB
+ return thread_db_get_tls_address (thread, offset, load_module, address);
+#else
+ return -1;
+#endif
+}
+
+bool
+linux_process_target::supports_qxfer_osdata ()
+{
+ return true;
+}
+
+int
+linux_process_target::qxfer_osdata (const char *annex,
+ unsigned char *readbuf,
+ unsigned const char *writebuf,
+ CORE_ADDR offset, int len)
{
return linux_common_xfer_osdata (annex, readbuf, offset, len);
}
}
}
-static int
-linux_xfer_siginfo (const char *annex, unsigned char *readbuf,
- unsigned const char *writebuf, CORE_ADDR offset, int len)
+bool
+linux_process_target::supports_qxfer_siginfo ()
+{
+ return true;
+}
+
+int
+linux_process_target::qxfer_siginfo (const char *annex,
+ unsigned char *readbuf,
+ unsigned const char *writebuf,
+ CORE_ADDR offset, int len)
{
int pid;
siginfo_t siginfo;
errno = old_errno;
}
-static int
-linux_supports_non_stop (void)
+bool
+linux_process_target::supports_non_stop ()
{
- return 1;
+ return true;
}
-static int
-linux_async (int enable)
+bool
+linux_process_target::async (bool enable)
{
- int previous = target_is_async_p ();
+ bool previous = target_is_async_p ();
if (debug_threads)
debug_printf ("linux_async (%d), previous=%d\n",
return previous;
}
-static int
-linux_start_non_stop (int nonstop)
+int
+linux_process_target::start_non_stop (bool nonstop)
{
/* Register or unregister from event-loop accordingly. */
- linux_async (nonstop);
+ target_async (nonstop);
- if (target_is_async_p () != (nonstop != 0))
+ if (target_is_async_p () != (nonstop != false))
return -1;
return 0;
}
-static int
-linux_supports_multi_process (void)
+bool
+linux_process_target::supports_multi_process ()
{
- return 1;
+ return true;
}
/* Check if fork events are supported. */
-static int
-linux_supports_fork_events (void)
+bool
+linux_process_target::supports_fork_events ()
{
return linux_supports_tracefork ();
}
/* Check if vfork events are supported. */
-static int
-linux_supports_vfork_events (void)
+bool
+linux_process_target::supports_vfork_events ()
{
return linux_supports_tracefork ();
}
/* Check if exec events are supported. */
-static int
-linux_supports_exec_events (void)
+bool
+linux_process_target::supports_exec_events ()
{
return linux_supports_traceexec ();
}
ptrace flags for all inferiors. This is in case the new GDB connection
doesn't support the same set of events that the previous one did. */
-static void
-linux_handle_new_gdb_connection (void)
+void
+linux_process_target::handle_new_gdb_connection ()
{
/* Request that all the lwps reset their ptrace options. */
for_each_thread ([] (thread_info *thread)
});
}
-static int
-linux_supports_disable_randomization (void)
+int
+linux_process_target::handle_monitor_command (char *mon)
{
-#ifdef HAVE_PERSONALITY
- return 1;
+#ifdef USE_THREAD_DB
+ return thread_db_handle_monitor_command (mon);
#else
return 0;
#endif
}
-static int
-linux_supports_agent (void)
+int
+linux_process_target::core_of_thread (ptid_t ptid)
{
- return 1;
+ return linux_common_core_of_thread (ptid);
+}
+
+bool
+linux_process_target::supports_disable_randomization ()
+{
+#ifdef HAVE_PERSONALITY
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool
+linux_process_target::supports_agent ()
+{
+ return true;
}
static int
# define LINUX_LOADMAP_INTERP PTRACE_GETFDPIC_INTERP
# endif
-static int
-linux_read_loadmap (const char *annex, CORE_ADDR offset,
- unsigned char *myaddr, unsigned int len)
+bool
+linux_process_target::supports_read_loadmap ()
+{
+ return true;
+}
+
+int
+linux_process_target::read_loadmap (const char *annex, CORE_ADDR offset,
+ unsigned char *myaddr, unsigned int len)
{
int pid = lwpid_of (current_thread);
int addr = -1;
memcpy (myaddr, (char *) data + offset, copy_length);
return copy_length;
}
-#else
-# define linux_read_loadmap NULL
#endif /* defined PT_GETDSBT || defined PTRACE_GETFDPIC */
-static void
-linux_process_qsupported (char **features, int count)
+void
+linux_process_target::process_qsupported (char **features, int count)
{
if (the_low_target.process_qsupported != NULL)
the_low_target.process_qsupported (features, count);
return (*the_low_target.get_ipa_tdesc_idx) ();
}
-static int
-linux_supports_tracepoints (void)
+bool
+linux_process_target::supports_tracepoints ()
{
if (*the_low_target.supports_tracepoints == NULL)
- return 0;
+ return false;
return (*the_low_target.supports_tracepoints) ();
}
-static CORE_ADDR
-linux_read_pc (struct regcache *regcache)
+CORE_ADDR
+linux_process_target::read_pc (regcache *regcache)
{
if (the_low_target.get_pc == NULL)
return 0;
return (*the_low_target.get_pc) (regcache);
}
-static void
-linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
+void
+linux_process_target::write_pc (regcache *regcache, CORE_ADDR pc)
{
gdb_assert (the_low_target.set_pc != NULL);
(*the_low_target.set_pc) (regcache, pc);
}
-static int
-linux_thread_stopped (struct thread_info *thread)
+bool
+linux_process_target::supports_thread_stopped ()
+{
+ return true;
+}
+
+bool
+linux_process_target::thread_stopped (thread_info *thread)
{
return get_thread_lwp (thread)->stopped;
}
/* This exposes stop-all-threads functionality to other modules. */
-static void
-linux_pause_all (int freeze)
+void
+linux_process_target::pause_all (bool freeze)
{
stop_all_lwps (freeze, NULL);
}
/* This exposes unstop-all-threads functionality to other gdbserver
modules. */
-static void
-linux_unpause_all (int unfreeze)
+void
+linux_process_target::unpause_all (bool unfreeze)
{
unstop_all_lwps (unfreeze, NULL);
}
-static int
-linux_prepare_to_access_memory (void)
+int
+linux_process_target::prepare_to_access_memory ()
{
/* Neither ptrace nor /proc/PID/mem allow accessing memory through a
running LWP. */
if (non_stop)
- linux_pause_all (1);
+ target_pause_all (true);
return 0;
}
-static void
-linux_done_accessing_memory (void)
+void
+linux_process_target::done_accessing_memory ()
{
/* Neither ptrace nor /proc/PID/mem allow accessing memory through a
running LWP. */
if (non_stop)
- linux_unpause_all (1);
+ target_unpause_all (true);
}
-static int
-linux_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
- CORE_ADDR collector,
- CORE_ADDR lockaddr,
- ULONGEST orig_size,
- CORE_ADDR *jump_entry,
- CORE_ADDR *trampoline,
- ULONGEST *trampoline_size,
- unsigned char *jjump_pad_insn,
- ULONGEST *jjump_pad_insn_size,
- CORE_ADDR *adjusted_insn_addr,
- CORE_ADDR *adjusted_insn_addr_end,
- char *err)
+bool
+linux_process_target::supports_fast_tracepoints ()
+{
+ return the_low_target.install_fast_tracepoint_jump_pad != nullptr;
+}
+
+int
+linux_process_target::install_fast_tracepoint_jump_pad
+ (CORE_ADDR tpoint, CORE_ADDR tpaddr, CORE_ADDR collector,
+ CORE_ADDR lockaddr, ULONGEST orig_size, CORE_ADDR *jump_entry,
+ CORE_ADDR *trampoline, ULONGEST *trampoline_size,
+ unsigned char *jjump_pad_insn, ULONGEST *jjump_pad_insn_size,
+ CORE_ADDR *adjusted_insn_addr, CORE_ADDR *adjusted_insn_addr_end,
+ char *err)
{
return (*the_low_target.install_fast_tracepoint_jump_pad)
(tpoint, tpaddr, collector, lockaddr, orig_size,
err);
}
-static struct emit_ops *
-linux_emit_ops (void)
+emit_ops *
+linux_process_target::emit_ops ()
{
if (the_low_target.emit_ops != NULL)
return (*the_low_target.emit_ops) ();
return NULL;
}
-static int
-linux_get_min_fast_tracepoint_insn_len (void)
+int
+linux_process_target::get_min_fast_tracepoint_insn_len ()
{
return (*the_low_target.get_min_fast_tracepoint_insn_len) ();
}
return ret;
}
+bool
+linux_process_target::supports_qxfer_libraries_svr4 ()
+{
+ return true;
+}
+
struct link_map_offsets
{
/* Offset and size of r_debug.r_version. */
/* Construct qXfer:libraries-svr4:read reply. */
-static int
-linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
- unsigned const char *writebuf,
- CORE_ADDR offset, int len)
+int
+linux_process_target::qxfer_libraries_svr4 (const char *annex,
+ unsigned char *readbuf,
+ unsigned const char *writebuf,
+ CORE_ADDR offset, int len)
{
struct process_info_private *const priv = current_process ()->priv;
char filename[PATH_MAX];
#ifdef HAVE_LINUX_BTRACE
+btrace_target_info *
+linux_process_target::enable_btrace (ptid_t ptid,
+ const btrace_config *conf)
+{
+ return linux_enable_btrace (ptid, conf);
+}
+
/* See to_disable_btrace target method. */
-static int
-linux_low_disable_btrace (struct btrace_target_info *tinfo)
+int
+linux_process_target::disable_btrace (btrace_target_info *tinfo)
{
enum btrace_error err;
/* See to_read_btrace target method. */
-static int
-linux_low_read_btrace (struct btrace_target_info *tinfo, struct buffer *buffer,
- enum btrace_read_type type)
+int
+linux_process_target::read_btrace (btrace_target_info *tinfo,
+ buffer *buffer,
+ enum btrace_read_type type)
{
struct btrace_data btrace;
enum btrace_error err;
/* See to_btrace_conf target method. */
-static int
-linux_low_btrace_conf (const struct btrace_target_info *tinfo,
- struct buffer *buffer)
+int
+linux_process_target::read_btrace_conf (const btrace_target_info *tinfo,
+ buffer *buffer)
{
const struct btrace_config *conf;
gdb_assert (wordsize == 4 || wordsize == 8);
- while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
+ while (the_target->pt->read_auxv (offset, data, 2 * wordsize) == 2 * wordsize)
{
if (wordsize == 4)
{
static linux_process_target the_linux_target;
static process_stratum_target linux_target_ops = {
- linux_fetch_registers,
- linux_store_registers,
- linux_prepare_to_access_memory,
- linux_done_accessing_memory,
- linux_read_memory,
- linux_write_memory,
- linux_look_up_symbols,
- linux_request_interrupt,
- linux_read_auxv,
- linux_supports_z_point_type,
- linux_insert_point,
- linux_remove_point,
- linux_stopped_by_sw_breakpoint,
- linux_supports_stopped_by_sw_breakpoint,
- linux_stopped_by_hw_breakpoint,
- linux_supports_stopped_by_hw_breakpoint,
- linux_supports_hardware_single_step,
- linux_stopped_by_watchpoint,
- linux_stopped_data_address,
-#if defined(__UCLIBC__) && defined(HAS_NOMMU) \
- && defined(PT_TEXT_ADDR) && defined(PT_DATA_ADDR) \
- && defined(PT_TEXT_END_ADDR)
- linux_read_offsets,
-#else
- NULL,
-#endif
-#ifdef USE_THREAD_DB
- thread_db_get_tls_address,
-#else
- NULL,
-#endif
- hostio_last_error_from_errno,
- linux_qxfer_osdata,
- linux_xfer_siginfo,
- linux_supports_non_stop,
- linux_async,
- linux_start_non_stop,
- linux_supports_multi_process,
- linux_supports_fork_events,
- linux_supports_vfork_events,
- linux_supports_exec_events,
- linux_handle_new_gdb_connection,
-#ifdef USE_THREAD_DB
- thread_db_handle_monitor_command,
-#else
- NULL,
-#endif
- linux_common_core_of_thread,
- linux_read_loadmap,
- linux_process_qsupported,
- linux_supports_tracepoints,
- linux_read_pc,
- linux_write_pc,
- linux_thread_stopped,
- NULL,
- linux_pause_all,
- linux_unpause_all,
- linux_stabilize_threads,
- linux_install_fast_tracepoint_jump_pad,
- linux_emit_ops,
- linux_supports_disable_randomization,
- linux_get_min_fast_tracepoint_insn_len,
- linux_qxfer_libraries_svr4,
- linux_supports_agent,
-#ifdef HAVE_LINUX_BTRACE
- linux_enable_btrace,
- linux_low_disable_btrace,
- linux_low_read_btrace,
- linux_low_btrace_conf,
-#else
- NULL,
- NULL,
- NULL,
- NULL,
-#endif
linux_supports_range_stepping,
linux_proc_pid_to_exec_file,
linux_mntns_open_cloexec,