// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <inttypes.h>

#include "garnet/bin/zxdb/client/finish_thread_controller.h"
#include "garnet/bin/zxdb/client/frame.h"
#include "garnet/bin/zxdb/client/process.h"
#include "garnet/bin/zxdb/client/register.h"
#include "garnet/bin/zxdb/client/session.h"
#include "garnet/bin/zxdb/client/step_over_thread_controller.h"
#include "garnet/bin/zxdb/client/step_thread_controller.h"
#include "garnet/bin/zxdb/client/thread.h"
#include "garnet/bin/zxdb/client/until_thread_controller.h"
#include "garnet/bin/zxdb/common/err.h"
#include "garnet/bin/zxdb/console/command.h"
#include "garnet/bin/zxdb/console/command_utils.h"
#include "garnet/bin/zxdb/console/console.h"
#include "garnet/bin/zxdb/console/format_frame.h"
#include "garnet/bin/zxdb/console/format_register.h"
#include "garnet/bin/zxdb/console/format_table.h"
#include "garnet/bin/zxdb/console/format_value.h"
#include "garnet/bin/zxdb/console/format_value_process_context_impl.h"
#include "garnet/bin/zxdb/console/input_location_parser.h"
#include "garnet/bin/zxdb/console/output_buffer.h"
#include "garnet/bin/zxdb/console/verbs.h"
#include "garnet/bin/zxdb/expr/expr.h"
#include "garnet/bin/zxdb/expr/symbol_eval_context.h"
#include "garnet/bin/zxdb/symbols/code_block.h"
#include "garnet/bin/zxdb/symbols/function.h"
#include "garnet/bin/zxdb/symbols/location.h"
#include "garnet/bin/zxdb/symbols/variable.h"
#include "garnet/lib/debug_ipc/helper/message_loop.h"
#include "lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

constexpr int kStepIntoUnsymbolized = 1;
constexpr int kVerboseFormat = 2;
constexpr int kForceAllTypes = 3;
constexpr int kForceNumberChar = 4;
constexpr int kForceNumberSigned = 5;
constexpr int kForceNumberUnsigned = 6;
constexpr int kForceNumberHex = 7;
constexpr int kMaxArraySize = 8;

// If the system has at least one running process, returns true. If not,
// returns false and sets the err.
//
// When doing global things like System::Continue(), it will succeed if there
// are no running programs (it will successfully continue all 0 processes).
// This is confusing to the user so this function is used to check first.
bool VerifySystemHasRunningProcess(System* system, Err* err) {
  for (const Target* target : system->GetTargets()) {
    if (target->GetProcess())
      return true;
  }
  *err = Err("No processes are running.");
  return false;
}

// Populates the formatting options with the given command's switches.
Err GetFormatExprValueOptions(const Command& cmd,
                              FormatExprValueOptions* options) {
  // Verbosity.
  if (cmd.HasSwitch(kForceAllTypes))
    options->verbosity = FormatExprValueOptions::Verbosity::kAllTypes;
  else if (cmd.HasSwitch(kVerboseFormat))
    options->verbosity = FormatExprValueOptions::Verbosity::kMedium;
  else
    options->verbosity = FormatExprValueOptions::Verbosity::kMinimal;

  // Array size.
  if (cmd.HasSwitch(kMaxArraySize)) {
    int size = 0;
    Err err = StringToInt(cmd.GetSwitchValue(kMaxArraySize), &size);
    if (err.has_error())
      return err;
    options->max_array_size = static_cast<uint32_t>(size);
  }

  // Mapping from command-line parameter to format enum.
  constexpr size_t kFormatCount = 4;
  static constexpr std::pair<int, FormatExprValueOptions::NumFormat>
      kFormats[kFormatCount] = {
          {kForceNumberChar, FormatExprValueOptions::NumFormat::kChar},
          {kForceNumberUnsigned, FormatExprValueOptions::NumFormat::kUnsigned},
          {kForceNumberSigned, FormatExprValueOptions::NumFormat::kSigned},
          {kForceNumberHex, FormatExprValueOptions::NumFormat::kHex}};

  int num_type_overrides = 0;
  for (const auto& cur : kFormats) {
    if (cmd.HasSwitch(cur.first)) {
      num_type_overrides++;
      options->num_format = cur.second;
    }
  }

  if (num_type_overrides > 1)
    return Err("More than one type override (-c, -d, -u, -x) specified.");
  return Err();
}

#define FORMAT_VALUE_SWITCHES                                                 \
  "  --max-array=<number>\n"                                                  \
  "      Specifies the maximum array size to print. By default this is\n"     \
  "      256. Specifying large values will slow things down and make the\n"   \
  "      output harder to read, but the default is sometimes insufficient.\n" \
  "      This also applies to strings.\n"                                     \
  "\n"                                                                        \
  "  -t\n"                                                                    \
  "  --types\n"                                                               \
  "      Force type printing on. The type of every value printed will be\n"   \
  "      explicitly shown. Implies -v.\n"                                     \
  "\n"                                                                        \
  "  -v\n"                                                                    \
  "  --verbose\n"                                                             \
  "      Don't elide type names. Show reference addresses and pointer\n"      \
  "      types.\n"                                                            \
  "\n"                                                                        \
  "Number formatting options\n"                                               \
  "\n"                                                                        \
  "  Force numeric values to be of specific types with these options:\n"      \
  "\n"                                                                        \
  "  -c  Character\n"                                                         \
  "  -d  Signed decimal\n"                                                    \
  "  -u  Unsigned decimal\n"                                                  \
  "  -x  Unsigned hexadecimal\n"

// backtrace -------------------------------------------------------------------

const char kBacktraceShortHelp[] = "backtrace / bt: Print a backtrace.";
const char kBacktraceHelp[] =
    R"(backtrace / bt

  Prints a backtrace of the selected thread. This is an alias for "frame -v".

  To see less information, use "frame" or just "f".

Arguments

  -t
  --types
      Include all type information for function parameters.

Examples

  t 2 bt
  thread 2 backtrace
)";
Err DoBacktrace(ConsoleContext* context, const Command& cmd) {
  Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread});
  if (err.has_error())
    return err;

  if (!cmd.thread())
    return Err("There is no thread to have frames.");

  // TODO(brettw) this should share formatting options and parsing with the
  // printing commands.
  bool show_params = cmd.HasSwitch(kForceAllTypes);
  OutputFrameList(cmd.thread(), show_params, true);
  return Err();
}

// continue --------------------------------------------------------------------

const char kContinueShortHelp[] =
    "continue / c: Continue a suspended thread or process.";
const char kContinueHelp[] =
    R"(continue / c

  When a thread is stopped at an exception or a breakpoint, "continue" will
  continue execution.

  See "pause" to stop a running thread or process.

  The behavior will depend upon the context specified.

  - By itself, "continue" will continue all threads of all processes that are
    currently stopped.

  - When a process is specified ("process 2 continue" for an explicit process
    or "process continue" for the current process), only the threads in that
    process will be continued. Other debugged processes currently stopped will
    remain so.

  - When a thread is specified ("thread 1 continue" for an explicit thread
    or "thread continue" for the current thread), only that thread will be
    continued. Other threads in that process and other processes currently
    stopped will remain so.

  TODO(brettw) it might be nice to have a --other flag that would continue
  all threads other than the specified one (which the user might want to step
  while everything else is going).

Examples

  c
  continue
      Continue all processes and threads.

  pr c
  process continue
  process 4 continue
      Continue all threads of a process (the current process is implicit if
      no process index is specified).

  t c
  thread continue
  pr 2 t 4 c
  process 2 thread 4 continue
      Continue only one thread (the current process and thread are implicit
      if no index is specified).
)";
Err DoContinue(ConsoleContext* context, const Command& cmd) {
  Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread});
  if (err.has_error())
    return err;

  if (cmd.HasNoun(Noun::kThread)) {
    cmd.thread()->Continue();
  } else if (cmd.HasNoun(Noun::kProcess)) {
    Process* process = cmd.target()->GetProcess();
    if (!process)
      return Err("Process not running, can't continue.");
    process->Continue();
  } else {
    if (!VerifySystemHasRunningProcess(&context->session()->system(), &err))
      return err;
    context->session()->system().Continue();
  }

  return Err();
}

// finish ----------------------------------------------------------------------

const char kFinishShortHelp[] =
    "finish / fi: Finish execution of a stack frame.";
const char kFinishHelp[] =
    R"(finish / fi

  Alias: "fi"

  Resume thread execution until the selected stack frame returns. This means
  that the current function call will execute normally until it finished.

  See also "until".

Examples

  fi
  finish
      Exit the currently selected stack frame (see "frame").

  pr 1 t 4 fi
  process 1 thead 4 finish
      Applies "finish" to process 1, thread 4.

  f 2 fi
  frame 2 finish
      Exit frame 2, leaving program execution in what was frame 3. Try also
      "frame 3 until" which will do the same thing when the function is not
      recursive.
)";
Err DoFinish(ConsoleContext* context, const Command& cmd) {
  // This command allows "frame" which AssertStoppedThreadCommand doesn't,
  // so pass "false" to disabled noun checking and manually check ourselves.
  Err err = AssertStoppedThreadCommand(context, cmd, false, "finish");
  if (err.has_error())
    return err;
  err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread, Noun::kFrame});
  if (err.has_error())
    return err;

  auto controller = std::make_unique<FinishThreadController>(
      FinishThreadController::FromFrame(), cmd.frame());
  cmd.thread()->ContinueWith(std::move(controller), [](const Err& err) {
    if (err.has_error())
      Console::get()->Output(err);
  });
  return Err();
}

// jump ------------------------------------------------------------------------

const char kJumpShortHelp[] =
    "jump / jmp: Set the instruction pointer to a different address.";
const char kJumpHelp[] =
    R"(jump <location>

  Alias: "jmp"

  Sets the instruction pointer of the thread to the given address. It does not
  continue execution. You can "step" or "continue" from the new location.

  You are responsible for what this means semantically since one can't
  generally change the instruction flow and expect things to work.

Location arguments

)" LOCATION_ARG_HELP("jump");
Err DoJump(ConsoleContext* context, const Command& cmd) {
  Err err = AssertStoppedThreadCommand(context, cmd, false, "jump");
  if (err.has_error())
    return err;

  if (cmd.args().size() != 1)
    return Err("The 'jump' command requires one argument for the location.");

  InputLocation input_location;
  err = ParseInputLocation(cmd.frame(), cmd.args()[0], &input_location);
  if (err.has_error())
    return err;

  Location location;
  err = ResolveUniqueInputLocation(cmd.target()->GetProcess()->GetSymbols(),
                                   input_location, true, &location);
  if (err.has_error())
    return err;

  cmd.thread()->JumpTo(
      location.address(),
      [thread = cmd.thread()->GetWeakPtr()](const Err& err) {
        Console* console = Console::get();
        if (err.has_error()) {
          console->Output(err);
        } else if (thread) {
          // Reset the current stack frame to the top to reflect the location
          // the user has just jumped to.
          console->context().SetActiveFrameIdForThread(thread.get(), 0);

          // Tell the user where they are.
          console->context().OutputThreadContext(
              thread.get(), debug_ipc::NotifyException::Type::kNone, {});
        }
      });

  return Err();
}

// locals ----------------------------------------------------------------------

const char kLocalsShortHelp[] =
    "locals: Print local variables and function args.";
const char kLocalsHelp[] =
    R"(locals

  Prints all local variables and the current function's arguments. By default
  it will print the variables for the currently selected stack frame.

  You can override the stack frame with the "frame" noun to get the locals
  for any specific stack frame of thread.

Arguments

)" FORMAT_VALUE_SWITCHES
    R"(
Examples

  locals
      Prints locals and args for the current stack frame.

  f 4 locals
  frame 4 locals
  thread 2 frame 3 locals
      Prints locals for a specific stack frame.

  f 4 locals -t
      Prints locals with types.
)";
Err DoLocals(ConsoleContext* context, const Command& cmd) {
  // Don't have AssertStoppedThreadCommand check nouns because we additionally
  // allow "frame", which we manually validate below.
  Err err = AssertStoppedThreadCommand(context, cmd, false, "locals");
  if (err.has_error())
    return err;
  err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread, Noun::kFrame});
  if (err.has_error())
    return err;
  if (!cmd.frame())
    return Err("There isn't a current frame to read locals from.");

  const Location& location = cmd.frame()->GetLocation();
  if (!location.symbol())
    return Err("There is no symbol information for the frame.");
  const Function* function = location.symbol().Get()->AsFunction();
  if (!function)
    return Err("Symbols are corrupt.");

  // Find the innermost lexical block for the current IP.
  const CodeBlock* block = function->GetMostSpecificChild(
      location.symbol_context(), location.address());
  if (!block)
    return Err("There is no symbol information for the current IP.");

  // Walk upward in the hierarchy to collect local variables until hitting a
  // function. Using the map allows collecting only the innermost version of
  // a given name, and sorts them as we go.
  std::map<std::string, const Variable*> vars;
  while (block) {
    for (const auto& lazy_var : block->variables()) {
      const Variable* var = lazy_var.Get()->AsVariable();
      if (!var)
        continue;  // Symbols are corrupt.
      const std::string& name = var->GetAssignedName();
      if (vars.find(name) == vars.end())
        vars[name] = var;  // New one.
    }

    if (block == function)
      break;
    block = block->parent().Get()->AsCodeBlock();
  }

  // Add function parameters. Don't overwrite existing names in case of
  // duplicates to duplicate the shadowing rules of the language.
  for (const auto& param : function->parameters()) {
    const Variable* var = param.Get()->AsVariable();
    if (!var)
      continue;  // Symbols are corrupt.
    const std::string& name = var->GetAssignedName();
    if (vars.find(name) == vars.end())
      vars[name] = var;  // New one.
  }

  if (vars.empty()) {
    Console::get()->Output("No local variables in scope.");
    return Err();
  }

  FormatExprValueOptions options;
  err = GetFormatExprValueOptions(cmd, &options);
  if (err.has_error())
    return err;

  auto helper = fxl::MakeRefCounted<FormatValue>(
      std::make_unique<FormatValueProcessContextImpl>(cmd.target()));
  for (const auto& pair : vars) {
    helper->AppendVariable(location.symbol_context(),
                           cmd.frame()->GetSymbolDataProvider(), pair.second,
                           options);
    helper->Append(OutputBuffer("\n"));
  }
  helper->Complete(
      [helper](OutputBuffer out) { Console::get()->Output(std::move(out)); });
  return Err();
}

// next ------------------------------------------------------------------------

const char kNextShortHelp[] = "next / n: Single-step over one source line.";
const char kNextHelp[] =
    R"(next / n

  When a thread is stopped, "next" will execute one source line, stepping over
  subroutine call instructions, and stop the thread again. If the thread is
  running it will issue an error.

  By default, "next" will operate on the current thread. If a thread context
  is given, the specified thread will be single-stepped. You can't single-step
  a process.

  See also "step" to step into subroutine calls or "nexti" to step machine
  instructions.

Examples

  n
  next
      Step the current thread.

  t 2 n
  thread 2 next
      Steps thread 2 in the current process.

  pr 3 n
  process 3 next
      Steps the current thread in process 3 (regardless of which process is
      the current process).

  pr 3 t 2 n
  process 3 thread 2 next
      Steps thread 2 in process 3.
)";
Err DoNext(ConsoleContext* context, const Command& cmd) {
  Err err = AssertStoppedThreadCommand(context, cmd, true, "next");
  if (err.has_error())
    return err;

  auto controller =
      std::make_unique<StepOverThreadController>(StepMode::kSourceLine);
  cmd.thread()->ContinueWith(std::move(controller), [](const Err& err) {
    if (err.has_error())
      Console::get()->Output(err);
  });
  return Err();
}

// nexti -----------------------------------------------------------------------

const char kNextiShortHelp[] =
    "nexti / ni: Single-step over one machine instruction.";
const char kNextiHelp[] =
    R"(nexti / ni

  When a thread is stopped, "nexti" will execute one machine instruction,
  stepping over subroutine call instructions, and stop the thread again.
  If the thread is running it will issue an error.

  Only machine call instructions ("call" on x86 and "bl" on ARM) will be
  stepped over with this command. This is not the only way to do a subroutine
  call, as code can manually set up a call frame and jump. These jumps will not
  count as a call and this command will step into the resulting frame.

  By default, "nexti" will operate on the current thread. If a thread context
  is given, the specified thread will be single-stepped. You can't single-step
  a process.

  See also "stepi" to step into subroutine calls.

Examples

  ni
  nexti
      Step the current thread.

  t 2 ni
  thread 2 nexti
      Steps thread 2 in the current process.

  pr 3 ni
  process 3 nexti
      Steps the current thread in process 3 (regardless of which process is
      the current process).

  pr 3 t 2 ni
  process 3 thread 2 nexti
      Steps thread 2 in process 3.
)";
Err DoNexti(ConsoleContext* context, const Command& cmd) {
  Err err = AssertStoppedThreadCommand(context, cmd, true, "nexti");
  if (err.has_error())
    return err;

  auto controller =
      std::make_unique<StepOverThreadController>(StepMode::kInstruction);
  cmd.thread()->ContinueWith(std::move(controller), [](const Err& err) {
    if (err.has_error())
      Console::get()->Output(err);
  });
  return Err();
}

// pause -----------------------------------------------------------------------

const char kPauseShortHelp[] = "pause / pa: Pause a thread or process.";
const char kPauseHelp[] =
    R"(pause / pa

  When a thread or process is running, "pause" will stop execution so state
  can be inspected or the thread single-stepped.

  See "continue" to resume a paused thread or process.

  The behavior will depend upon the context specified.

  - By itself, "pause" will pause all threads of all processes that are
    currently running.

  - When a process is specified ("process 2 pause" for an explicit process
    or "process pause" for the current process), only the threads in that
    process will be paused. Other debugged processes currently running will
    remain so.

  - When a thread is specified ("thread 1 pause" for an explicit thread
    or "thread pause" for the current thread), only that thread will be
    paused. Other threads in that process and other processes currently
    running will remain so.

  TODO(brettw) it might be nice to have a --other flag that would pause
  all threads other than the specified one.

Examples

  pa
  pause
      Pause all processes and threads.

  pr pa
  process pause
  process 4 pause
      Pause all threads of a process (the current process is implicit if
      no process index is specified).

  t pa
  thread pause
  pr 2 t 4 pa
  process 2 thread 4 pause
      Pause only one thread (the current process and thread are implicit
      if no index is specified).
)";
Err DoPause(ConsoleContext* context, const Command& cmd) {
  Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread});
  if (err.has_error())
    return err;

  if (cmd.HasNoun(Noun::kThread)) {
    cmd.thread()->Pause();
  } else if (cmd.HasNoun(Noun::kProcess)) {
    Process* process = cmd.target()->GetProcess();
    if (!process)
      return Err("Process not running, can't pause.");
    process->Pause();
  } else {
    if (!VerifySystemHasRunningProcess(&context->session()->system(), &err))
      return err;
    context->session()->system().Pause();
  }

  return Err();
}

// print -----------------------------------------------------------------------

const char kPrintShortHelp[] = "print / p: Print a variable or expression.";
const char kPrintHelp[] =
    R"(print <expression>

  Alias: p

  Evaluates a simple expression or variable name and prints the result.

  The expression is evaluated by default in the currently selected thread and
  stack frame. You can override this with "frame <x> print ...".

Arguments

)" FORMAT_VALUE_SWITCHES
    R"(
Expressions

  The expression evaluator understands the following C/C++ things:

    - Identifiers

    - Struct and class member access: . ->

    - Array access (for native arrays): [ <expression> ]

    - Create or dereference pointers: & *

    - Precedence: ( <expression> )

  Not supported: function calls, overloaded operators, casting.

Examples

  p foo
  print foo
      Print a variable

  p *foo->bar
  print &foo.bar[2]
      Deal with structs and arrays.

  f 2 p -t foo
  frame 2 print -t foo
  thread 1 frame 2 print -t foo
      Print a variable with types in the context of a specific stack frame.
)";
Err DoPrint(ConsoleContext* context, const Command& cmd) {
  Err err = AssertStoppedThreadCommand(context, cmd, false, "print");
  if (err.has_error())
    return err;
  err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread, Noun::kFrame});
  if (err.has_error())
    return err;
  if (!cmd.frame())
    return Err("There isn't a current frame for printing context.");

  // This takes one expression that may have spaces, so concatenate everything
  // the command parser has split apart back into one thing.
  //
  // If we run into limitations of this, we should add a "don't parse the args"
  // flag to the command record.
  std::string expr;
  for (const auto& cur : cmd.args()) {
    if (!expr.empty())
      expr.push_back(' ');
    expr += cur;
  }

  if (expr.empty())
    return Err("Usage: print <expression>\nSee \"help print\" for more.");

  FormatExprValueOptions options;
  err = GetFormatExprValueOptions(cmd, &options);
  if (err.has_error())
    return err;

  auto data_provider = cmd.frame()->GetSymbolDataProvider();
  auto formatter = fxl::MakeRefCounted<FormatValue>(
      std::make_unique<FormatValueProcessContextImpl>(cmd.target()));

  EvalExpression(
      expr, cmd.frame()->GetExprEvalContext(),
      [formatter, options, data_provider](const Err& err, ExprValue value) {
        if (err.has_error()) {
          Console::get()->Output(err);
        } else {
          formatter->AppendValue(data_provider, value, options);
          // Bind the formatter to keep it in scope across this
          // async call.
          formatter->Complete([formatter](OutputBuffer out) {
            Console::get()->Output(std::move(out));
          });
        }
      });

  return Err();
}

// step ------------------------------------------------------------------------

const char kStepShortHelp[] =
    "step / s: Step one source line, going into subroutines.";
const char kStepHelp[] =
    R"(step [ <function-fragment> ]

  Alias: "s"

  When a thread is stopped, "step" will execute one source line and stop the
  thread again. This will follow execution into subroutines. If the thread is
  running it will issue an error.

  By default, "step" will single-step the current thread. If a thread context
  is given, the specified thread will be stepped. You can't step a process.
  Other threads in the process will be unchanged so will remain running or
  stopped.

  See also "stepi".

Stepping into specific functions

  If provided, the parameter will specify a specific function call to step
  into.

  The string will be matched against the symbol names of subroutines called
  directly from the current line. Execution will stop if the function name
  contains this fragment, and automatically complete that function call
  otherwise.

Arguments

  --unsymbolized | -u
      Force stepping into functions with no symbols. Normally "step" will
      skip over library calls or thunks with no symbols. This option allows
      one to step into these unsymbolized calls.

Examples

  s
  step
      Step the current thread.

  t 2 s
  thread 2 step
      Steps thread 2 in the current process.

  s Pri
      Steps into a function with the substring "Pri" anywhere in its name. If
      you have a complex line such as:

        Print(GetFoo(), std::string("bar");

      The "s Pri" command will step over the GetFoo() and std::string() calls,
      and leave execution at the beginning of the "Print" subroutine.
)";
Err DoStep(ConsoleContext* context, const Command& cmd) {
  Err err = AssertStoppedThreadCommand(context, cmd, true, "step");
  if (err.has_error())
    return err;

  // All controllers do this on completion.
  auto completion = [](const Err& err) {
    if (err.has_error())
      Console::get()->Output(err);
  };

  if (cmd.args().empty()) {
    // Step over a single line.
    auto controller =
        std::make_unique<StepThreadController>(StepMode::kSourceLine);
    controller->set_stop_on_no_symbols(cmd.HasSwitch(kStepIntoUnsymbolized));
    cmd.thread()->ContinueWith(std::move(controller), std::move(completion));
  } else if (cmd.args().size() == 1) {
    // Step into a specific named subroutine. This uses the "step over"
    // controller with a special condition.
    if (cmd.HasSwitch(kStepIntoUnsymbolized)) {
      return Err(
          "The --unsymbolized switch is not compatible with a named "
          "subroutine to step\ninto.");
    }
    auto controller =
        std::make_unique<StepOverThreadController>(StepMode::kSourceLine);
    controller->set_subframe_should_stop_callback(
        [substr = cmd.args()[0]](const Frame* frame)->bool {
          const Symbol* symbol = frame->GetLocation().symbol().Get();
          if (!symbol)
            return false;  // Unsymbolized location, continue.
          return symbol->GetFullName().find(substr) != std::string::npos;
        });
    cmd.thread()->ContinueWith(std::move(controller), std::move(completion));
  } else {
    return Err("Too many arguments for 'step'.");
  }

  return Err();
}

// stepi -----------------------------------------------------------------------

const char kStepiShortHelp[] =
    "stepi / si: Single-step a thread one machine instruction.";
const char kStepiHelp[] =
    R"(stepi / si

  When a thread is stopped, "stepi" will execute one machine instruction and
  stop the thread again. If the thread is running it will issue an error.

  By default, "stepi" will single-step the current thread. If a thread context
  is given, the specified thread will be single-stepped. You can't single-step
  a process.

  See also "nexti" to step over subroutine calls.

Examples

  si
  stepi
      Step the current thread.

  t 2 si
  thread 2 stepi
      Steps thread 2 in the current process.

  pr 3 si
  process 3 stepi
      Steps the current thread in process 3 (regardless of which process is
      the current process).

  pr 3 t 2 si
  process 3 thread 2 stepi
      Steps thread 2 in process 3.
)";
Err DoStepi(ConsoleContext* context, const Command& cmd) {
  Err err = AssertStoppedThreadCommand(context, cmd, true, "stepi");
  if (err.has_error())
    return err;

  cmd.thread()->StepInstruction();
  return Err();
}

// regs ------------------------------------------------------------------------

using debug_ipc::RegisterCategory;

const char kRegsShortHelp[] =
    "regs / rg: Show the current registers for a thread.";
const char kRegsHelp[] =
    R"(regs [(--category|-c)=<category>] [(--extended|-e)] [<regexp>]

  Alias: "rg"

  Shows the current registers for a thread. The thread must be stopped.
  By default the general purpose registers will be shown, but more can be
  configures through switches.

  NOTE: The values are displayed in the endianess of the target architecture.
        The interpretation of which bits are the MSB will vary across different
        endianess.

Arguments

  --category=<category> | -c <category>
      Which categories if registers to show.
      The following options can be set:

      - general: Show general purpose registers.
      - fp: Show floating point registers.
      - vector: Show vector registers.
      - debug: Show debug registers (eg. The DR registers on x86).
      - all: Show all the categories available.

      NOTE: not all categories exist within all architectures. For example,
            ARM64's fp category doesn't have any registers.

  --extended | -e
      Enables more verbose flag decoding. This will enable more information
      that is not normally useful for everyday debugging. This includes
      information such as the system level flags within the RFLAGS register for
      x86.

  <regexp>
      Case insensitive regular expression. Any register that matches will be
      shown. Uses POSIX Basic Regular Expression syntax. If not specified, it
      will match all registers.

Examples

  regs
  thread 4 regs --category=vector
  process 2 thread 1 regs -c all v*
)";

// Switches
constexpr int kRegsCategoriesSwitch = 1;
constexpr int kRegsExtendedSwitch = 2;

void OnRegsComplete(const Err& cmd_err, const RegisterSet& register_set,
                    FormatRegisterOptions options) {
  Console* console = Console::get();
  if (cmd_err.has_error()) {
    console->Output(cmd_err);
    return;
  }

  options.arch = register_set.arch();

  FilteredRegisterSet filtered_set;
  Err err = FilterRegisters(options, register_set, &filtered_set);
  if (!err.ok()) {
    console->Output(err);
    return;
  }

  OutputBuffer out;
  err = FormatRegisters(options, filtered_set, &out);
  if (!err.ok()) {
    console->Output(err);
    return;
  }
  console->Output(out);
}

Err DoRegs(ConsoleContext* context, const Command& cmd) {
  Err err = AssertStoppedThreadCommand(context, cmd, true, "regs");
  if (err.has_error())
    return err;

  // When empty, we print all the registers.
  std::string regex_filter;
  if (!cmd.args().empty()) {
    // We expect only one name.
    if (cmd.args().size() > 1u) {
      return Err("Only one register regular expression filter expected.");
    }
    regex_filter = cmd.args().front();
  }

  // General purpose are the default.
  std::vector<RegisterCategory::Type> cats_to_show = {
      RegisterCategory::Type::kGeneral};
  if (cmd.HasSwitch(kRegsCategoriesSwitch)) {
    auto option = cmd.GetSwitchValue(kRegsCategoriesSwitch);
    if (option == "all") {
      cats_to_show = {
          debug_ipc::RegisterCategory::Type::kGeneral,
          debug_ipc::RegisterCategory::Type::kFP,
          debug_ipc::RegisterCategory::Type::kVector,
          debug_ipc::RegisterCategory::Type::kDebug,
      };
    } else if (option == "general") {
      cats_to_show = {RegisterCategory::Type::kGeneral};
    } else if (option == "fp") {
      cats_to_show = {RegisterCategory::Type::kFP};
    } else if (option == "vector") {
      cats_to_show = {RegisterCategory::Type::kVector};
    } else if (option == "debug") {
      cats_to_show = {RegisterCategory::Type::kDebug};
    } else {
      return Err(fxl::StringPrintf("Unknown category: %s", option.c_str()));
    }
  }

  // Parse the switches
  FormatRegisterOptions options;
  options.categories = cats_to_show;
  options.extended = cmd.HasSwitch(kRegsExtendedSwitch);
  options.filter_regexp = std::move(regex_filter);

  // We pass the given register name to the callback
  auto regs_cb = [options = std::move(options)](const Err& err,
                                                const RegisterSet& registers) {
    OnRegsComplete(err, registers, std::move(options));
  };

  cmd.thread()->ReadRegisters(std::move(cats_to_show), regs_cb);
  return Err();
}

// until -----------------------------------------------------------------------

const char kUntilShortHelp[] =
    "until / u: Runs a thread until a location is reached.";
const char kUntilHelp[] =
    R"(until <location>

  Alias: "u"

  Continues execution of a thread or a process until a given location is
  reached. You could think of this command as setting an implicit one-shot
  breakpoint at the given location and continuing execution.

  Normally this operation will apply only to the current thread. To apply to
  all threads in a process, use "process until" (see the examples below).

  See also "finish".

Location arguments

  Current frame's address (no input)
    until

)" LOCATION_ARG_HELP("until")
        R"(
Examples

  u
  until
      Runs until the current frame's location is hit again. This can be useful
      if the current code is called in a loop to advance to the next iteration
      of the current code.

  f 1 u
  frame 1 until
      Runs until the given frame's location is hit. Since frame 1 is
      always the current function's calling frame, this command will normally
      stop when the current function returns. The exception is if the code
      in the calling function is called recursively from the current location,
      in which case the next invocation will stop ("until" does not match
      stack frames on break). See "finish" for a stack-aware version.

  u 24
  until 24
      Runs the current thread until line 24 of the current frame's file.

  until foo.cc:24
      Runs the current thread until the given file/line is reached.

  thread 2 until 24
  process 1 thread 2 until 24
      Runs the specified thread until line 24 is reached. When no filename is
      given, the specified thread's currently selected frame will be used.

  u MyClass::MyFunc
  until MyClass::MyFunc
      Runs the current thread until the given function is called.

  pr u MyClass::MyFunc
  process until MyClass::MyFunc
      Continues all threads of the current process, stopping the next time any
      of them call the function.
)";
Err DoUntil(ConsoleContext* context, const Command& cmd) {
  Err err;

  // Decode the location.
  //
  // The validation on this is a bit tricky. Most uses apply to the current
  // thread and take some implicit information from the current frame (which
  // requires the thread be stopped). But when doing a process-wide one, don't
  // require a currently stopped thread unless it's required to compute the
  // location.
  InputLocation location;
  if (cmd.args().empty()) {
    // No args means use the current location.
    if (!cmd.frame()) {
      return Err(ErrType::kInput,
                 "There isn't a current frame to take the location from.");
    }
    location = InputLocation(cmd.frame()->GetAddress());
  } else if (cmd.args().size() == 1) {
    // One arg = normal location (ParseInputLocation can handle null frames).
    Err err = ParseInputLocation(cmd.frame(), cmd.args()[0], &location);
    if (err.has_error())
      return err;
  } else {
    return Err(ErrType::kInput,
               "Expecting zero or one arg for the location.\n"
               "Formats: <function>, <file>:<line#>, <line#>, or *<address>");
  }

  auto callback = [](const Err& err) {
    if (err.has_error())
      Console::get()->Output(err);
  };

  // Dispatch the request.
  if (cmd.HasNoun(Noun::kProcess) && !cmd.HasNoun(Noun::kThread) &&
      !cmd.HasNoun(Noun::kFrame)) {
    // Process-wide ("process until ...").
    err = AssertRunningTarget(context, "until", cmd.target());
    if (err.has_error())
      return err;
    cmd.target()->GetProcess()->ContinueUntil(location, callback);
  } else {
    // Thread-specific.
    err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread, Noun::kFrame});
    if (err.has_error())
      return err;

    err = AssertStoppedThreadCommand(context, cmd, false, "until");
    if (err.has_error())
      return err;

    auto controller = std::make_unique<UntilThreadController>(location);
    cmd.thread()->ContinueWith(std::move(controller), [](const Err& err) {
      if (err.has_error())
        Console::get()->Output(err);
    });
  }
  return Err();
}

}  // namespace

void AppendThreadVerbs(std::map<Verb, VerbRecord>* verbs) {
  // Shared options for value printing.
  SwitchRecord force_types(kForceAllTypes, false, "types", 't');
  const std::vector<SwitchRecord> format_switches{
      force_types,
      SwitchRecord(kVerboseFormat, false, "verbose", 'v'),
      SwitchRecord(kForceNumberChar, false, "", 'c'),
      SwitchRecord(kForceNumberSigned, false, "", 'd'),
      SwitchRecord(kForceNumberUnsigned, false, "", 'u'),
      SwitchRecord(kForceNumberHex, false, "", 'x'),
      SwitchRecord(kMaxArraySize, true, "max-array")};

  VerbRecord backtrace(&DoBacktrace, {"backtrace", "bt"}, kBacktraceShortHelp,
                       kBacktraceHelp, CommandGroup::kQuery);
  backtrace.switches = {force_types};
  (*verbs)[Verb::kBacktrace] = std::move(backtrace);

  (*verbs)[Verb::kContinue] =
      VerbRecord(&DoContinue, {"continue", "cont", "c"}, kContinueShortHelp,
                 kContinueHelp, CommandGroup::kStep, SourceAffinity::kSource);
  (*verbs)[Verb::kFinish] =
      VerbRecord(&DoFinish, {"finish", "fi"}, kFinishShortHelp, kFinishHelp,
                 CommandGroup::kStep);
  (*verbs)[Verb::kJump] = VerbRecord(&DoJump, {"jump", "jmp"}, kJumpShortHelp,
                                     kJumpHelp, CommandGroup::kStep);

  // locals
  VerbRecord locals(&DoLocals, {"locals"}, kLocalsShortHelp, kLocalsHelp,
                    CommandGroup::kQuery);
  locals.switches = format_switches;
  (*verbs)[Verb::kLocals] = std::move(locals);

  (*verbs)[Verb::kNext] =
      VerbRecord(&DoNext, {"next", "n"}, kNextShortHelp, kNextHelp,
                 CommandGroup::kStep, SourceAffinity::kSource);
  (*verbs)[Verb::kNexti] =
      VerbRecord(&DoNexti, {"nexti", "ni"}, kNextiShortHelp, kNextiHelp,
                 CommandGroup::kAssembly, SourceAffinity::kAssembly);
  (*verbs)[Verb::kPause] =
      VerbRecord(&DoPause, {"pause", "pa"}, kPauseShortHelp, kPauseHelp,
                 CommandGroup::kProcess);

  // print
  VerbRecord print(&DoPrint, {"print", "p"}, kPrintShortHelp, kPrintHelp,
                   CommandGroup::kQuery);
  print.switches = format_switches;
  (*verbs)[Verb::kPrint] = std::move(print);

  // regs
  SwitchRecord regs_categories(kRegsCategoriesSwitch, true, "category", 'c');
  SwitchRecord regs_extended(kRegsExtendedSwitch, false, "extended", 'e');
  VerbRecord regs(&DoRegs, {"regs", "rg"}, kRegsShortHelp, kRegsHelp,
                  CommandGroup::kAssembly);
  regs.switches.push_back(std::move(regs_categories));
  regs.switches.push_back(std::move(regs_extended));
  (*verbs)[Verb::kRegs] = std::move(regs);

  // step
  SwitchRecord step_force(kStepIntoUnsymbolized, false, "unsymbolized", 'u');
  VerbRecord step(&DoStep, {"step", "s"}, kStepShortHelp, kStepHelp,
                  CommandGroup::kStep, SourceAffinity::kSource);
  step.switches.push_back(step_force);
  (*verbs)[Verb::kStep] = std::move(step);

  (*verbs)[Verb::kStepi] =
      VerbRecord(&DoStepi, {"stepi", "si"}, kStepiShortHelp, kStepiHelp,
                 CommandGroup::kAssembly, SourceAffinity::kAssembly);
  (*verbs)[Verb::kUntil] = VerbRecord(&DoUntil, {"until", "u"}, kUntilShortHelp,
                                      kUntilHelp, CommandGroup::kStep);
}

}  // namespace zxdb
