// Copyright 2020 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 "src/developer/debug/zxdb/console/format_symbol.h"

#include <algorithm>
#include <optional>

#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/common/string_util.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/format_location.h"
#include "src/developer/debug/zxdb/console/format_name.h"
#include "src/developer/debug/zxdb/console/format_table.h"
#include "src/developer/debug/zxdb/expr/find_name.h"
#include "src/developer/debug/zxdb/expr/resolve_type.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/call_site.h"
#include "src/developer/debug/zxdb/symbols/call_site_parameter.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/compile_unit.h"
#include "src/developer/debug/zxdb/symbols/data_member.h"
#include "src/developer/debug/zxdb/symbols/dwarf_expr_eval.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/inherited_from.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/module_symbol_status.h"
#include "src/developer/debug/zxdb/symbols/module_symbols.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
#include "src/developer/debug/zxdb/symbols/type.h"
#include "src/developer/debug/zxdb/symbols/variable.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

std::string GetIndentStr(int indent_level) { return std::string(indent_level * 2, ' '); }

// Handles formatting with pretty identifier formatting if possible, and falls back to raw strings
// for cases where the name isn't an identifier (e.g. modified types like "const int*").
//
// The input can be null which will print out an error.
OutputBuffer GetFormattedName(const Symbol* symbol) {
  OutputBuffer out;
  if (!symbol) {
    out.Append(Syntax::kComment, "<bad symbol>");
    return out;
  }

  const Identifier& ident = symbol->GetIdentifier();
  if (ident.empty()) {
    out.Append(symbol->GetFullName());
  } else {
    FormatIdentifierOptions options;
    options.bold_last = true;
    out.Append(FormatIdentifier(ident, options));
  }

  return out;
}

// ProcessSymbols can be null.
OutputBuffer FormatCollectionMembers(const ProcessSymbols* process_symbols,
                                     const Collection* coll) {
  OutputBuffer out;

  struct Record {
    Record(std::optional<size_t> o, size_t s, OutputBuffer n, OutputBuffer t)
        : offset(o), size(s), name(std::move(n)), type(std::move(t)) {}

    std::optional<size_t> offset;  // nullopt for virtual inheritance where the offset is not known.
    size_t size;
    OutputBuffer name;
    OutputBuffer type;
  };
  std::vector<Record> records;

  FindNameContext find_name_context(process_symbols);  // FindNameContext handles null pointers.

  // Inherited base classes.
  for (const auto& lazy_from : coll->inherited_from()) {
    const InheritedFrom* from = lazy_from.Get()->As<InheritedFrom>();
    if (!from)
      continue;

    auto from_type = GetConcreteType(find_name_context, from->from());
    if (!from_type)
      continue;

    std::optional<size_t> offset;
    if (from->kind() == InheritedFrom::kConstant)
      offset = from->offset();

    records.emplace_back(offset, from_type->byte_size(),
                         OutputBuffer(Syntax::kComment, "<base class>"),
                         GetFormattedName(from_type.get()));
  }

  // Data members.
  for (const auto& lazy_member : coll->data_members()) {
    const DataMember* member = lazy_member.Get()->As<DataMember>();
    if (!member)
      continue;

    const Type* member_type = member->type().Get()->As<Type>();
    if (!member_type)
      continue;

    // TODO(brettw) We should probably show bitfields here.
    records.emplace_back(member->member_location(), member_type->byte_size(),
                         OutputBuffer(Syntax::kVariable, member->GetAssignedName()),
                         GetFormattedName(member_type));
  }

  // Sort by data offset. Use the stable sort to keep inherited base classes first even if they
  // start at the same offset as a data member (they can be 0 size).
  std::stable_sort(records.begin(), records.end(),
                   [](const Record& a, const Record& b) { return a.offset < b.offset; });

  out.Append(Syntax::kHeading, "  Members:");
  if (records.empty()) {
    out.Append(" <empty>\n");
    return out;
  }
  out.Append("\n");

  // Construct into table rows.
  std::vector<std::vector<OutputBuffer>> rows;
  size_t prev_end = 0;  // Next byte after the last one we've processed.
  for (Record& record : records) {
    OutputBuffer offset_desc;

    if (record.offset) {
      if (record.offset > prev_end) {
        // Found empty space. Indicate this.
        auto& row = rows.emplace_back();
        row.emplace_back(Syntax::kComment, std::to_string(prev_end));
        row.emplace_back(Syntax::kComment, std::to_string(*record.offset - prev_end));
        row.emplace_back();
        row.emplace_back(Syntax::kComment, "<padding>");
      }
      offset_desc = OutputBuffer(std::to_string(*record.offset));
    } else {
      // Virtual inheritance.
      offset_desc = OutputBuffer(Syntax::kComment, "<virtual>");
    }

    auto& row = rows.emplace_back();
    row.push_back(std::move(offset_desc));
    row.emplace_back(std::to_string(record.size));
    row.push_back(std::move(record.name));
    row.push_back(std::move(record.type));

    if (record.offset) {
      // The std::max() call is necessary so we always go forward. Sometimes inheritance information
      // for zero-sized base classes can overlap.
      prev_end = std::max(prev_end, *record.offset + record.size);
    }
  }

  FormatTable({ColSpec(Align::kRight, 0, "Offset", 4), ColSpec(Align::kRight, 0, "Size"),
               ColSpec(Align::kLeft, 0, "Name"), ColSpec(Align::kLeft, 0, "Type")},
              rows, &out);
  return out;
}

// Formats a type as a one-line member for use while dumping a symbol that has a type. The heading
// will be followed with a colon to provide a label.
OutputBuffer FormatTypeDescription(const char* heading, const LazySymbol& lazy_type) {
  OutputBuffer out;
  out.Append(Syntax::kHeading, fxl::StringPrintf("  %s: ", heading));
  // DWARF uses empty types for "void".
  if (lazy_type) {
    out.Append(GetFormattedName(lazy_type.Get()->As<Type>()));
  } else {
    out.Append("void");
  }
  out.Append("\n");
  return out;
}

// Creates a compilation unit and module line for the given symbol. If there is none (normally
// during testing), returns an empty buffer.
OutputBuffer FormatCompilationUnitAndModule(int indent, const Symbol* symbol) {
  OutputBuffer out;

  auto compile_unit = symbol->GetCompileUnit();
  if (!compile_unit)
    return out;

  std::string indent_str = GetIndentStr(indent);

  if (fxl::WeakPtr<ModuleSymbols> module = symbol->GetModuleSymbols()) {
    ModuleSymbolStatus status = module->GetStatus();
    if (!status.name.empty()) {
      out.Append(Syntax::kHeading, indent_str + "  Module: ");
      out.Append(Syntax::kFileName, status.name);
      out.Append("\n");
    }
  }

  out.Append(Syntax::kHeading, indent_str + "  Compilation unit: ");
  out.Append(Syntax::kFileName, compile_unit->name());
  out.Append("\n");

  return out;
}

// Implements SymbolDataProvider just enough for the DwarfExprEval to pretty-print register names.
class ArchDataProvider : public SymbolDataProvider {
 public:
  ArchDataProvider(debug::Arch a) : arch_(a) {}

  debug::Arch GetArch() override { return arch_; }

 private:
  debug::Arch arch_;
};

// Format the given DwarfExpr, does not include a newline at the end.
OutputBuffer FormatDwarfExpr(debug::Arch arch, FormatSymbolOptions::DwarfExpr what,
                             const SymbolContext& symbol_context, const DwarfExpr& expr) {
  if (what == FormatSymbolOptions::DwarfExpr::kBytes) {
    // Dump the raw DWARF expression bytes.
    std::string result;
    bool first = true;
    for (uint8_t byte : expr.data()) {
      if (first) {
        first = false;
      } else {
        result.push_back(' ');  // Separator between bytes.
      }
      result += to_hex_string(byte, 2);
    }
    return result;
  }

  DwarfExprEval eval;
  return eval.ToString(fxl::MakeRefCounted<ArchDataProvider>(arch), symbol_context, expr,
                       what == FormatSymbolOptions::DwarfExpr::kPretty);
}

OutputBuffer FormatVariableLocation(int indent, const std::string& title,
                                    const SymbolContext& symbol_context,
                                    const VariableLocation& loc, const FormatSymbolOptions& opts) {
  std::string indent_str = GetIndentStr(indent);

  OutputBuffer out;
  if (loc.is_null()) {
    out.Append(Syntax::kHeading, indent_str + title + ":");
    out.Append(Syntax::kComment, " <no location info>\n");
    return out;
  }

  out.Append(Syntax::kHeading, indent_str + title);
  out.Append(Syntax::kComment, " (address range + DWARF expression):\n");
  for (const auto& entry : loc.locations()) {
    out.Append(indent_str +
               fxl::StringPrintf("  [0x%" PRIx64 ", 0x%" PRIx64 "): ",
                                 symbol_context.RelativeToAbsolute(entry.range.begin()),
                                 symbol_context.RelativeToAbsolute(entry.range.end())));
    out.Append(FormatDwarfExpr(opts.arch, opts.dwarf_expr, symbol_context, entry.expression));
    out.Append("\n");
  }

  if (const DwarfExpr* default_expr = loc.default_expr()) {
    out.Append(Syntax::kComment, indent_str + "  <default>: ");
    out.Append(FormatDwarfExpr(opts.arch, opts.dwarf_expr, symbol_context, *default_expr));
    out.Append("\n");
  }

  return out;
}

OutputBuffer FormatType(const ProcessSymbols* process_symbols, const Type* type) {
  OutputBuffer out;
  out.Append(Syntax::kHeading, "Type: ");
  out.Append(GetFormattedName(type));

  out.Append(Syntax::kHeading, "\n  DWARF tag: ");
  out.Append(DwarfTagToString(type->tag(), true) + "\n");
  out.Append(FormatCompilationUnitAndModule(0, type));
  out.Append(Syntax::kHeading, "  Byte size: ");
  out.Append(std::to_string(type->byte_size()) + "\n");

  // Subtype-specific handling.
  if (const BaseType* base_type = type->As<BaseType>()) {
    out.Append(Syntax::kHeading, "  DWARF base type: ");
    out.Append(BaseType::BaseTypeToString(base_type->base_type(), true) + "\n");
  } else if (const Collection* collection = type->As<Collection>()) {
    out.Append(Syntax::kHeading, "  Calling convention: ");
    out.Append(Collection::CallingConventionToString(collection->calling_convention()));
    out.Append("\n");
    out.Append(FormatCollectionMembers(process_symbols, collection));
  } else if (const ModifiedType* modified = type->As<ModifiedType>()) {
    if (modified->tag() == DwarfTag::kTypedef) {
      out.Append(FormatTypeDescription("Underlying type", modified->modified()));

      // For typedefs of collections, show the collection members. Often people won't know such
      // a thing is a typedef and doing this can save a step. Additionally, in C it's common to do
      // "typedef struct { ... } Name;" which creates a typedef of an anonymous struct. There's no
      // way to refer to the underlying struct so putting them here is the only way to see them.
      if (const Collection* modified_collection = modified->modified().Get()->As<Collection>())
        out.Append(FormatCollectionMembers(process_symbols, modified_collection));
    } else {
      out.Append(FormatTypeDescription("Modified type", modified->modified()));
    }
  }

  return out;
}

OutputBuffer FormatVariable(const std::string& heading, int indent,
                            const SymbolContext& symbol_context, const Variable* variable,
                            const FormatSymbolOptions& opts) {
  std::string indent_str = GetIndentStr(indent);

  OutputBuffer out;
  out.Append(Syntax::kHeading, indent_str + heading + ": ");
  out.Append(Syntax::kVariable, variable->GetAssignedName());
  out.Append("\n" + indent_str);
  out.Append(FormatTypeDescription("Type", variable->type()));
  out.Append(FormatCompilationUnitAndModule(indent, variable));
  out.Append(Syntax::kHeading, indent_str + "  DWARF tag: ");
  out.Append(DwarfTagToString(variable->tag(), true) + "\n");

  out.Append(FormatVariableLocation(indent + 1, "DWARF location", symbol_context,
                                    variable->location(), opts));

  return out;
}

OutputBuffer FormatFunction(const SymbolContext& symbol_context, const Function* function,
                            const FormatSymbolOptions& opts) {
  OutputBuffer out;

  // Type and name.
  if (function->is_inline())
    out.Append(Syntax::kHeading, "Inline function: ");
  else
    out.Append(Syntax::kHeading, "Function: ");

  FormatFunctionNameOptions name_opts;
  name_opts.name.bold_last = true;
  name_opts.params = FormatFunctionNameOptions::kParamTypes;

  out.Append(FormatFunctionName(function, name_opts));
  out.Append("\n");

  // Linkage name.
  if (!function->linkage_name().empty()) {
    out.Append(Syntax::kHeading, "  Linkage name: ");
    out.Append(function->linkage_name());
    out.Append("\n");
  }

  // Declaration.
  if (function->decl_line().is_valid()) {
    out.Append(Syntax::kHeading, "  Declaration: ");
    out.Append(FormatFileLine(function->decl_line()));
    out.Append("\n");
  }

  // Call location.
  if (function->call_line().is_valid()) {
    out.Append(Syntax::kHeading, "  Inline call location: ");
    out.Append(FormatFileLine(function->call_line()));
    out.Append("\n");
  }

  // Code ranges.
  AddressRanges ranges = function->GetAbsoluteCodeRanges(symbol_context);
  if (ranges.empty()) {
    out.Append("  No code ranges.\n");
  } else {
    out.Append(Syntax::kHeading, "  Code ranges");
    out.Append(Syntax::kComment, " [begin, end-non-inclusive):\n");
    for (const auto& range : ranges)
      out.Append("    " + range.ToString() + "\n");
  }

  out.Append(FormatVariableLocation(1, "Frame base", symbol_context, function->frame_base(), opts));
  out.Append(FormatTypeDescription("Return type", function->return_type()));

  // Object pointer.
  if (const Variable* object = function->GetObjectPointerVariable())
    out.Append(FormatVariable("Object", 1, symbol_context, object, opts));

  return out;
}

OutputBuffer FormatDataMember(const DataMember* data_member) {
  OutputBuffer out;
  out.Append(Syntax::kHeading, "Data member: ");
  out.Append(Syntax::kVariable, data_member->GetFullName() + "\n");

  auto parent = data_member->parent().Get();
  out.Append(Syntax::kHeading, "  Contained in: ");
  out.Append(FormatIdentifier(parent->GetIdentifier(), FormatIdentifierOptions()));
  out.Append("\n");

  out.Append(FormatTypeDescription("Type", data_member->type()));
  out.Append(Syntax::kHeading, "  Offset within container: ");
  out.Append(fxl::StringPrintf("%" PRIu32 "\n", data_member->member_location()));
  out.Append(Syntax::kHeading, "  DWARF tag: ");
  out.Append(DwarfTagToString(data_member->tag(), true) + "\n");

  return out;
}

OutputBuffer FormatElfSymbol(const SymbolContext& symbol_context, const ElfSymbol* elf_symbol) {
  OutputBuffer out;
  switch (elf_symbol->elf_type()) {
    case ElfSymbolType::kNormal:
      out.Append(Syntax::kHeading, "ELF symbol: ");
      break;
    case ElfSymbolType::kPlt:
      out.Append(Syntax::kHeading, "ELF PLT symbol: ");
      break;
  }
  out.Append(elf_symbol->linkage_name() + "\n");

  out.Append(Syntax::kHeading, "  Address: ");
  out.Append(to_hex_string(symbol_context.RelativeToAbsolute(elf_symbol->relative_address())) +
             "\n");
  out.Append(Syntax::kHeading, "  Size: ");
  out.Append(to_hex_string(elf_symbol->size()) + "\n");
  return out;
}

OutputBuffer FormatOtherSymbol(const Symbol* symbol) {
  OutputBuffer out;
  out.Append(Syntax::kHeading, "Other symbol: ");
  out.Append(symbol->GetFullName() + "\n");
  return out;
}

OutputBuffer FormatCallSiteParameter(const SymbolContext& symbol_context,
                                     const CallSiteParameter* param,
                                     const FormatSymbolOptions& opts, int indent) {
  OutputBuffer out;
  std::string indent_str = GetIndentStr(indent);

  out.Append(Syntax::kHeading,
             indent_str + "Call site parameter:\n  " + indent_str + "DWARF register #: ");
  if (param->location_register_num()) {
    out.Append(std::to_string(*param->location_register_num()));
  } else {
    out.Append(Syntax::kComment, "<unspecified>");
  }

  out.Append(Syntax::kHeading, "\n" + indent_str + "  Value expression: ");
  out.Append(FormatDwarfExpr(opts.arch, opts.dwarf_expr, symbol_context, param->value_expr()));
  out.Append("\n");

  return out;
}

OutputBuffer FormatCallSite(const SymbolContext& symbol_context, const CallSite* call_site,
                            const FormatSymbolOptions& opts) {
  OutputBuffer out;
  out.Append(Syntax::kHeading, "Call Site\n  Return to: ");
  if (call_site->return_pc()) {
    out.Append(to_hex_string(symbol_context.RelativeToAbsolute(*call_site->return_pc())));
  } else {
    out.Append(Syntax::kComment, "<not specified>");
  }

  out.Append(Syntax::kHeading, "\n  Parameters:\n");
  for (const auto& lazy : call_site->parameters()) {
    if (const CallSiteParameter* param = lazy.Get()->As<CallSiteParameter>())
      out.Append(FormatCallSiteParameter(symbol_context, param, opts, 2));
  }
  if (call_site->parameters().empty())
    out.Append(Syntax::kComment, "    <no parameters>");

  return out;
}

}  // namespace

OutputBuffer FormatSymbol(const ProcessSymbols* process_symbols, const Symbol* symbol,
                          const FormatSymbolOptions& opts) {
  SymbolContext symbol_context = symbol->GetSymbolContext(process_symbols);

  if (const Type* type = symbol->As<Type>())
    return FormatType(process_symbols, type);
  if (const CallSite* call_site = symbol->As<CallSite>())
    return FormatCallSite(symbol_context, call_site, opts);
  if (const CallSiteParameter* call_site_param = symbol->As<CallSiteParameter>())
    return FormatCallSiteParameter(symbol_context, call_site_param, opts, 0);
  if (const Function* function = symbol->As<Function>())
    return FormatFunction(symbol_context, function, opts);
  if (const Variable* variable = symbol->As<Variable>())
    return FormatVariable("Variable", 0, symbol_context, variable, opts);
  if (const DataMember* data_member = symbol->As<DataMember>())
    return FormatDataMember(data_member);
  if (const ElfSymbol* elf_symbol = symbol->As<ElfSymbol>())
    return FormatElfSymbol(symbol_context, elf_symbol);

  return FormatOtherSymbol(symbol);
}

ErrOr<FormatSymbolOptions> GetFormatSymbolOptionsFromCommand(const Command& cmd, int expr_switch) {
  FormatSymbolOptions opts;
  opts.arch = cmd.target()->session()->arch();

  if (cmd.HasSwitch(expr_switch)) {
    std::string expr_value = cmd.GetSwitchValue(expr_switch);
    if (expr_value == "bytes") {
      opts.dwarf_expr = FormatSymbolOptions::DwarfExpr::kBytes;
    } else if (expr_value == "ops") {
      opts.dwarf_expr = FormatSymbolOptions::DwarfExpr::kOps;
    } else if (expr_value == "pretty") {
      opts.dwarf_expr = FormatSymbolOptions::DwarfExpr::kPretty;
    } else {
      return Err("Expected 'bytes', 'ops', or 'pretty' for DWARF expression format.");
    }
  }

  return opts;
}

}  // namespace zxdb
