//===-- llvm-symbolizer.cpp - Simple addr2line-like symbolizer ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This utility works much like "addr2line". It is able of transforming
// tuples (module name, module offset) to code locations (function name,
// file, line number, column number). It is targeted for compiler-rt tools
// (especially AddressSanitizer and ThreadSanitizer) that can use it
// to symbolize stack traces in their error reports.
//
//===----------------------------------------------------------------------===//

#include "Opts.inc"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/config.h"
#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
#include "llvm/DebugInfo/Symbolize/Markup.h"
#include "llvm/DebugInfo/Symbolize/MarkupFilter.h"
#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
#include "llvm/Debuginfod/BuildIDFetcher.h"
#include "llvm/Debuginfod/Debuginfod.h"
#include "llvm/Debuginfod/HTTPClient.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/COM.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>

using namespace llvm;
using namespace symbolize;

namespace {
enum ID {
  OPT_INVALID = 0, // This is not an option ID.
#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
#include "Opts.inc"
#undef OPTION
};

#define OPTTABLE_STR_TABLE_CODE
#include "Opts.inc"
#undef OPTTABLE_STR_TABLE_CODE

#define OPTTABLE_PREFIXES_TABLE_CODE
#include "Opts.inc"
#undef OPTTABLE_PREFIXES_TABLE_CODE

using namespace llvm::opt;
static constexpr opt::OptTable::Info InfoTable[] = {
#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
#include "Opts.inc"
#undef OPTION
};

class SymbolizerOptTable : public opt::GenericOptTable {
public:
  SymbolizerOptTable()
      : GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {
    setGroupedShortOptions(true);
  }
};
} // namespace

static std::string ToolName;

static void printError(const ErrorInfoBase &EI, StringRef AuxInfo) {
  WithColor::error(errs(), ToolName);
  if (!AuxInfo.empty())
    errs() << "'" << AuxInfo << "': ";
  EI.log(errs());
  errs() << '\n';
}

template <typename T>
static void print(const Request &Request, Expected<T> &ResOrErr,
                  DIPrinter &Printer) {
  if (ResOrErr) {
    // No error, print the result.
    Printer.print(Request, *ResOrErr);
    return;
  }

  // Handle the error.
  bool PrintEmpty = true;
  handleAllErrors(std::move(ResOrErr.takeError()),
                  [&](const ErrorInfoBase &EI) {
                    PrintEmpty = Printer.printError(Request, EI);
                  });

  if (PrintEmpty)
    Printer.print(Request, T());
}

enum class OutputStyle { LLVM, GNU, JSON };

enum class Command {
  Code,
  Data,
  Frame,
};

static void enableDebuginfod(LLVMSymbolizer &Symbolizer,
                             const opt::ArgList &Args) {
  static bool IsEnabled = false;
  if (IsEnabled)
    return;
  IsEnabled = true;
  // Look up symbols using the debuginfod client.
  Symbolizer.setBuildIDFetcher(std::make_unique<DebuginfodFetcher>(
      Args.getAllArgValues(OPT_debug_file_directory_EQ)));
  // The HTTPClient must be initialized for use by the debuginfod client.
  HTTPClient::initialize();
}

static StringRef getSpaceDelimitedWord(StringRef &Source) {
  const char kDelimiters[] = " \n\r";
  const char *Pos = Source.data();
  StringRef Result;
  Pos += strspn(Pos, kDelimiters);
  if (*Pos == '"' || *Pos == '\'') {
    char Quote = *Pos;
    Pos++;
    const char *End = strchr(Pos, Quote);
    if (!End)
      return StringRef();
    Result = StringRef(Pos, End - Pos);
    Pos = End + 1;
  } else {
    int NameLength = strcspn(Pos, kDelimiters);
    Result = StringRef(Pos, NameLength);
    Pos += NameLength;
  }
  Source = StringRef(Pos, Source.end() - Pos);
  return Result;
}

static Error makeStringError(StringRef Msg) {
  return make_error<StringError>(Msg, inconvertibleErrorCode());
}

static Error parseCommand(StringRef BinaryName, bool IsAddr2Line,
                          StringRef InputString, Command &Cmd,
                          std::string &ModuleName, object::BuildID &BuildID,
                          StringRef &Symbol, uint64_t &Offset) {
  ModuleName = BinaryName;
  if (InputString.consume_front("CODE ")) {
    Cmd = Command::Code;
  } else if (InputString.consume_front("DATA ")) {
    Cmd = Command::Data;
  } else if (InputString.consume_front("FRAME ")) {
    Cmd = Command::Frame;
  } else {
    // If no cmd, assume it's CODE.
    Cmd = Command::Code;
  }

  // Parse optional input file specification.
  bool HasFilePrefix = false;
  bool HasBuildIDPrefix = false;
  while (!InputString.empty()) {
    InputString = InputString.ltrim();
    if (InputString.consume_front("FILE:")) {
      if (HasFilePrefix || HasBuildIDPrefix)
        return makeStringError("duplicate input file specification prefix");
      HasFilePrefix = true;
      continue;
    }
    if (InputString.consume_front("BUILDID:")) {
      if (HasBuildIDPrefix || HasFilePrefix)
        return makeStringError("duplicate input file specification prefix");
      HasBuildIDPrefix = true;
      continue;
    }
    break;
  }

  // If an input file is not specified on the command line, try to extract it
  // from the command.
  if (HasBuildIDPrefix || HasFilePrefix) {
    InputString = InputString.ltrim();
    if (InputString.empty()) {
      if (HasFilePrefix)
        return makeStringError("must be followed by an input file");
      else
        return makeStringError("must be followed by a hash");
    }

    if (!BinaryName.empty() || !BuildID.empty())
      return makeStringError("input file has already been specified");

    StringRef Name = getSpaceDelimitedWord(InputString);
    if (Name.empty())
      return makeStringError("unbalanced quotes in input file name");
    if (HasBuildIDPrefix) {
      BuildID = parseBuildID(Name);
      if (BuildID.empty())
        return makeStringError("wrong format of build-id");
    } else {
      ModuleName = Name;
    }
  } else if (BinaryName.empty() && BuildID.empty()) {
    // No input file has been specified. If the input string contains at least
    // two items, assume that the first item is a file name.
    ModuleName = getSpaceDelimitedWord(InputString);
    if (ModuleName.empty())
      return makeStringError("no input filename has been specified");
  }

  // Parse address specification, which can be an offset in module or a
  // symbol with optional offset.
  InputString = InputString.trim();
  if (InputString.empty())
    return makeStringError("no module offset has been specified");

  // If input string contains a space, ignore everything after it. This behavior
  // is consistent with GNU addr2line.
  int AddrSpecLength = InputString.find_first_of(" \n\r");
  StringRef AddrSpec = InputString.substr(0, AddrSpecLength);
  bool StartsWithDigit = std::isdigit(AddrSpec.front());

  // GNU addr2line assumes the address is hexadecimal and allows a redundant
  // "0x", "0X" prefix or an optional `+` sign; do the same for
  // compatibility.
  if (IsAddr2Line) {
    AddrSpec.consume_front_insensitive("0x") ||
        AddrSpec.consume_front_insensitive("+0x");
  }

  // If address specification is a number, treat it as a module offset.
  if (!AddrSpec.getAsInteger(IsAddr2Line ? 16 : 0, Offset)) {
    // Module offset is an address.
    Symbol = StringRef();
    return Error::success();
  }

  // If address specification starts with a digit, but is not a number, consider
  // it as invalid.
  if (StartsWithDigit || AddrSpec.empty())
    return makeStringError("expected a number as module offset");

  // Otherwise it is a symbol name, potentially with an offset.
  Symbol = AddrSpec;
  Offset = 0;

  // If the address specification contains '+', try treating it as
  // "symbol + offset".
  size_t Plus = AddrSpec.rfind('+');
  if (Plus != StringRef::npos) {
    StringRef SymbolStr = AddrSpec.take_front(Plus);
    StringRef OffsetStr = AddrSpec.substr(Plus + 1);
    if (!SymbolStr.empty() && !OffsetStr.empty() &&
        !OffsetStr.getAsInteger(0, Offset)) {
      Symbol = SymbolStr;
      return Error::success();
    }
    // The found '+' is not an offset delimiter.
  }

  return Error::success();
}

template <typename T>
void executeCommand(StringRef ModuleName, const T &ModuleSpec, Command Cmd,
                    StringRef Symbol, uint64_t Offset, uint64_t AdjustVMA,
                    bool ShouldInline, OutputStyle Style,
                    LLVMSymbolizer &Symbolizer, DIPrinter &Printer) {
  uint64_t AdjustedOffset = Offset - AdjustVMA;
  object::SectionedAddress Address = {AdjustedOffset,
                                      object::SectionedAddress::UndefSection};
  Request SymRequest = {
      ModuleName, Symbol.empty() ? std::make_optional(Offset) : std::nullopt,
      Symbol};
  if (Cmd == Command::Data) {
    Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(ModuleSpec, Address);
    print(SymRequest, ResOrErr, Printer);
  } else if (Cmd == Command::Frame) {
    Expected<std::vector<DILocal>> ResOrErr =
        Symbolizer.symbolizeFrame(ModuleSpec, Address);
    print(SymRequest, ResOrErr, Printer);
  } else if (!Symbol.empty()) {
    Expected<std::vector<DILineInfo>> ResOrErr =
        Symbolizer.findSymbol(ModuleSpec, Symbol, Offset);
    print(SymRequest, ResOrErr, Printer);
  } else if (ShouldInline) {
    Expected<DIInliningInfo> ResOrErr =
        Symbolizer.symbolizeInlinedCode(ModuleSpec, Address);
    print(SymRequest, ResOrErr, Printer);
  } else if (Style == OutputStyle::GNU) {
    // With PrintFunctions == FunctionNameKind::LinkageName (default)
    // and UseSymbolTable == true (also default), Symbolizer.symbolizeCode()
    // may override the name of an inlined function with the name of the topmost
    // caller function in the inlining chain. This contradicts the existing
    // behavior of addr2line. Symbolizer.symbolizeInlinedCode() overrides only
    // the topmost function, which suits our needs better.
    Expected<DIInliningInfo> ResOrErr =
        Symbolizer.symbolizeInlinedCode(ModuleSpec, Address);
    Expected<DILineInfo> Res0OrErr =
        !ResOrErr
            ? Expected<DILineInfo>(ResOrErr.takeError())
            : ((ResOrErr->getNumberOfFrames() == 0) ? DILineInfo()
                                                    : ResOrErr->getFrame(0));
    print(SymRequest, Res0OrErr, Printer);
  } else {
    Expected<DILineInfo> ResOrErr =
        Symbolizer.symbolizeCode(ModuleSpec, Address);
    print(SymRequest, ResOrErr, Printer);
  }
  Symbolizer.pruneCache();
}

static void printUnknownLineInfo(std::string ModuleName, DIPrinter &Printer) {
  Request SymRequest = {ModuleName, std::nullopt, StringRef()};
  Printer.print(SymRequest, DILineInfo());
}

static void symbolizeInput(const opt::InputArgList &Args,
                           object::BuildIDRef IncomingBuildID,
                           uint64_t AdjustVMA, bool IsAddr2Line,
                           OutputStyle Style, StringRef InputString,
                           LLVMSymbolizer &Symbolizer, DIPrinter &Printer) {
  Command Cmd;
  std::string ModuleName;
  object::BuildID BuildID(IncomingBuildID.begin(), IncomingBuildID.end());
  uint64_t Offset = 0;
  StringRef Symbol;

  // An empty input string may be used to check if the process is alive and
  // responding to input. Do not emit a message on stderr in this case but
  // respond on stdout.
  if (InputString.empty()) {
    printUnknownLineInfo(ModuleName, Printer);
    return;
  }
  if (Error E = parseCommand(Args.getLastArgValue(OPT_obj_EQ), IsAddr2Line,
                             StringRef(InputString), Cmd, ModuleName, BuildID,
                             Symbol, Offset)) {
    handleAllErrors(std::move(E), [&](const StringError &EI) {
      printError(EI, InputString);
      printUnknownLineInfo(ModuleName, Printer);
    });
    return;
  }
  bool ShouldInline = Args.hasFlag(OPT_inlines, OPT_no_inlines, !IsAddr2Line);
  if (!BuildID.empty()) {
    assert(ModuleName.empty());
    if (!Args.hasArg(OPT_no_debuginfod))
      enableDebuginfod(Symbolizer, Args);
    std::string BuildIDStr = toHex(BuildID);
    executeCommand(BuildIDStr, BuildID, Cmd, Symbol, Offset, AdjustVMA,
                   ShouldInline, Style, Symbolizer, Printer);
  } else {
    executeCommand(ModuleName, ModuleName, Cmd, Symbol, Offset, AdjustVMA,
                   ShouldInline, Style, Symbolizer, Printer);
  }
}

static void printHelp(StringRef ToolName, const SymbolizerOptTable &Tbl,
                      raw_ostream &OS) {
  const char HelpText[] = " [options] addresses...";
  Tbl.printHelp(OS, (ToolName + HelpText).str().c_str(),
                ToolName.str().c_str());
  // TODO Replace this with OptTable API once it adds extrahelp support.
  OS << "\nPass @FILE as argument to read options from FILE.\n";
}

static opt::InputArgList parseOptions(int Argc, char *Argv[], bool IsAddr2Line,
                                      StringSaver &Saver,
                                      SymbolizerOptTable &Tbl) {
  StringRef ToolName = IsAddr2Line ? "llvm-addr2line" : "llvm-symbolizer";
  // The environment variable specifies initial options which can be overridden
  // by commnad line options.
  Tbl.setInitialOptionsFromEnvironment(IsAddr2Line ? "LLVM_ADDR2LINE_OPTS"
                                                   : "LLVM_SYMBOLIZER_OPTS");
  bool HasError = false;
  opt::InputArgList Args =
      Tbl.parseArgs(Argc, Argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
        errs() << ("error: " + Msg + "\n");
        HasError = true;
      });
  if (HasError)
    exit(1);
  if (Args.hasArg(OPT_help)) {
    printHelp(ToolName, Tbl, outs());
    exit(0);
  }
  if (Args.hasArg(OPT_version)) {
    outs() << ToolName << '\n';
    cl::PrintVersionMessage();
    exit(0);
  }

  return Args;
}

template <typename T>
static void parseIntArg(const opt::InputArgList &Args, int ID, T &Value) {
  if (const opt::Arg *A = Args.getLastArg(ID)) {
    StringRef V(A->getValue());
    if (!llvm::to_integer(V, Value, 0)) {
      errs() << A->getSpelling() +
                    ": expected a non-negative integer, but got '" + V + "'";
      exit(1);
    }
  } else {
    Value = 0;
  }
}

static FunctionNameKind decideHowToPrintFunctions(const opt::InputArgList &Args,
                                                  bool IsAddr2Line) {
  if (Args.hasArg(OPT_functions))
    return FunctionNameKind::LinkageName;
  if (const opt::Arg *A = Args.getLastArg(OPT_functions_EQ))
    return StringSwitch<FunctionNameKind>(A->getValue())
        .Case("none", FunctionNameKind::None)
        .Case("short", FunctionNameKind::ShortName)
        .Default(FunctionNameKind::LinkageName);
  return IsAddr2Line ? FunctionNameKind::None : FunctionNameKind::LinkageName;
}

static std::optional<bool> parseColorArg(const opt::InputArgList &Args) {
  if (Args.hasArg(OPT_color))
    return true;
  if (const opt::Arg *A = Args.getLastArg(OPT_color_EQ))
    return StringSwitch<std::optional<bool>>(A->getValue())
        .Case("always", true)
        .Case("never", false)
        .Case("auto", std::nullopt);
  return std::nullopt;
}

static object::BuildID parseBuildIDArg(const opt::InputArgList &Args, int ID) {
  const opt::Arg *A = Args.getLastArg(ID);
  if (!A)
    return {};

  StringRef V(A->getValue());
  object::BuildID BuildID = parseBuildID(V);
  if (BuildID.empty()) {
    errs() << A->getSpelling() + ": expected a build ID, but got '" + V + "'\n";
    exit(1);
  }
  return BuildID;
}

// Symbolize markup from stdin and write the result to stdout.
static void filterMarkup(const opt::InputArgList &Args, LLVMSymbolizer &Symbolizer) {
  MarkupFilter Filter(outs(), Symbolizer, parseColorArg(Args));
  std::string InputString;
  while (std::getline(std::cin, InputString)) {
    InputString += '\n';
    Filter.filter(std::move(InputString));
  }
  Filter.finish();
}

int llvm_symbolizer_main(int argc, char **argv, const llvm::ToolContext &) {
  sys::InitializeCOMRAII COM(sys::COMThreadingMode::MultiThreaded);

  ToolName = argv[0];
  bool IsAddr2Line = sys::path::stem(ToolName).contains("addr2line");
  BumpPtrAllocator A;
  StringSaver Saver(A);
  SymbolizerOptTable Tbl;
  opt::InputArgList Args = parseOptions(argc, argv, IsAddr2Line, Saver, Tbl);

  LLVMSymbolizer::Options Opts;
  uint64_t AdjustVMA;
  PrinterConfig Config;
  parseIntArg(Args, OPT_adjust_vma_EQ, AdjustVMA);
  if (const opt::Arg *A = Args.getLastArg(OPT_basenames, OPT_relativenames)) {
    Opts.PathStyle =
        A->getOption().matches(OPT_basenames)
            ? DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly
            : DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath;
  } else {
    Opts.PathStyle = DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
  }
  Opts.SkipLineZero = Args.hasArg(OPT_skip_line_zero);
  Opts.DebugFileDirectory = Args.getAllArgValues(OPT_debug_file_directory_EQ);
  Opts.DefaultArch = Args.getLastArgValue(OPT_default_arch_EQ).str();
  Opts.Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, !IsAddr2Line);
  Opts.DWPName = Args.getLastArgValue(OPT_dwp_EQ).str();
  Opts.FallbackDebugPath =
      Args.getLastArgValue(OPT_fallback_debug_path_EQ).str();
  Opts.GsymFileDirectory = Args.getAllArgValues(OPT_gsym_file_directory_EQ);
  Opts.DisableGsym = Args.hasArg(OPT_disable_gsym);
  Opts.PrintFunctions = decideHowToPrintFunctions(Args, IsAddr2Line);
  parseIntArg(Args, OPT_print_source_context_lines_EQ,
              Config.SourceContextLines);
  Opts.RelativeAddresses = Args.hasArg(OPT_relative_address);
  Opts.UntagAddresses =
      Args.hasFlag(OPT_untag_addresses, OPT_no_untag_addresses, !IsAddr2Line);
  Opts.UseDIA = Args.hasArg(OPT_use_dia);
#if !defined(LLVM_ENABLE_DIA_SDK)
  if (Opts.UseDIA) {
    WithColor::warning() << "DIA not available; using native PDB reader\n";
    Opts.UseDIA = false;
  }
#endif
  Opts.UseSymbolTable = true;
  if (Args.hasArg(OPT_cache_size_EQ))
    parseIntArg(Args, OPT_cache_size_EQ, Opts.MaxCacheSize);
  Config.PrintAddress = Args.hasArg(OPT_addresses);
  Config.PrintFunctions = Opts.PrintFunctions != FunctionNameKind::None;
  Config.Pretty = Args.hasArg(OPT_pretty_print);
  Config.Verbose = Args.hasArg(OPT_verbose);

  for (const opt::Arg *A : Args.filtered(OPT_dsym_hint_EQ)) {
    StringRef Hint(A->getValue());
    if (sys::path::extension(Hint) == ".dSYM") {
      Opts.DsymHints.emplace_back(Hint);
    } else {
      errs() << "Warning: invalid dSYM hint: \"" << Hint
             << "\" (must have the '.dSYM' extension).\n";
    }
  }

  LLVMSymbolizer Symbolizer(Opts);

  if (Args.hasFlag(OPT_debuginfod, OPT_no_debuginfod, canUseDebuginfod()))
    enableDebuginfod(Symbolizer, Args);

  if (Args.hasArg(OPT_filter_markup)) {
    filterMarkup(Args, Symbolizer);
    return 0;
  }

  auto Style = IsAddr2Line ? OutputStyle::GNU : OutputStyle::LLVM;
  if (const opt::Arg *A = Args.getLastArg(OPT_output_style_EQ)) {
    if (strcmp(A->getValue(), "GNU") == 0)
      Style = OutputStyle::GNU;
    else if (strcmp(A->getValue(), "JSON") == 0)
      Style = OutputStyle::JSON;
    else
      Style = OutputStyle::LLVM;
  }

  if (Args.hasArg(OPT_build_id_EQ) && Args.hasArg(OPT_obj_EQ)) {
    errs() << "error: cannot specify both --build-id and --obj\n";
    return EXIT_FAILURE;
  }
  object::BuildID BuildID = parseBuildIDArg(Args, OPT_build_id_EQ);

  std::unique_ptr<DIPrinter> Printer;
  if (Style == OutputStyle::GNU)
    Printer = std::make_unique<GNUPrinter>(outs(), printError, Config);
  else if (Style == OutputStyle::JSON)
    Printer = std::make_unique<JSONPrinter>(outs(), Config);
  else
    Printer = std::make_unique<LLVMPrinter>(outs(), printError, Config);

  // When an input file is specified, exit immediately if the file cannot be
  // read. If getOrCreateModuleInfo succeeds, symbolizeInput will reuse the
  // cached file handle.
  if (auto *Arg = Args.getLastArg(OPT_obj_EQ); Arg) {
    auto Status = Symbolizer.getOrCreateModuleInfo(Arg->getValue());
    if (!Status) {
      Request SymRequest = {Arg->getValue(), 0, StringRef()};
      handleAllErrors(Status.takeError(), [&](const ErrorInfoBase &EI) {
        Printer->printError(SymRequest, EI);
      });
      return EXIT_FAILURE;
    }
  }

  std::vector<std::string> InputAddresses = Args.getAllArgValues(OPT_INPUT);
  if (InputAddresses.empty()) {
    const int kMaxInputStringLength = 1024;
    char InputString[kMaxInputStringLength];

    while (fgets(InputString, sizeof(InputString), stdin)) {
      // Strip newline characters.
      std::string StrippedInputString(InputString);
      llvm::erase_if(StrippedInputString,
                     [](char c) { return c == '\r' || c == '\n'; });
      symbolizeInput(Args, BuildID, AdjustVMA, IsAddr2Line, Style,
                     StrippedInputString, Symbolizer, *Printer);
      outs().flush();
    }
  } else {
    Printer->listBegin();
    for (StringRef Address : InputAddresses)
      symbolizeInput(Args, BuildID, AdjustVMA, IsAddr2Line, Style, Address,
                     Symbolizer, *Printer);
    Printer->listEnd();
  }

  return 0;
}
