//===-- CommandObjectDisassemble.cpp --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "CommandObjectDisassemble.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"

static constexpr unsigned default_disasm_byte_size = 32;
static constexpr unsigned default_disasm_num_ins = 4;

using namespace lldb;
using namespace lldb_private;

#define LLDB_OPTIONS_disassemble
#include "CommandOptions.inc"

CommandObjectDisassemble::CommandOptions::CommandOptions() {
  OptionParsingStarting(nullptr);
}

CommandObjectDisassemble::CommandOptions::~CommandOptions() = default;

Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
    uint32_t option_idx, llvm::StringRef option_arg,
    ExecutionContext *execution_context) {
  Status error;

  const int short_option = m_getopt_table[option_idx].val;

  switch (short_option) {
  case 'm':
    show_mixed = true;
    break;

  case 'C':
    if (option_arg.getAsInteger(0, num_lines_context))
      error = Status::FromErrorStringWithFormat(
          "invalid num context lines string: \"%s\"", option_arg.str().c_str());
    break;

  case 'c':
    if (option_arg.getAsInteger(0, num_instructions))
      error = Status::FromErrorStringWithFormat(
          "invalid num of instructions string: \"%s\"",
          option_arg.str().c_str());
    break;

  case 'b':
    show_bytes = true;
    break;

  case 'k':
    show_control_flow_kind = true;
    break;

  case 's': {
    start_addr = OptionArgParser::ToAddress(execution_context, option_arg,
                                            LLDB_INVALID_ADDRESS, &error);
    if (start_addr != LLDB_INVALID_ADDRESS)
      some_location_specified = true;
  } break;
  case 'e': {
    end_addr = OptionArgParser::ToAddress(execution_context, option_arg,
                                          LLDB_INVALID_ADDRESS, &error);
    if (end_addr != LLDB_INVALID_ADDRESS)
      some_location_specified = true;
  } break;

  case 'n':
    func_name.assign(std::string(option_arg));
    some_location_specified = true;
    break;

  case 'p':
    at_pc = true;
    some_location_specified = true;
    break;

  case 'l':
    frame_line = true;
    // Disassemble the current source line kind of implies showing mixed source
    // code context.
    show_mixed = true;
    some_location_specified = true;
    break;

  case 'P':
    plugin_name.assign(std::string(option_arg));
    break;

  case 'F': {
    TargetSP target_sp =
        execution_context ? execution_context->GetTargetSP() : TargetSP();
    if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() ==
                          llvm::Triple::x86 ||
                      target_sp->GetArchitecture().GetTriple().getArch() ==
                          llvm::Triple::x86_64)) {
      flavor_string.assign(std::string(option_arg));
    } else
      error = Status::FromErrorStringWithFormat(
          "Disassembler flavors are currently only "
          "supported for x86 and x86_64 targets.");
    break;
  }

  case 'X':
    cpu_string = std::string(option_arg);
    break;

  case 'Y':
    features_string = std::string(option_arg);
    break;

  case 'r':
    raw = true;
    break;

  case 'f':
    current_function = true;
    some_location_specified = true;
    break;

  case 'A':
    if (execution_context) {
      const auto &target_sp = execution_context->GetTargetSP();
      auto platform_ptr = target_sp ? target_sp->GetPlatform().get() : nullptr;
      arch = Platform::GetAugmentedArchSpec(platform_ptr, option_arg);
    }
    break;

  case 'a': {
    symbol_containing_addr = OptionArgParser::ToAddress(
        execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
    if (symbol_containing_addr != LLDB_INVALID_ADDRESS) {
      some_location_specified = true;
    }
  } break;

  case '\x01':
    force = true;
    break;

  default:
    llvm_unreachable("Unimplemented option");
  }

  return error;
}

void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
    ExecutionContext *execution_context) {
  show_mixed = false;
  show_bytes = false;
  show_control_flow_kind = false;
  num_lines_context = 0;
  num_instructions = 0;
  func_name.clear();
  current_function = false;
  at_pc = false;
  frame_line = false;
  start_addr = LLDB_INVALID_ADDRESS;
  end_addr = LLDB_INVALID_ADDRESS;
  symbol_containing_addr = LLDB_INVALID_ADDRESS;
  raw = false;
  plugin_name.clear();

  Target *target =
      execution_context ? execution_context->GetTargetPtr() : nullptr;

  if (target) {
    // This is a hack till we get the ability to specify features based on
    // architecture.  For now GetDisassemblyFlavor is really only valid for x86
    // (and for the llvm assembler plugin, but I'm papering over that since that
    // is the only disassembler plugin we have...
    if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
        target->GetArchitecture().GetTriple().getArch() ==
            llvm::Triple::x86_64) {
      flavor_string.assign(target->GetDisassemblyFlavor());
    } else {
      flavor_string.assign("default");
    }
    if (const char *cpu = target->GetDisassemblyCPU())
      cpu_string.assign(cpu);
    if (const char *features = target->GetDisassemblyFeatures())
      features_string.assign(features);
  } else {
    flavor_string.assign("default");
    cpu_string.assign("default");
    features_string.assign("default");
  }

  arch.Clear();
  some_location_specified = false;
  force = false;
}

Status CommandObjectDisassemble::CommandOptions::OptionParsingFinished(
    ExecutionContext *execution_context) {
  if (!some_location_specified)
    current_function = true;
  return Status();
}

llvm::ArrayRef<OptionDefinition>
CommandObjectDisassemble::CommandOptions::GetDefinitions() {
  return llvm::ArrayRef(g_disassemble_options);
}

// CommandObjectDisassemble

CommandObjectDisassemble::CommandObjectDisassemble(
    CommandInterpreter &interpreter)
    : CommandObjectParsed(
          interpreter, "disassemble",
          "Disassemble specified instructions in the current target.  "
          "Defaults to the current function for the current thread and "
          "stack frame.",
          "disassemble [<cmd-options>]", eCommandRequiresTarget) {}

CommandObjectDisassemble::~CommandObjectDisassemble() = default;

llvm::Error CommandObjectDisassemble::CheckRangeSize(const AddressRange &range,
                                                     llvm::StringRef what) {
  if (m_options.num_instructions > 0 || m_options.force ||
      range.GetByteSize() < GetDebugger().GetStopDisassemblyMaxSize())
    return llvm::Error::success();
  StreamString msg;
  msg << "Not disassembling " << what << " because it is very large ";
  range.Dump(&msg, &GetTarget(), Address::DumpStyleLoadAddress,
             Address::DumpStyleFileAddress);
  msg << ". To disassemble specify an instruction count limit, start/stop "
         "addresses or use the --force option.";
  return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                 msg.GetString());
}

llvm::Expected<std::vector<AddressRange>>
CommandObjectDisassemble::GetContainingAddressRanges() {
  std::vector<AddressRange> ranges;
  const auto &get_range = [&](Address addr) {
    ModuleSP module_sp(addr.GetModule());
    SymbolContext sc;
    bool resolve_tail_call_address = true;
    addr.GetModule()->ResolveSymbolContextForAddress(
        addr, eSymbolContextEverything, sc, resolve_tail_call_address);
    if (sc.function || sc.symbol) {
      AddressRange range;
      sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
                         false, range);
      ranges.push_back(range);
    }
  };

  Target &target = GetTarget();
  if (target.HasLoadedSections()) {
    Address symbol_containing_address;
    if (target.ResolveLoadAddress(m_options.symbol_containing_addr,
                                  symbol_containing_address)) {
      get_range(symbol_containing_address);
    }
  } else {
    for (lldb::ModuleSP module_sp : target.GetImages().Modules()) {
      Address file_address;
      if (module_sp->ResolveFileAddress(m_options.symbol_containing_addr,
                                        file_address)) {
        get_range(file_address);
      }
    }
  }

  if (ranges.empty()) {
    return llvm::createStringError(
        llvm::inconvertibleErrorCode(),
        "Could not find function bounds for address 0x%" PRIx64,
        m_options.symbol_containing_addr);
  }

  if (llvm::Error err = CheckRangeSize(ranges[0], "the function"))
    return std::move(err);
  return ranges;
}

llvm::Expected<std::vector<AddressRange>>
CommandObjectDisassemble::GetCurrentFunctionRanges() {
  Process *process = m_exe_ctx.GetProcessPtr();
  StackFrame *frame = m_exe_ctx.GetFramePtr();
  if (!frame) {
    if (process) {
      return llvm::createStringError(
          llvm::inconvertibleErrorCode(),
          "Cannot disassemble around the current "
          "function without the process being stopped.\n");
    } else {
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "Cannot disassemble around the current "
                                     "function without a selected frame: "
                                     "no currently running process.\n");
    }
  }
  SymbolContext sc(
      frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
  AddressRange range;
  if (sc.function)
    range = sc.function->GetAddressRange();
  else if (sc.symbol && sc.symbol->ValueIsAddress()) {
    range = {sc.symbol->GetAddress(), sc.symbol->GetByteSize()};
  } else
    range = {frame->GetFrameCodeAddress(), default_disasm_byte_size};

  if (llvm::Error err = CheckRangeSize(range, "the current function"))
    return std::move(err);
  return std::vector<AddressRange>{range};
}

llvm::Expected<std::vector<AddressRange>>
CommandObjectDisassemble::GetCurrentLineRanges() {
  Process *process = m_exe_ctx.GetProcessPtr();
  StackFrame *frame = m_exe_ctx.GetFramePtr();
  if (!frame) {
    if (process) {
      return llvm::createStringError(
          llvm::inconvertibleErrorCode(),
          "Cannot disassemble around the current "
          "function without the process being stopped.\n");
    } else {
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "Cannot disassemble around the current "
                                     "line without a selected frame: "
                                     "no currently running process.\n");
    }
  }

  LineEntry pc_line_entry(
      frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
  if (pc_line_entry.IsValid())
    return std::vector<AddressRange>{pc_line_entry.range};

  // No line entry, so just disassemble around the current pc
  m_options.show_mixed = false;
  return GetPCRanges();
}

llvm::Expected<std::vector<AddressRange>>
CommandObjectDisassemble::GetNameRanges(CommandReturnObject &result) {
  ConstString name(m_options.func_name.c_str());

  ModuleFunctionSearchOptions function_options;
  function_options.include_symbols = true;
  function_options.include_inlines = true;

  // Find functions matching the given name.
  SymbolContextList sc_list;
  GetTarget().GetImages().FindFunctions(name, eFunctionNameTypeAuto,
                                        function_options, sc_list);

  std::vector<AddressRange> ranges;
  llvm::Error range_errs = llvm::Error::success();
  AddressRange range;
  const uint32_t scope =
      eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
  const bool use_inline_block_range = true;
  for (SymbolContext sc : sc_list.SymbolContexts()) {
    for (uint32_t range_idx = 0;
         sc.GetAddressRange(scope, range_idx, use_inline_block_range, range);
         ++range_idx) {
      if (llvm::Error err = CheckRangeSize(range, "a range"))
        range_errs = joinErrors(std::move(range_errs), std::move(err));
      else
        ranges.push_back(range);
    }
  }
  if (ranges.empty()) {
    if (range_errs)
      return std::move(range_errs);
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                   "Unable to find symbol with name '%s'.\n",
                                   name.GetCString());
  }
  if (range_errs)
    result.AppendWarning(toString(std::move(range_errs)));
  return ranges;
}

llvm::Expected<std::vector<AddressRange>>
CommandObjectDisassemble::GetPCRanges() {
  Process *process = m_exe_ctx.GetProcessPtr();
  StackFrame *frame = m_exe_ctx.GetFramePtr();
  if (!frame) {
    if (process) {
      return llvm::createStringError(
          llvm::inconvertibleErrorCode(),
          "Cannot disassemble around the current "
          "function without the process being stopped.\n");
    } else {
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "Cannot disassemble around the current "
                                     "PC without a selected frame: "
                                     "no currently running process.\n");
    }
  }

  if (m_options.num_instructions == 0) {
    // Disassembling at the PC always disassembles some number of
    // instructions (not the whole function).
    m_options.num_instructions = default_disasm_num_ins;
  }
  return std::vector<AddressRange>{{frame->GetFrameCodeAddress(), 0}};
}

llvm::Expected<std::vector<AddressRange>>
CommandObjectDisassemble::GetStartEndAddressRanges() {
  addr_t size = 0;
  if (m_options.end_addr != LLDB_INVALID_ADDRESS) {
    if (m_options.end_addr <= m_options.start_addr) {
      return llvm::createStringError(llvm::inconvertibleErrorCode(),
                                     "End address before start address.");
    }
    size = m_options.end_addr - m_options.start_addr;
  }
  return std::vector<AddressRange>{{Address(m_options.start_addr), size}};
}

llvm::Expected<std::vector<AddressRange>>
CommandObjectDisassemble::GetRangesForSelectedMode(
    CommandReturnObject &result) {
  if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
    return CommandObjectDisassemble::GetContainingAddressRanges();
  if (m_options.current_function)
    return CommandObjectDisassemble::GetCurrentFunctionRanges();
  if (m_options.frame_line)
    return CommandObjectDisassemble::GetCurrentLineRanges();
  if (!m_options.func_name.empty())
    return CommandObjectDisassemble::GetNameRanges(result);
  if (m_options.start_addr != LLDB_INVALID_ADDRESS)
    return CommandObjectDisassemble::GetStartEndAddressRanges();
  return CommandObjectDisassemble::GetPCRanges();
}

void CommandObjectDisassemble::DoExecute(Args &command,
                                         CommandReturnObject &result) {
  Target &target = GetTarget();

  if (!m_options.arch.IsValid())
    m_options.arch = target.GetArchitecture();

  if (!m_options.arch.IsValid()) {
    result.AppendError(
        "use the --arch option or set the target architecture to disassemble");
    return;
  }

  const char *plugin_name = m_options.GetPluginName();
  const char *flavor_string = m_options.GetFlavorString();
  const char *cpu_string = m_options.GetCPUString();
  const char *features_string = m_options.GetFeaturesString();

  DisassemblerSP disassembler = Disassembler::FindPlugin(
      m_options.arch, flavor_string, cpu_string, features_string, plugin_name);

  if (!disassembler) {
    if (plugin_name) {
      result.AppendErrorWithFormat(
          "Unable to find Disassembler plug-in named '%s' that supports the "
          "'%s' architecture.\n",
          plugin_name, m_options.arch.GetArchitectureName());
    } else
      result.AppendErrorWithFormat(
          "Unable to find Disassembler plug-in for the '%s' architecture.\n",
          m_options.arch.GetArchitectureName());
    return;
  } else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(
                                             m_options.arch, flavor_string))
    result.AppendWarningWithFormat(
        "invalid disassembler flavor \"%s\", using default.\n", flavor_string);

  result.SetStatus(eReturnStatusSuccessFinishResult);

  if (!command.empty()) {
    result.AppendErrorWithFormat(
        "\"disassemble\" arguments are specified as options.\n");
    const int terminal_width =
        GetCommandInterpreter().GetDebugger().GetTerminalWidth();
    GetOptions()->GenerateOptionUsage(result.GetErrorStream(), *this,
                                      terminal_width);
    return;
  }

  if (m_options.show_mixed && m_options.num_lines_context == 0)
    m_options.num_lines_context = 2;

  // Always show the PC in the disassembly
  uint32_t options = Disassembler::eOptionMarkPCAddress;

  // Mark the source line for the current PC only if we are doing mixed source
  // and assembly
  if (m_options.show_mixed)
    options |= Disassembler::eOptionMarkPCSourceLine;

  if (m_options.show_bytes)
    options |= Disassembler::eOptionShowBytes;

  if (m_options.show_control_flow_kind)
    options |= Disassembler::eOptionShowControlFlowKind;

  if (m_options.raw)
    options |= Disassembler::eOptionRawOuput;

  llvm::Expected<std::vector<AddressRange>> ranges =
      GetRangesForSelectedMode(result);
  if (!ranges) {
    result.AppendError(toString(ranges.takeError()));
    return;
  }

  bool print_sc_header = ranges->size() > 1;
  for (AddressRange cur_range : *ranges) {
    Disassembler::Limit limit;
    if (m_options.num_instructions == 0) {
      limit = {Disassembler::Limit::Bytes, cur_range.GetByteSize()};
      if (limit.value == 0)
        limit.value = default_disasm_byte_size;
    } else {
      limit = {Disassembler::Limit::Instructions, m_options.num_instructions};
    }
    if (Disassembler::Disassemble(
            GetDebugger(), m_options.arch, plugin_name, flavor_string,
            cpu_string, features_string, m_exe_ctx, cur_range.GetBaseAddress(),
            limit, m_options.show_mixed,
            m_options.show_mixed ? m_options.num_lines_context : 0, options,
            result.GetOutputStream())) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS) {
        result.AppendErrorWithFormat(
            "Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n",
            m_options.symbol_containing_addr);
      } else {
        result.AppendErrorWithFormat(
            "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
            cur_range.GetBaseAddress().GetLoadAddress(&target));
      }
    }
    if (print_sc_header)
      result.GetOutputStream() << "\n";
  }
}
