/* Ada Ravenscar thread support.

   Copyright (C) 2004-2023 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "gdbcore.h"
#include "gdbthread.h"
#include "ada-lang.h"
#include "target.h"
#include "inferior.h"
#include "command.h"
#include "ravenscar-thread.h"
#include "observable.h"
#include "gdbcmd.h"
#include "top.h"
#include "regcache.h"
#include "objfiles.h"
#include <unordered_map>

/* This module provides support for "Ravenscar" tasks (Ada) when
   debugging on bare-metal targets.

   The typical situation is when debugging a bare-metal target over
   the remote protocol. In that situation, the system does not know
   about high-level concepts such as threads, only about some code
   running on one or more CPUs. And since the remote protocol does not
   provide any handling for CPUs, the de facto standard for handling
   them is to have one thread per CPU, where the thread's ptid has
   its lwp field set to the CPU number (eg: 1 for the first CPU,
   2 for the second one, etc).  This module will make that assumption.

   This module then creates and maintains the list of threads based
   on the list of Ada tasks, with one thread per Ada task. The convention
   is that threads corresponding to the CPUs (see assumption above)
   have a ptid_t of the form (PID, LWP, 0), while threads corresponding
   to our Ada tasks have a ptid_t of the form (PID, 0, TID) where TID
   is the Ada task's ID as extracted from Ada runtime information.

   Switching to a given Ada task (or its underlying thread) is performed
   by fetching the registers of that task from the memory area where
   the registers were saved.  For any of the other operations, the
   operation is performed by first finding the CPU on which the task
   is running, switching to its corresponding ptid, and then performing
   the operation on that ptid using the target beneath us.  */

/* If true, ravenscar task support is enabled.  */
static bool ravenscar_task_support = true;

static const char running_thread_name[] = "__gnat_running_thread_table";

static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
static const char first_task_name[] = "system__tasking__debug__first_task";

static const char ravenscar_runtime_initializer[]
  = "system__bb__threads__initialize";

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 ()
    : m_base_ptid (inferior_ptid)
  {
  }

  const target_info &info () const override
  { return ravenscar_target_info; }

  strata stratum () const override { return thread_stratum; }

  ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) 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;

  enum target_xfer_status xfer_partial (enum target_object object,
					const char *annex,
					gdb_byte *readbuf,
					const gdb_byte *writebuf,
					ULONGEST offset, ULONGEST len,
					ULONGEST *xfered_len) override;

  bool thread_alive (ptid_t ptid) override;

  int core_of_thread (ptid_t ptid) override;

  void update_thread_list () override;

  std::string pid_to_str (ptid_t) override;

  ptid_t get_ada_task_ptid (long lwp, ULONGEST thread) override;

  struct btrace_target_info *enable_btrace (thread_info *tp,
					    const struct btrace_config *conf)
    override
  {
    process_stratum_target *proc_target
      = as_process_stratum_target (this->beneath ());
    ptid_t underlying = get_base_thread_from_ravenscar_task (tp->ptid);
    tp = find_thread_ptid (proc_target, underlying);

    return beneath ()->enable_btrace (tp, conf);
  }

  void mourn_inferior () override;

  void close () override
  {
    delete this;
  }

  thread_info *add_active_thread ();

private:

  /* 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.  */
  ptid_t m_base_ptid;

  ptid_t active_task (int cpu);
  bool task_is_currently_active (ptid_t ptid);
  bool runtime_initialized ();
  int get_thread_base_cpu (ptid_t ptid);
  ptid_t get_base_thread_from_ravenscar_task (ptid_t ptid);
  void add_thread (struct ada_task_info *task);

  /* Like switch_to_thread, but uses the base ptid for the thread.  */
  void set_base_thread_from_ravenscar_task (ptid_t ptid)
  {
    process_stratum_target *proc_target
      = as_process_stratum_target (this->beneath ());
    ptid_t underlying = get_base_thread_from_ravenscar_task (ptid);
    switch_to_thread (find_thread_ptid (proc_target, underlying));
  }

  /* Some targets use lazy FPU initialization.  On these, the FP
     registers for a given task might be uninitialized, or stored in
     the per-task context, or simply be the live registers on the CPU.
     This enum is used to encode this information.  */
  enum fpu_state
  {
    /* This target doesn't do anything special for FP registers -- if
       any exist, they are treated just identical to non-FP
       registers.  */
    NOTHING_SPECIAL,
    /* This target uses the lazy FP scheme, and the FP registers are
       taken from the CPU.  This can happen for any task, because if a
       task switch occurs, the registers aren't immediately written to
       the per-task context -- this is deferred until the current task
       causes an FPU trap.  */
    LIVE_FP_REGISTERS,
    /* This target uses the lazy FP scheme, and the FP registers are
       not available.  Maybe this task never initialized the FPU, or
       maybe GDB couldn't find the required symbol.  */
    NO_FP_REGISTERS
  };

  /* Return the FPU state.  */
  fpu_state get_fpu_state (struct regcache *regcache,
			   const ravenscar_arch_ops *arch_ops);

  /* This maps a TID to the CPU on which it was running.  This is
     needed because sometimes the runtime will report an active task
     that hasn't yet been put on the list of tasks that is read by
     ada-tasks.c.  */
  std::unordered_map<ULONGEST, int> m_cpu_map;
};

/* Return true iff PTID corresponds to a ravenscar task.  */

static bool
is_ravenscar_task (ptid_t ptid)
{
  /* 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,
   return which CPU that ptid is running on.

   This assume that PTID is a valid ptid_t.  Otherwise, a gdb_assert
   will be triggered.  */

int
ravenscar_thread_target::get_thread_base_cpu (ptid_t ptid)
{
  int base_cpu;

  if (is_ravenscar_task (ptid))
    {
      /* Prefer to not read inferior memory if possible, to avoid
	 reentrancy problems with xfer_partial.  */
      auto iter = m_cpu_map.find (ptid.tid ());

      if (iter != m_cpu_map.end ())
	base_cpu = iter->second;
      else
	{
	  struct ada_task_info *task_info = ada_get_task_info_from_ptid (ptid);

	  gdb_assert (task_info != NULL);
	  base_cpu = task_info->base_cpu;
	}
    }
  else
    {
      /* We assume that the LWP of the PTID is equal to the CPU number.  */
      base_cpu = ptid.lwp ();
    }

  return base_cpu;
}

/* Given a ravenscar task (identified by its ptid_t PTID), return true
   if this task is the currently active task on the cpu that task is
   running on.

   In other words, this function determine which CPU this task is
   currently running on, and then return nonzero if the CPU in question
   is executing the code for that task.  If that's the case, then
   that task's registers are in the CPU bank.  Otherwise, the task
   is currently suspended, and its registers have been saved in memory.  */

bool
ravenscar_thread_target::task_is_currently_active (ptid_t ptid)
{
  ptid_t active_task_ptid = active_task (get_thread_base_cpu (ptid));

  return ptid == active_task_ptid;
}

/* Return the CPU thread (as a ptid_t) on which the given ravenscar
   task is running.

   This is the thread that corresponds to the CPU on which the task
   is running.  */

ptid_t
ravenscar_thread_target::get_base_thread_from_ravenscar_task (ptid_t ptid)
{
  int base_cpu;

  if (!is_ravenscar_task (ptid))
    return ptid;

  base_cpu = get_thread_base_cpu (ptid);
  return ptid_t (ptid.pid (), base_cpu);
}

/* Fetch the ravenscar running thread from target memory, make sure
   there's a corresponding thread in the thread list, and return it.
   If the runtime is not initialized, return NULL.  */

thread_info *
ravenscar_thread_target::add_active_thread ()
{
  process_stratum_target *proc_target
    = as_process_stratum_target (this->beneath ());

  int base_cpu;

  gdb_assert (!is_ravenscar_task (m_base_ptid));
  base_cpu = get_thread_base_cpu (m_base_ptid);

  if (!runtime_initialized ())
    return nullptr;

  /* It's possible for runtime_initialized to return true but for it
     not to be fully initialized.  For example, this can happen for a
     breakpoint placed at the task's beginning.  */
  ptid_t active_ptid = active_task (base_cpu);
  if (active_ptid == null_ptid)
    return nullptr;

  /* The running thread may not have been added to
     system.tasking.debug's list yet; so ravenscar_update_thread_list
     may not always add it to the thread list.  Add it here.  */
  thread_info *active_thr = find_thread_ptid (proc_target, active_ptid);
  if (active_thr == nullptr)
    {
      active_thr = ::add_thread (proc_target, active_ptid);
      m_cpu_map[active_ptid.tid ()] = base_cpu;
    }
  return active_thr;
}

/* The Ravenscar Runtime exports a symbol which contains the ID of
   the thread that is currently running.  Try to locate that symbol
   and return its associated minimal symbol.
   Return NULL if not found.  */

static struct bound_minimal_symbol
get_running_thread_msymbol ()
{
  struct bound_minimal_symbol msym;

  msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
  if (!msym.minsym)
    /* Older versions of the GNAT runtime were using a different
       (less ideal) name for the symbol where the active thread ID
       is stored.  If we couldn't find the symbol using the latest
       name, then try the old one.  */
    msym = lookup_minimal_symbol ("running_thread", NULL, NULL);

  return msym;
}

/* Return True if the Ada Ravenscar run-time can be found in the
   application.  */

static bool
has_ravenscar_runtime ()
{
  struct bound_minimal_symbol msym_ravenscar_runtime_initializer
    = lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
  struct bound_minimal_symbol msym_known_tasks
    = lookup_minimal_symbol (known_tasks_name, NULL, NULL);
  struct bound_minimal_symbol msym_first_task
    = lookup_minimal_symbol (first_task_name, NULL, NULL);
  struct bound_minimal_symbol msym_running_thread
    = get_running_thread_msymbol ();

  return (msym_ravenscar_runtime_initializer.minsym
	  && (msym_known_tasks.minsym || msym_first_task.minsym)
	  && msym_running_thread.minsym);
}

/* Return True if the Ada Ravenscar run-time can be found in the
   application, and if it has been initialized on target.  */

bool
ravenscar_thread_target::runtime_initialized ()
{
  return active_task (1) != null_ptid;
}

/* Return the ID of the thread that is currently running.
   Return 0 if the ID could not be determined.  */

static CORE_ADDR
get_running_thread_id (int cpu)
{
  struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
  int object_size;
  int buf_size;
  gdb_byte *buf;
  CORE_ADDR object_addr;
  struct type *builtin_type_void_data_ptr
    = builtin_type (target_gdbarch ())->builtin_data_ptr;

  if (!object_msym.minsym)
    return 0;

  object_size = builtin_type_void_data_ptr->length ();
  object_addr = (object_msym.value_address ()
		 + (cpu - 1) * object_size);
  buf_size = object_size;
  buf = (gdb_byte *) alloca (buf_size);
  read_memory (object_addr, buf, buf_size);
  return extract_typed_address (buf, builtin_type_void_data_ptr);
}

void
ravenscar_thread_target::resume (ptid_t ptid, int step,
				 enum gdb_signal siggnal)
{
  /* If we see a wildcard resume, we simply pass that on.  Otherwise,
     arrange to resume the base ptid.  */
  inferior_ptid = m_base_ptid;
  if (ptid.is_pid ())
    {
      /* We only have one process, so resume all threads of it.  */
      ptid = minus_one_ptid;
    }
  else if (ptid != minus_one_ptid)
    ptid = m_base_ptid;
  beneath ()->resume (ptid, step, siggnal);
}

ptid_t
ravenscar_thread_target::wait (ptid_t ptid,
			       struct target_waitstatus *status,
			       target_wait_flags options)
{
  process_stratum_target *beneath
    = as_process_stratum_target (this->beneath ());
  ptid_t event_ptid;

  if (ptid != minus_one_ptid)
    ptid = m_base_ptid;
  event_ptid = beneath->wait (ptid, status, 0);
  /* Find any new threads that might have been created, and return the
     active thread.

     Only do it if the program is still alive, though.  Otherwise,
     this causes problems when debugging through the remote protocol,
     because we might try switching threads (and thus sending packets)
     after the remote has disconnected.  */
  if (status->kind () != TARGET_WAITKIND_EXITED
      && status->kind () != TARGET_WAITKIND_SIGNALLED
      && runtime_initialized ())
    {
      m_base_ptid = event_ptid;
      this->update_thread_list ();
      thread_info *thr = this->add_active_thread ();
      if (thr != nullptr)
	return thr->ptid;
    }
  return event_ptid;
}

/* Add the thread associated to the given TASK to the thread list
   (if the thread has already been added, this is a no-op).  */

void
ravenscar_thread_target::add_thread (struct ada_task_info *task)
{
  if (find_thread_ptid (current_inferior (), task->ptid) == NULL)
    {
      ::add_thread (current_inferior ()->process_target (), task->ptid);
      m_cpu_map[task->ptid.tid ()] = task->base_cpu;
    }
}

void
ravenscar_thread_target::update_thread_list ()
{
  /* iterate_over_live_ada_tasks requires that inferior_ptid be set,
     but this isn't always the case in target methods.  So, we ensure
     it here.  */
  scoped_restore save_ptid = make_scoped_restore (&inferior_ptid,
						  m_base_ptid);

  /* Do not clear the thread list before adding the Ada task, to keep
     the thread that the process stratum has included into it
     (m_base_ptid) and the running thread, that may not have been included
     to system.tasking.debug's list yet.  */

  iterate_over_live_ada_tasks ([=] (struct ada_task_info *task)
			       {
				 this->add_thread (task);
			       });
}

ptid_t
ravenscar_thread_target::active_task (int cpu)
{
  CORE_ADDR tid = get_running_thread_id (cpu);

  if (tid == 0)
    return null_ptid;
  else
    return ptid_t (m_base_ptid.pid (), 0, tid);
}

bool
ravenscar_thread_target::thread_alive (ptid_t ptid)
{
  /* Ravenscar tasks are non-terminating.  */
  return true;
}

std::string
ravenscar_thread_target::pid_to_str (ptid_t ptid)
{
  if (!is_ravenscar_task (ptid))
    return beneath ()->pid_to_str (ptid);

  return string_printf ("Ravenscar Thread 0x%s",
			phex_nz (ptid.tid (), sizeof (ULONGEST)));
}

CORE_ADDR
ravenscar_arch_ops::get_stack_base (struct regcache *regcache) const
{
  struct gdbarch *gdbarch = regcache->arch ();
  const int sp_regnum = gdbarch_sp_regnum (gdbarch);
  ULONGEST stack_address;
  regcache_cooked_read_unsigned (regcache, sp_regnum, &stack_address);
  return (CORE_ADDR) stack_address;
}

void
ravenscar_arch_ops::supply_one_register (struct regcache *regcache,
					 int regnum,
					 CORE_ADDR descriptor,
					 CORE_ADDR stack_base) const
{
  CORE_ADDR addr;
  if (regnum >= first_stack_register && regnum <= last_stack_register)
    addr = stack_base;
  else
    addr = descriptor;
  addr += offsets[regnum];

  struct gdbarch *gdbarch = regcache->arch ();
  int size = register_size (gdbarch, regnum);
  gdb_byte *buf = (gdb_byte *) alloca (size);
  read_memory (addr, buf, size);
  regcache->raw_supply (regnum, buf);
}

void
ravenscar_arch_ops::fetch_register (struct regcache *regcache,
				    int regnum) const
{
  gdb_assert (regnum != -1);

  struct gdbarch *gdbarch = regcache->arch ();
  /* The tid is the thread_id field, which is a pointer to the thread.  */
  CORE_ADDR thread_descriptor_address
    = (CORE_ADDR) regcache->ptid ().tid ();

  int sp_regno = -1;
  CORE_ADDR stack_address = 0;
  if (regnum >= first_stack_register && regnum <= last_stack_register)
    {
      /* We must supply SP for get_stack_base, so recurse.  */
      sp_regno = gdbarch_sp_regnum (gdbarch);
      gdb_assert (!(sp_regno >= first_stack_register
		    && sp_regno <= last_stack_register));
      fetch_register (regcache, sp_regno);
      stack_address = get_stack_base (regcache);
    }

  if (regnum < offsets.size () && offsets[regnum] != -1)
    supply_one_register (regcache, regnum, thread_descriptor_address,
			 stack_address);
}

void
ravenscar_arch_ops::store_one_register (struct regcache *regcache, int regnum,
					CORE_ADDR descriptor,
					CORE_ADDR stack_base) const
{
  CORE_ADDR addr;
  if (regnum >= first_stack_register && regnum <= last_stack_register)
    addr = stack_base;
  else
    addr = descriptor;
  addr += offsets[regnum];

  struct gdbarch *gdbarch = regcache->arch ();
  int size = register_size (gdbarch, regnum);
  gdb_byte *buf = (gdb_byte *) alloca (size);
  regcache->raw_collect (regnum, buf);
  write_memory (addr, buf, size);
}

void
ravenscar_arch_ops::store_register (struct regcache *regcache,
				    int regnum) const
{
  gdb_assert (regnum != -1);

  /* The tid is the thread_id field, which is a pointer to the thread.  */
  CORE_ADDR thread_descriptor_address
    = (CORE_ADDR) regcache->ptid ().tid ();

  CORE_ADDR stack_address = 0;
  if (regnum >= first_stack_register && regnum <= last_stack_register)
    stack_address = get_stack_base (regcache);

  if (regnum < offsets.size () && offsets[regnum] != -1)
    store_one_register (regcache, regnum, thread_descriptor_address,
			stack_address);
}

/* Temporarily set the ptid of a regcache to some other value.  When
   this object is destroyed, the regcache's original ptid is
   restored.  */

class temporarily_change_regcache_ptid
{
public:

  temporarily_change_regcache_ptid (struct regcache *regcache, ptid_t new_ptid)
    : m_regcache (regcache),
      m_save_ptid (regcache->ptid ())
  {
    m_regcache->set_ptid (new_ptid);
  }

  ~temporarily_change_regcache_ptid ()
  {
    m_regcache->set_ptid (m_save_ptid);
  }

private:

  /* The regcache.  */
  struct regcache *m_regcache;
  /* The saved ptid.  */
  ptid_t m_save_ptid;
};

ravenscar_thread_target::fpu_state
ravenscar_thread_target::get_fpu_state (struct regcache *regcache,
					const ravenscar_arch_ops *arch_ops)
{
  /* We want to return true if the special FP register handling is
     needed.  If this target doesn't have lazy FP, then no special
     treatment is ever needed.  */
  if (!arch_ops->on_demand_fp ())
    return NOTHING_SPECIAL;

  bound_minimal_symbol fpu_context
    = lookup_minimal_symbol ("system__bb__cpu_primitives__current_fpu_context",
			     nullptr, nullptr);
  /* If the symbol can't be found, just fall back.  */
  if (fpu_context.minsym == nullptr)
    return NO_FP_REGISTERS;

  struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
  ptr_type = lookup_pointer_type (ptr_type);
  value *val = value_from_pointer (ptr_type, fpu_context.value_address ());

  int cpu = get_thread_base_cpu (regcache->ptid ());
  /* The array index type has a lower bound of 1 -- it is Ada code --
     so subtract 1 here.  */
  val = value_ptradd (val, cpu - 1);

  val = value_ind (val);
  CORE_ADDR fpu_task = value_as_long (val);

  /* The tid is the thread_id field, which is a pointer to the thread.  */
  CORE_ADDR thread_descriptor_address
    = (CORE_ADDR) regcache->ptid ().tid ();
  if (fpu_task == (thread_descriptor_address
		   + arch_ops->get_fpu_context_offset ()))
    return LIVE_FP_REGISTERS;

  int v_init_offset = arch_ops->get_v_init_offset ();
  gdb_byte init = 0;
  read_memory (thread_descriptor_address + v_init_offset, &init, 1);
  return init ? NOTHING_SPECIAL : NO_FP_REGISTERS;
}

void
ravenscar_thread_target::fetch_registers (struct regcache *regcache,
					  int regnum)
{
  ptid_t ptid = regcache->ptid ();

  if (runtime_initialized () && is_ravenscar_task (ptid))
    {
      struct gdbarch *gdbarch = regcache->arch ();
      bool is_active = task_is_currently_active (ptid);
      struct ravenscar_arch_ops *arch_ops = gdbarch_ravenscar_ops (gdbarch);
      gdb::optional<fpu_state> fp_state;

      int low_reg = regnum == -1 ? 0 : regnum;
      int high_reg = regnum == -1 ? gdbarch_num_regs (gdbarch) : regnum + 1;

      ptid_t base = get_base_thread_from_ravenscar_task (ptid);
      for (int i = low_reg; i < high_reg; ++i)
	{
	  bool use_beneath = false;
	  if (arch_ops->is_fp_register (i))
	    {
	      if (!fp_state.has_value ())
		fp_state = get_fpu_state (regcache, arch_ops);
	      if (*fp_state == NO_FP_REGISTERS)
		continue;
	      if (*fp_state == LIVE_FP_REGISTERS
		  || (is_active && *fp_state == NOTHING_SPECIAL))
		use_beneath = true;
	    }
	  else
	    use_beneath = is_active;

	  if (use_beneath)
	    {
	      temporarily_change_regcache_ptid changer (regcache, base);
	      beneath ()->fetch_registers (regcache, i);
	    }
	  else
	    arch_ops->fetch_register (regcache, i);
	}
    }
  else
    beneath ()->fetch_registers (regcache, regnum);
}

void
ravenscar_thread_target::store_registers (struct regcache *regcache,
					  int regnum)
{
  ptid_t ptid = regcache->ptid ();

  if (runtime_initialized () && is_ravenscar_task (ptid))
    {
      struct gdbarch *gdbarch = regcache->arch ();
      bool is_active = task_is_currently_active (ptid);
      struct ravenscar_arch_ops *arch_ops = gdbarch_ravenscar_ops (gdbarch);
      gdb::optional<fpu_state> fp_state;

      int low_reg = regnum == -1 ? 0 : regnum;
      int high_reg = regnum == -1 ? gdbarch_num_regs (gdbarch) : regnum + 1;

      ptid_t base = get_base_thread_from_ravenscar_task (ptid);
      for (int i = low_reg; i < high_reg; ++i)
	{
	  bool use_beneath = false;
	  if (arch_ops->is_fp_register (i))
	    {
	      if (!fp_state.has_value ())
		fp_state = get_fpu_state (regcache, arch_ops);
	      if (*fp_state == NO_FP_REGISTERS)
		continue;
	      if (*fp_state == LIVE_FP_REGISTERS
		  || (is_active && *fp_state == NOTHING_SPECIAL))
		use_beneath = true;
	    }
	  else
	    use_beneath = is_active;

	  if (use_beneath)
	    {
	      temporarily_change_regcache_ptid changer (regcache, base);
	      beneath ()->store_registers (regcache, i);
	    }
	  else
	    arch_ops->store_register (regcache, i);
	}
    }
  else
    beneath ()->store_registers (regcache, regnum);
}

void
ravenscar_thread_target::prepare_to_store (struct regcache *regcache)
{
  ptid_t ptid = regcache->ptid ();

  if (runtime_initialized () && is_ravenscar_task (ptid))
    {
      if (task_is_currently_active (ptid))
	{
	  ptid_t base = get_base_thread_from_ravenscar_task (ptid);
	  temporarily_change_regcache_ptid changer (regcache, base);
	  beneath ()->prepare_to_store (regcache);
	}
      else
	{
	  /* Nothing.  */
	}
    }
  else
    beneath ()->prepare_to_store (regcache);
}

/* Implement the to_stopped_by_sw_breakpoint target_ops "method".  */

bool
ravenscar_thread_target::stopped_by_sw_breakpoint ()
{
  scoped_restore_current_thread saver;
  set_base_thread_from_ravenscar_task (inferior_ptid);
  return beneath ()->stopped_by_sw_breakpoint ();
}

/* Implement the to_stopped_by_hw_breakpoint target_ops "method".  */

bool
ravenscar_thread_target::stopped_by_hw_breakpoint ()
{
  scoped_restore_current_thread saver;
  set_base_thread_from_ravenscar_task (inferior_ptid);
  return beneath ()->stopped_by_hw_breakpoint ();
}

/* Implement the to_stopped_by_watchpoint target_ops "method".  */

bool
ravenscar_thread_target::stopped_by_watchpoint ()
{
  scoped_restore_current_thread saver;
  set_base_thread_from_ravenscar_task (inferior_ptid);
  return beneath ()->stopped_by_watchpoint ();
}

/* Implement the to_stopped_data_address target_ops "method".  */

bool
ravenscar_thread_target::stopped_data_address (CORE_ADDR *addr_p)
{
  scoped_restore_current_thread saver;
  set_base_thread_from_ravenscar_task (inferior_ptid);
  return beneath ()->stopped_data_address (addr_p);
}

void
ravenscar_thread_target::mourn_inferior ()
{
  m_base_ptid = null_ptid;
  target_ops *beneath = this->beneath ();
  current_inferior ()->unpush_target (this);
  beneath->mourn_inferior ();
}

/* Implement the to_core_of_thread target_ops "method".  */

int
ravenscar_thread_target::core_of_thread (ptid_t ptid)
{
  scoped_restore_current_thread saver;
  set_base_thread_from_ravenscar_task (inferior_ptid);
  return beneath ()->core_of_thread (inferior_ptid);
}

/* Implement the target xfer_partial method.  */

enum target_xfer_status
ravenscar_thread_target::xfer_partial (enum target_object object,
				       const char *annex,
				       gdb_byte *readbuf,
				       const gdb_byte *writebuf,
				       ULONGEST offset, ULONGEST len,
				       ULONGEST *xfered_len)
{
  scoped_restore save_ptid = make_scoped_restore (&inferior_ptid);
  /* Calling get_base_thread_from_ravenscar_task can read memory from
     the inferior.  However, that function is written to prefer our
     internal map, so it should not result in recursive calls in
     practice.  */
  inferior_ptid = get_base_thread_from_ravenscar_task (inferior_ptid);
  return beneath ()->xfer_partial (object, annex, readbuf, writebuf,
				   offset, len, xfered_len);
}

/* Observer on inferior_created: push ravenscar thread stratum if needed.  */

static void
ravenscar_inferior_created (inferior *inf)
{
  const char *err_msg;

  if (!ravenscar_task_support
      || gdbarch_ravenscar_ops (target_gdbarch ()) == NULL
      || !has_ravenscar_runtime ())
    return;

  err_msg = ada_get_tcb_types_info ();
  if (err_msg != NULL)
    {
      warning (_("%s. Task/thread support disabled."), err_msg);
      return;
    }

  ravenscar_thread_target *rtarget = new ravenscar_thread_target ();
  inf->push_target (target_ops_up (rtarget));
  thread_info *thr = rtarget->add_active_thread ();
  if (thr != nullptr)
    switch_to_thread (thr);
}

ptid_t
ravenscar_thread_target::get_ada_task_ptid (long lwp, ULONGEST thread)
{
  return ptid_t (m_base_ptid.pid (), 0, thread);
}

/* Command-list for the "set/show ravenscar" prefix command.  */
static struct cmd_list_element *set_ravenscar_list;
static struct cmd_list_element *show_ravenscar_list;

/* Implement the "show ravenscar task-switching" command.  */

static void
show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
				       struct cmd_list_element *c,
				       const char *value)
{
  if (ravenscar_task_support)
    gdb_printf (file, _("\
Support for Ravenscar task/thread switching is enabled\n"));
  else
    gdb_printf (file, _("\
Support for Ravenscar task/thread switching is disabled\n"));
}

/* Module startup initialization function, automagically called by
   init.c.  */

void _initialize_ravenscar ();
void
_initialize_ravenscar ()
{
  /* Notice when the inferior is created in order to push the
     ravenscar ops if needed.  */
  gdb::observers::inferior_created.attach (ravenscar_inferior_created,
					   "ravenscar-thread");

  add_setshow_prefix_cmd
    ("ravenscar", no_class,
     _("Prefix command for changing Ravenscar-specific settings."),
     _("Prefix command for showing Ravenscar-specific settings."),
     &set_ravenscar_list, &show_ravenscar_list,
     &setlist, &showlist);

  add_setshow_boolean_cmd ("task-switching", class_obscure,
			   &ravenscar_task_support, _("\
Enable or disable support for GNAT Ravenscar tasks."), _("\
Show whether support for GNAT Ravenscar tasks is enabled."),
			   _("\
Enable or disable support for task/thread switching with the GNAT\n\
Ravenscar run-time library for bareboard configuration."),
			   NULL, show_ravenscar_task_switching_command,
			   &set_ravenscar_list, &show_ravenscar_list);
}
