/* Displaced stepping related things.

   Copyright (C) 2020-2022 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 "displaced-stepping.h"

#include "cli/cli-cmds.h"
#include "command.h"
#include "gdbarch.h"
#include "gdbcore.h"
#include "gdbthread.h"
#include "inferior.h"
#include "regcache.h"
#include "target/target.h"

/* Default destructor for displaced_step_copy_insn_closure.  */

displaced_step_copy_insn_closure::~displaced_step_copy_insn_closure ()
  = default;

bool debug_displaced = false;

static void
show_debug_displaced (struct ui_file *file, int from_tty,
		      struct cmd_list_element *c, const char *value)
{
  gdb_printf (file, _("Displace stepping debugging is %s.\n"), value);
}

displaced_step_prepare_status
displaced_step_buffers::prepare (thread_info *thread, CORE_ADDR &displaced_pc)
{
  gdb_assert (!thread->displaced_step_state.in_progress ());

  /* Sanity check: the thread should not be using a buffer at this point.  */
  for (displaced_step_buffer &buf : m_buffers)
    gdb_assert (buf.current_thread != thread);

  regcache *regcache = get_thread_regcache (thread);
  const address_space *aspace = regcache->aspace ();
  gdbarch *arch = regcache->arch ();
  ULONGEST len = gdbarch_max_insn_length (arch);

  /* Search for an unused buffer.  */
  displaced_step_buffer *buffer = nullptr;
  displaced_step_prepare_status fail_status
    = DISPLACED_STEP_PREPARE_STATUS_CANT;

  for (displaced_step_buffer &candidate : m_buffers)
    {
      bool bp_in_range = breakpoint_in_range_p (aspace, candidate.addr, len);
      bool is_free = candidate.current_thread == nullptr;

      if (!bp_in_range)
	{
	  if (is_free)
	    {
	      buffer = &candidate;
	      break;
	    }
	  else
	    {
	      /* This buffer would be suitable, but it's used right now.  */
	      fail_status = DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
	    }
	}
      else
	{
	  /* There's a breakpoint set in the scratch pad location range
	     (which is usually around the entry point).  We'd either
	     install it before resuming, which would overwrite/corrupt the
	     scratch pad, or if it was already inserted, this displaced
	     step would overwrite it.  The latter is OK in the sense that
	     we already assume that no thread is going to execute the code
	     in the scratch pad range (after initial startup) anyway, but
	     the former is unacceptable.  Simply punt and fallback to
	     stepping over this breakpoint in-line.  */
	  displaced_debug_printf ("breakpoint set in displaced stepping "
				  "buffer at %s, can't use.",
				  paddress (arch, candidate.addr));
	}
    }

  if (buffer == nullptr)
    return fail_status;

  displaced_debug_printf ("selected buffer at %s",
			  paddress (arch, buffer->addr));

  /* Save the original PC of the thread.  */
  buffer->original_pc = regcache_read_pc (regcache);

  /* Return displaced step buffer address to caller.  */
  displaced_pc = buffer->addr;

  /* Save the original contents of the displaced stepping buffer.  */
  buffer->saved_copy.resize (len);

  int status = target_read_memory (buffer->addr,
				    buffer->saved_copy.data (), len);
  if (status != 0)
    throw_error (MEMORY_ERROR,
		 _("Error accessing memory address %s (%s) for "
		   "displaced-stepping scratch space."),
		 paddress (arch, buffer->addr), safe_strerror (status));

  displaced_debug_printf ("saved %s: %s",
			  paddress (arch, buffer->addr),
			  displaced_step_dump_bytes
			  (buffer->saved_copy.data (), len).c_str ());

  /* Save this in a local variable first, so it's released if code below
     throws.  */
  displaced_step_copy_insn_closure_up copy_insn_closure
    = gdbarch_displaced_step_copy_insn (arch, buffer->original_pc,
					buffer->addr, regcache);

  if (copy_insn_closure == nullptr)
    {
      /* The architecture doesn't know how or want to displaced step
	 this instruction or instruction sequence.  Fallback to
	 stepping over the breakpoint in-line.  */
      return DISPLACED_STEP_PREPARE_STATUS_CANT;
    }

  /* Resume execution at the copy.  */
  regcache_write_pc (regcache, buffer->addr);

  /* This marks the buffer as being in use.  */
  buffer->current_thread = thread;

  /* Save this, now that we know everything went fine.  */
  buffer->copy_insn_closure = std::move (copy_insn_closure);

  /* Tell infrun not to try preparing a displaced step again for this inferior if
     all buffers are taken.  */
  thread->inf->displaced_step_state.unavailable = true;
  for (const displaced_step_buffer &buf : m_buffers)
    {
      if (buf.current_thread == nullptr)
	{
	  thread->inf->displaced_step_state.unavailable = false;
	  break;
	}
    }

  return DISPLACED_STEP_PREPARE_STATUS_OK;
}

static void
write_memory_ptid (ptid_t ptid, CORE_ADDR memaddr,
		   const gdb_byte *myaddr, int len)
{
  scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);

  inferior_ptid = ptid;
  write_memory (memaddr, myaddr, len);
}

static bool
displaced_step_instruction_executed_successfully (gdbarch *arch,
						  gdb_signal signal)
{
  if (signal != GDB_SIGNAL_TRAP)
    return false;

  if (target_stopped_by_watchpoint ())
    {
      if (gdbarch_have_nonsteppable_watchpoint (arch)
	  || target_have_steppable_watchpoint ())
	return false;
    }

  return true;
}

displaced_step_finish_status
displaced_step_buffers::finish (gdbarch *arch, thread_info *thread,
				gdb_signal sig)
{
  gdb_assert (thread->displaced_step_state.in_progress ());

  /* Find the buffer this thread was using.  */
  displaced_step_buffer *buffer = nullptr;

  for (displaced_step_buffer &candidate : m_buffers)
    {
      if (candidate.current_thread == thread)
	{
	  buffer = &candidate;
	  break;
	}
    }

  gdb_assert (buffer != nullptr);

  /* Move this to a local variable so it's released in case something goes
     wrong.  */
  displaced_step_copy_insn_closure_up copy_insn_closure
    = std::move (buffer->copy_insn_closure);
  gdb_assert (copy_insn_closure != nullptr);

  /* Reset BUFFER->CURRENT_THREAD immediately to mark the buffer as available,
     in case something goes wrong below.  */
  buffer->current_thread = nullptr;

  /* Now that a buffer gets freed, tell infrun it can ask us to prepare a displaced
     step again for this inferior.  Do that here in case something goes wrong
     below.  */
  thread->inf->displaced_step_state.unavailable = false;

  ULONGEST len = gdbarch_max_insn_length (arch);

  /* Restore memory of the buffer.  */
  write_memory_ptid (thread->ptid, buffer->addr,
		     buffer->saved_copy.data (), len);

  displaced_debug_printf ("restored %s %s",
			  thread->ptid.to_string ().c_str (),
			  paddress (arch, buffer->addr));

  regcache *rc = get_thread_regcache (thread);

  bool instruction_executed_successfully
    = displaced_step_instruction_executed_successfully (arch, sig);

  if (instruction_executed_successfully)
    {
      gdbarch_displaced_step_fixup (arch, copy_insn_closure.get (),
				    buffer->original_pc,
				    buffer->addr, rc);
      return DISPLACED_STEP_FINISH_STATUS_OK;
    }
  else
    {
      /* Since the instruction didn't complete, all we can do is relocate the
	 PC.  */
      CORE_ADDR pc = regcache_read_pc (rc);
      pc = buffer->original_pc + (pc - buffer->addr);
      regcache_write_pc (rc, pc);
      return DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED;
    }
}

const displaced_step_copy_insn_closure *
displaced_step_buffers::copy_insn_closure_by_addr (CORE_ADDR addr)
{
  for (const displaced_step_buffer &buffer : m_buffers)
    {
      if (addr == buffer.addr)
	return buffer.copy_insn_closure.get ();
    }

  return nullptr;
}

void
displaced_step_buffers::restore_in_ptid (ptid_t ptid)
{
  for (const displaced_step_buffer &buffer : m_buffers)
    {
      if (buffer.current_thread == nullptr)
	continue;

      regcache *regcache = get_thread_regcache (buffer.current_thread);
      gdbarch *arch = regcache->arch ();
      ULONGEST len = gdbarch_max_insn_length (arch);

      write_memory_ptid (ptid, buffer.addr, buffer.saved_copy.data (), len);

      displaced_debug_printf ("restored in ptid %s %s",
			      ptid.to_string ().c_str (),
			      paddress (arch, buffer.addr));
    }
}

void _initialize_displaced_stepping ();
void
_initialize_displaced_stepping ()
{
  add_setshow_boolean_cmd ("displaced", class_maintenance,
			   &debug_displaced, _("\
Set displaced stepping debugging."), _("\
Show displaced stepping debugging."), _("\
When non-zero, displaced stepping specific debugging is enabled."),
			    NULL,
			    show_debug_displaced,
			    &setdebuglist, &showdebuglist);
}
