#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
{
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
}
+
+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
+}
-static int
-linux_qxfer_osdata (const char *annex,
- unsigned char *readbuf, unsigned const char *writebuf,
- CORE_ADDR offset, int len)
+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)
});
}
+int
+linux_process_target::handle_monitor_command (char *mon)
+{
+#ifdef USE_THREAD_DB
+ return thread_db_handle_monitor_command (mon);
+#else
+ return 0;
+#endif
+}
+
+int
+linux_process_target::core_of_thread (ptid_t ptid)
+{
+ return linux_common_core_of_thread (ptid);
+}
+
static int
linux_supports_disable_randomization (void)
{
# 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);
}
/* 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;
}
/* 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,
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) ();
}
static linux_process_target the_linux_target;
static process_stratum_target linux_target_ops = {
- 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