//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
//
// 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/Core/SourceManager.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandCompletions.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/Process.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(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(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(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();
}
