/* Ada Ravenscar thread support.
- Copyright (C) 2004-2017 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "inferior.h"
#include "command.h"
#include "ravenscar-thread.h"
-#include "observer.h"
+#include "observable.h"
#include "gdbcmd.h"
#include "top.h"
#include "regcache.h"
/* If non-null, ravenscar task support is enabled. */
static int ravenscar_task_support = 1;
-/* This module's target-specific operations. */
-static struct target_ops ravenscar_ops;
-
/* PTID of the last thread that received an event.
This can be useful to determine the associated task that received
the event, to make it the current task. */
static const char ravenscar_runtime_initializer[] =
"system__bb__threads__initialize";
-static void ravenscar_update_thread_list (struct target_ops *ops);
+static const target_info ravenscar_target_info = {
+ "ravenscar",
+ N_("Ravenscar tasks."),
+ N_("Ravenscar tasks support.")
+};
+
+struct ravenscar_thread_target final : public target_ops
+{
+ ravenscar_thread_target ()
+ { to_stratum = thread_stratum; }
+
+ const target_info &info () const override
+ { return ravenscar_target_info; }
+
+ ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+ void resume (ptid_t, int, enum gdb_signal) override;
+
+ void fetch_registers (struct regcache *, int) override;
+ void store_registers (struct regcache *, int) override;
+
+ void prepare_to_store (struct regcache *) override;
+
+ bool stopped_by_sw_breakpoint () override;
+
+ bool stopped_by_hw_breakpoint () override;
+
+ bool stopped_by_watchpoint () override;
+
+ bool stopped_data_address (CORE_ADDR *) override;
+
+ bool thread_alive (ptid_t ptid) override;
+
+ int core_of_thread (ptid_t ptid) override;
+
+ void update_thread_list () override;
+
+ const char *extra_thread_info (struct thread_info *) override;
+
+ const char *pid_to_str (ptid_t) override;
+
+ ptid_t get_ada_task_ptid (long lwp, long thread) override;
+
+ void mourn_inferior () override;
+
+ bool has_all_memory () override { return default_child_has_all_memory (); }
+ bool has_memory () override { return default_child_has_memory (); }
+ bool has_stack () override { return default_child_has_stack (); }
+ bool has_registers () override { return default_child_has_registers (); }
+ bool has_execution (ptid_t ptid) override
+ { return default_child_has_execution (ptid); }
+};
+
+/* This module's target-specific operations. */
+static ravenscar_thread_target ravenscar_ops;
+
static ptid_t ravenscar_active_task (int cpu);
-static const char *ravenscar_extra_thread_info (struct target_ops *self,
- struct thread_info *tp);
-static int ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid);
-static void ravenscar_fetch_registers (struct target_ops *ops,
- struct regcache *regcache, int regnum);
-static void ravenscar_store_registers (struct target_ops *ops,
- struct regcache *regcache, int regnum);
-static void ravenscar_prepare_to_store (struct target_ops *self,
- struct regcache *regcache);
-static void ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
- enum gdb_signal siggnal);
-static void ravenscar_mourn_inferior (struct target_ops *ops);
static void ravenscar_update_inferior_ptid (void);
static int has_ravenscar_runtime (void);
static int ravenscar_runtime_initialized (void);
static int
is_ravenscar_task (ptid_t ptid)
{
- /* By construction, ravenscar tasks have their LWP set to zero. */
- return ptid_get_lwp (ptid) == 0;
+ /* By construction, ravenscar tasks have their LWP set to zero.
+ Also make sure that the TID is nonzero, as some remotes, when
+ asked for the list of threads, will return the first thread
+ as having its TID set to zero. For instance, TSIM version
+ 2.0.48 for LEON3 sends 'm0' as a reply to the 'qfThreadInfo'
+ query, which the remote protocol layer then treats as a thread
+ whose TID is 0. This is obviously not a ravenscar task. */
+ return ptid.lwp () == 0 && ptid.tid () != 0;
}
/* Given PTID, which can be either a ravenscar task or a CPU thread,
else
{
/* We assume that the LWP of the PTID is equal to the CPU number. */
- base_cpu = ptid_get_lwp (ptid);
+ base_cpu = ptid.lwp ();
}
return base_cpu;
ptid_t active_task_ptid
= ravenscar_active_task (ravenscar_get_thread_base_cpu (ptid));
- return ptid_equal (ptid, active_task_ptid);
+ return ptid == active_task_ptid;
}
/* Return the CPU thread (as a ptid_t) on which the given ravenscar
return ptid;
base_cpu = ravenscar_get_thread_base_cpu (ptid);
- return ptid_build (ptid_get_pid (ptid), base_cpu, 0);
+ return ptid_t (ptid.pid (), base_cpu, 0);
}
/* Fetch the ravenscar running thread from target memory and
/* Make sure we set base_ptid before calling ravenscar_active_task
as the latter relies on it. */
inferior_ptid = ravenscar_active_task (base_cpu);
- gdb_assert (!ptid_equal (inferior_ptid, null_ptid));
+ gdb_assert (inferior_ptid != null_ptid);
/* The running thread may not have been added to
system.tasking.debug's list yet; so ravenscar_update_thread_list
static int
ravenscar_runtime_initialized (void)
{
- return (!(ptid_equal (ravenscar_active_task (1), null_ptid)));
+ return (!(ravenscar_active_task (1) == null_ptid));
}
/* Return the ID of the thread that is currently running.
return extract_typed_address (buf, builtin_type_void_data_ptr);
}
-static void
-ravenscar_resume (struct target_ops *ops, ptid_t ptid, int step,
- enum gdb_signal siggnal)
+void
+ravenscar_thread_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
{
- struct target_ops *beneath = find_target_beneath (ops);
-
inferior_ptid = base_ptid;
- beneath->to_resume (beneath, base_ptid, step, siggnal);
+ beneath ()->resume (base_ptid, step, siggnal);
}
-static ptid_t
-ravenscar_wait (struct target_ops *ops, ptid_t ptid,
- struct target_waitstatus *status,
- int options)
+ptid_t
+ravenscar_thread_target::wait (ptid_t ptid,
+ struct target_waitstatus *status,
+ int options)
{
- struct target_ops *beneath = find_target_beneath (ops);
+ ptid_t event_ptid;
inferior_ptid = base_ptid;
- beneath->to_wait (beneath, base_ptid, status, 0);
+ event_ptid = beneath ()->wait (base_ptid, status, 0);
/* Find any new threads that might have been created, and update
inferior_ptid to the active thread.
if (status->kind != TARGET_WAITKIND_EXITED
&& status->kind != TARGET_WAITKIND_SIGNALLED)
{
- ravenscar_update_thread_list (ops);
+ inferior_ptid = event_ptid;
+ this->update_thread_list ();
ravenscar_update_inferior_ptid ();
}
return inferior_ptid;
add_thread (task->ptid);
}
-static void
-ravenscar_update_thread_list (struct target_ops *ops)
+void
+ravenscar_thread_target::update_thread_list ()
{
ada_build_task_list ();
if (tid == 0)
return null_ptid;
else
- return ptid_build (ptid_get_pid (base_ptid), 0, tid);
+ return ptid_t (base_ptid.pid (), 0, tid);
}
-static const char *
-ravenscar_extra_thread_info (struct target_ops *self, struct thread_info *tp)
+const char *
+ravenscar_thread_target::extra_thread_info (thread_info *tp)
{
return "Ravenscar task";
}
-static int
-ravenscar_thread_alive (struct target_ops *ops, ptid_t ptid)
+bool
+ravenscar_thread_target::thread_alive (ptid_t ptid)
{
/* Ravenscar tasks are non-terminating. */
- return 1;
+ return true;
}
-static const char *
-ravenscar_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+ravenscar_thread_target::pid_to_str (ptid_t ptid)
{
static char buf[30];
- snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid_get_tid (ptid));
+ snprintf (buf, sizeof (buf), "Thread %#x", (int) ptid.tid ());
return buf;
}
-static void
-ravenscar_fetch_registers (struct target_ops *ops,
- struct regcache *regcache, int regnum)
+void
+ravenscar_thread_target::fetch_registers (struct regcache *regcache, int regnum)
{
- struct target_ops *beneath = find_target_beneath (ops);
- ptid_t ptid = regcache_get_ptid (regcache);
+ ptid_t ptid = regcache->ptid ();
if (ravenscar_runtime_initialized ()
&& is_ravenscar_task (ptid)
arch_ops->to_fetch_registers (regcache, regnum);
}
else
- beneath->to_fetch_registers (beneath, regcache, regnum);
+ beneath ()->fetch_registers (regcache, regnum);
}
-static void
-ravenscar_store_registers (struct target_ops *ops,
- struct regcache *regcache, int regnum)
+void
+ravenscar_thread_target::store_registers (struct regcache *regcache,
+ int regnum)
{
- struct target_ops *beneath = find_target_beneath (ops);
- ptid_t ptid = regcache_get_ptid (regcache);
+ ptid_t ptid = regcache->ptid ();
if (ravenscar_runtime_initialized ()
&& is_ravenscar_task (ptid)
arch_ops->to_store_registers (regcache, regnum);
}
else
- beneath->to_store_registers (beneath, regcache, regnum);
+ beneath ()->store_registers (regcache, regnum);
}
-static void
-ravenscar_prepare_to_store (struct target_ops *self,
- struct regcache *regcache)
+void
+ravenscar_thread_target::prepare_to_store (struct regcache *regcache)
{
- struct target_ops *beneath = find_target_beneath (self);
- ptid_t ptid = regcache_get_ptid (regcache);
+ ptid_t ptid = regcache->ptid ();
if (ravenscar_runtime_initialized ()
&& is_ravenscar_task (ptid)
arch_ops->to_prepare_to_store (regcache);
}
else
- beneath->to_prepare_to_store (beneath, regcache);
+ beneath ()->prepare_to_store (regcache);
}
/* Implement the to_stopped_by_sw_breakpoint target_ops "method". */
-static int
-ravenscar_stopped_by_sw_breakpoint (struct target_ops *ops)
+bool
+ravenscar_thread_target::stopped_by_sw_breakpoint ()
{
ptid_t saved_ptid = inferior_ptid;
- struct target_ops *beneath = find_target_beneath (ops);
- int result;
+ bool result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
- result = beneath->to_stopped_by_sw_breakpoint (beneath);
+ result = beneath ()->stopped_by_sw_breakpoint ();
inferior_ptid = saved_ptid;
return result;
}
/* Implement the to_stopped_by_hw_breakpoint target_ops "method". */
-static int
-ravenscar_stopped_by_hw_breakpoint (struct target_ops *ops)
+bool
+ravenscar_thread_target::stopped_by_hw_breakpoint ()
{
ptid_t saved_ptid = inferior_ptid;
- struct target_ops *beneath = find_target_beneath (ops);
- int result;
+ bool result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
- result = beneath->to_stopped_by_hw_breakpoint (beneath);
+ result = beneath ()->stopped_by_hw_breakpoint ();
inferior_ptid = saved_ptid;
return result;
}
/* Implement the to_stopped_by_watchpoint target_ops "method". */
-static int
-ravenscar_stopped_by_watchpoint (struct target_ops *ops)
+bool
+ravenscar_thread_target::stopped_by_watchpoint ()
{
ptid_t saved_ptid = inferior_ptid;
- struct target_ops *beneath = find_target_beneath (ops);
- int result;
+ bool result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
- result = beneath->to_stopped_by_watchpoint (beneath);
+ result = beneath ()->stopped_by_watchpoint ();
inferior_ptid = saved_ptid;
return result;
}
/* Implement the to_stopped_data_address target_ops "method". */
-static int
-ravenscar_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
+bool
+ravenscar_thread_target::stopped_data_address (CORE_ADDR *addr_p)
{
ptid_t saved_ptid = inferior_ptid;
- struct target_ops *beneath = find_target_beneath (ops);
- int result;
+ bool result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
- result = beneath->to_stopped_data_address (beneath, addr_p);
+ result = beneath ()->stopped_data_address (addr_p);
inferior_ptid = saved_ptid;
return result;
}
-static void
-ravenscar_mourn_inferior (struct target_ops *ops)
+void
+ravenscar_thread_target::mourn_inferior ()
{
- struct target_ops *beneath = find_target_beneath (ops);
-
base_ptid = null_ptid;
- beneath->to_mourn_inferior (beneath);
+ beneath ()->mourn_inferior ();
unpush_target (&ravenscar_ops);
}
/* Implement the to_core_of_thread target_ops "method". */
-static int
-ravenscar_core_of_thread (struct target_ops *ops, ptid_t ptid)
+int
+ravenscar_thread_target::core_of_thread (ptid_t ptid)
{
ptid_t saved_ptid = inferior_ptid;
- struct target_ops *beneath = find_target_beneath (ops);
int result;
inferior_ptid = get_base_thread_from_ravenscar_task (saved_ptid);
- result = beneath->to_core_of_thread (beneath, inferior_ptid);
+ result = beneath ()->core_of_thread (inferior_ptid);
inferior_ptid = saved_ptid;
return result;
}
err_msg = ada_get_tcb_types_info ();
if (err_msg != NULL)
{
- warning (_("%s. Task/thread support disabled.\n"), err_msg);
+ warning (_("%s. Task/thread support disabled."), err_msg);
return;
}
push_target (&ravenscar_ops);
}
-static ptid_t
-ravenscar_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
+ptid_t
+ravenscar_thread_target::get_ada_task_ptid (long lwp, long thread)
{
- return ptid_build (ptid_get_pid (base_ptid), 0, thread);
-}
-
-static void
-init_ravenscar_thread_ops (void)
-{
- ravenscar_ops.to_shortname = "ravenscar";
- ravenscar_ops.to_longname = "Ravenscar tasks.";
- ravenscar_ops.to_doc = "Ravenscar tasks support.";
- ravenscar_ops.to_resume = ravenscar_resume;
- ravenscar_ops.to_wait = ravenscar_wait;
- ravenscar_ops.to_fetch_registers = ravenscar_fetch_registers;
- ravenscar_ops.to_store_registers = ravenscar_store_registers;
- ravenscar_ops.to_prepare_to_store = ravenscar_prepare_to_store;
- ravenscar_ops.to_stopped_by_sw_breakpoint
- = ravenscar_stopped_by_sw_breakpoint;
- ravenscar_ops.to_stopped_by_hw_breakpoint
- = ravenscar_stopped_by_hw_breakpoint;
- ravenscar_ops.to_stopped_by_watchpoint = ravenscar_stopped_by_watchpoint;
- ravenscar_ops.to_stopped_data_address = ravenscar_stopped_data_address;
- ravenscar_ops.to_thread_alive = ravenscar_thread_alive;
- ravenscar_ops.to_update_thread_list = ravenscar_update_thread_list;
- ravenscar_ops.to_pid_to_str = ravenscar_pid_to_str;
- ravenscar_ops.to_extra_thread_info = ravenscar_extra_thread_info;
- ravenscar_ops.to_get_ada_task_ptid = ravenscar_get_ada_task_ptid;
- ravenscar_ops.to_mourn_inferior = ravenscar_mourn_inferior;
- ravenscar_ops.to_has_all_memory = default_child_has_all_memory;
- ravenscar_ops.to_has_memory = default_child_has_memory;
- ravenscar_ops.to_has_stack = default_child_has_stack;
- ravenscar_ops.to_has_registers = default_child_has_registers;
- ravenscar_ops.to_has_execution = default_child_has_execution;
- ravenscar_ops.to_stratum = thread_stratum;
- ravenscar_ops.to_core_of_thread = ravenscar_core_of_thread;
- ravenscar_ops.to_magic = OPS_MAGIC;
+ return ptid_t (base_ptid.pid (), 0, thread);
}
/* Command-list for the "set/show ravenscar" prefix command. */
void
_initialize_ravenscar (void)
{
- init_ravenscar_thread_ops ();
base_ptid = null_ptid;
/* Notice when the inferior is created in order to push the
ravenscar ops if needed. */
- observer_attach_inferior_created (ravenscar_inferior_created);
-
- complete_target_initialization (&ravenscar_ops);
+ gdb::observers::inferior_created.attach (ravenscar_inferior_created);
add_prefix_cmd ("ravenscar", no_class, set_ravenscar_command,
_("Prefix command for changing Ravenscar-specific settings"),