//===-- 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/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"

#define DEFAULT_DISASM_BYTE_SIZE 32
#define DEFAULT_DISASM_NUM_INS 4

using namespace lldb;
using namespace lldb_private;

#define LLDB_OPTIONS_disassemble
#include "CommandOptions.inc"

CommandObjectDisassemble::CommandOptions::CommandOptions()
    : Options(), num_lines_context(0), num_instructions(0), func_name(),
      current_function(false), start_addr(), end_addr(), at_pc(false),
      frame_line(false), plugin_name(), flavor_string(), arch(),
      some_location_specified(false), symbol_containing_addr() {
  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.SetErrorStringWithFormat("invalid num context lines string: \"%s\"",
                                     option_arg.str().c_str());
    break;

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

  case 'b':
    show_bytes = 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.SetErrorStringWithFormat("Disassembler flavors are currently only "
                                     "supported for x86 and x86_64 targets.");
    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;

  default:
    llvm_unreachable("Unimplemented option");
  }

  return error;
}

void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
    ExecutionContext *execution_context) {
  show_mixed = false;
  show_bytes = 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;

  // 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) {
    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");

  } else
    flavor_string.assign("default");

  arch.Clear();
  some_location_specified = 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::makeArrayRef(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),
      m_options() {}

CommandObjectDisassemble::~CommandObjectDisassemble() = default;

bool CommandObjectDisassemble::DoExecute(Args &command,
                                         CommandReturnObject &result) {
  Target *target = &GetSelectedTarget();

  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");
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  const char *plugin_name = m_options.GetPluginName();
  const char *flavor_string = m_options.GetFlavorString();

  DisassemblerSP disassembler =
      Disassembler::FindPlugin(m_options.arch, flavor_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());
    result.SetStatus(eReturnStatusFailed);
    return false;
  } 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);
    result.SetStatus(eReturnStatusFailed);
    return false;
  }

  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.raw)
    options |= Disassembler::eOptionRawOuput;

  if (!m_options.func_name.empty()) {
    ConstString name(m_options.func_name.c_str());

    if (Disassembler::Disassemble(
            GetDebugger(), m_options.arch, plugin_name, flavor_string,
            m_exe_ctx, name,
            nullptr, // Module *
            m_options.num_instructions, m_options.show_mixed,
            m_options.show_mixed ? m_options.num_lines_context : 0, options,
            result.GetOutputStream())) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendErrorWithFormat("Unable to find symbol with name '%s'.\n",
                                   name.GetCString());
      result.SetStatus(eReturnStatusFailed);
    }
  } else {
    std::vector<AddressRange> ranges;
    AddressRange range;
    StackFrame *frame = m_exe_ctx.GetFramePtr();
    if (m_options.frame_line) {
      if (frame == nullptr) {
        result.AppendError("Cannot disassemble around the current line without "
                           "a selected frame.\n");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
      LineEntry pc_line_entry(
          frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
      if (pc_line_entry.IsValid()) {
        range = pc_line_entry.range;
      } else {
        m_options.at_pc =
            true; // No line entry, so just disassemble around the current pc
        m_options.show_mixed = false;
      }
    } else if (m_options.current_function) {
      if (frame == nullptr) {
        result.AppendError("Cannot disassemble around the current function "
                           "without a selected frame.\n");
        result.SetStatus(eReturnStatusFailed);
        return false;
      }
      Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
      if (symbol) {
        range.GetBaseAddress() = symbol->GetAddress();
        range.SetByteSize(symbol->GetByteSize());
      }
    }

    // Did the "m_options.frame_line" find a valid range already? If so skip
    // the rest...
    if (range.GetByteSize() == 0) {
      if (m_options.at_pc) {
        if (frame == nullptr) {
          result.AppendError("Cannot disassemble around the current PC without "
                             "a selected frame.\n");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        range.GetBaseAddress() = frame->GetFrameCodeAddress();
        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;
        }
        ranges.push_back(range);
      } else {
        range.GetBaseAddress().SetOffset(m_options.start_addr);
        if (range.GetBaseAddress().IsValid()) {
          if (m_options.end_addr != LLDB_INVALID_ADDRESS) {
            if (m_options.end_addr <= m_options.start_addr) {
              result.AppendErrorWithFormat(
                  "End address before start address.\n");
              result.SetStatus(eReturnStatusFailed);
              return false;
            }
            range.SetByteSize(m_options.end_addr - m_options.start_addr);
          }
          ranges.push_back(range);
        } else {
          if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS &&
              target) {
            if (!target->GetSectionLoadList().IsEmpty()) {
              bool failed = false;
              Address symbol_containing_address;
              if (target->GetSectionLoadList().ResolveLoadAddress(
                      m_options.symbol_containing_addr,
                      symbol_containing_address)) {
                ModuleSP module_sp(symbol_containing_address.GetModule());
                SymbolContext sc;
                bool resolve_tail_call_address = true; // PC can be one past the
                                                       // address range of the
                                                       // function.
                module_sp->ResolveSymbolContextForAddress(
                    symbol_containing_address, eSymbolContextEverything, sc,
                    resolve_tail_call_address);
                if (sc.function || sc.symbol) {
                  sc.GetAddressRange(eSymbolContextFunction |
                                         eSymbolContextSymbol,
                                     0, false, range);
                } else {
                  failed = true;
                }
              } else {
                failed = true;
              }
              if (failed) {
                result.AppendErrorWithFormat(
                    "Could not find function bounds for address 0x%" PRIx64
                    "\n",
                    m_options.symbol_containing_addr);
                result.SetStatus(eReturnStatusFailed);
                return false;
              }
              ranges.push_back(range);
            } else {
              for (lldb::ModuleSP module_sp : target->GetImages().Modules()) {
                lldb::addr_t file_addr = m_options.symbol_containing_addr;
                Address file_address;
                if (module_sp->ResolveFileAddress(file_addr, file_address)) {
                  SymbolContext sc;
                  bool resolve_tail_call_address = true; // PC can be one past
                                                         // the address range of
                                                         // the function.
                  module_sp->ResolveSymbolContextForAddress(
                      file_address, eSymbolContextEverything, sc,
                      resolve_tail_call_address);
                  if (sc.function || sc.symbol) {
                    sc.GetAddressRange(eSymbolContextFunction |
                                           eSymbolContextSymbol,
                                       0, false, range);
                    ranges.push_back(range);
                  }
                }
              }
            }
          }
        }
      }
    } else
      ranges.push_back(range);

    if (m_options.num_instructions != 0) {
      if (ranges.empty()) {
        // The default action is to disassemble the current frame function.
        if (frame) {
          SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
                                                   eSymbolContextSymbol));
          if (sc.function)
            range.GetBaseAddress() =
                sc.function->GetAddressRange().GetBaseAddress();
          else if (sc.symbol && sc.symbol->ValueIsAddress())
            range.GetBaseAddress() = sc.symbol->GetAddress();
          else
            range.GetBaseAddress() = frame->GetFrameCodeAddress();
        }

        if (!range.GetBaseAddress().IsValid()) {
          result.AppendError("invalid frame");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
      }

      bool print_sc_header = ranges.size() > 1;
      for (AddressRange cur_range : ranges) {
        if (Disassembler::Disassemble(
                GetDebugger(), m_options.arch, plugin_name, flavor_string,
                m_exe_ctx, cur_range.GetBaseAddress(),
                m_options.num_instructions, m_options.show_mixed,
                m_options.show_mixed ? m_options.num_lines_context : 0, options,
                result.GetOutputStream())) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          if (m_options.start_addr != LLDB_INVALID_ADDRESS)
            result.AppendErrorWithFormat(
                "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
                m_options.start_addr);
          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);
          result.SetStatus(eReturnStatusFailed);
        }
      }
      if (print_sc_header)
        result.AppendMessage("\n");
    } else {
      if (ranges.empty()) {
        // The default action is to disassemble the current frame function.
        if (frame) {
          SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
                                                   eSymbolContextSymbol));
          if (sc.function)
            range = sc.function->GetAddressRange();
          else if (sc.symbol && sc.symbol->ValueIsAddress()) {
            range.GetBaseAddress() = sc.symbol->GetAddress();
            range.SetByteSize(sc.symbol->GetByteSize());
          } else
            range.GetBaseAddress() = frame->GetFrameCodeAddress();
        } else {
          result.AppendError("invalid frame");
          result.SetStatus(eReturnStatusFailed);
          return false;
        }
        ranges.push_back(range);
      }

      bool print_sc_header = ranges.size() > 1;
      for (AddressRange cur_range : ranges) {
        if (cur_range.GetByteSize() == 0)
          cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);

        if (Disassembler::Disassemble(
                GetDebugger(), m_options.arch, plugin_name, flavor_string,
                m_exe_ctx, cur_range, m_options.num_instructions,
                m_options.show_mixed,
                m_options.show_mixed ? m_options.num_lines_context : 0, options,
                result.GetOutputStream())) {
          result.SetStatus(eReturnStatusSuccessFinishResult);
        } else {
          result.AppendErrorWithFormat(
              "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
              cur_range.GetBaseAddress().GetLoadAddress(target));
          result.SetStatus(eReturnStatusFailed);
        }
        if (print_sc_header)
          result.AppendMessage("\n");
      }
    }
  }

  return result.Succeeded();
}
