brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · 1467093 Raw
200 lines · cpp
1//===-- llvm-c++filt.cpp --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/StringExtras.h"10#include "llvm/Demangle/Demangle.h"11#include "llvm/Demangle/StringViewExtras.h"12#include "llvm/Option/Arg.h"13#include "llvm/Option/ArgList.h"14#include "llvm/Option/Option.h"15#include "llvm/Support/CommandLine.h"16#include "llvm/Support/LLVMDriver.h"17#include "llvm/Support/WithColor.h"18#include "llvm/Support/raw_ostream.h"19#include "llvm/TargetParser/Host.h"20#include "llvm/TargetParser/Triple.h"21#include <cstdlib>22#include <iostream>23 24using namespace llvm;25 26namespace {27enum ID {28  OPT_INVALID = 0, // This is not an option ID.29#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),30#include "Opts.inc"31#undef OPTION32};33 34#define OPTTABLE_STR_TABLE_CODE35#include "Opts.inc"36#undef OPTTABLE_STR_TABLE_CODE37 38#define OPTTABLE_PREFIXES_TABLE_CODE39#include "Opts.inc"40#undef OPTTABLE_PREFIXES_TABLE_CODE41 42using namespace llvm::opt;43static constexpr opt::OptTable::Info InfoTable[] = {44#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),45#include "Opts.inc"46#undef OPTION47};48 49class CxxfiltOptTable : public opt::GenericOptTable {50public:51  CxxfiltOptTable()52      : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, InfoTable) {53    setGroupedShortOptions(true);54  }55};56} // namespace57 58static bool ParseParams;59static bool Quote;60static bool StripUnderscore;61static bool Types;62 63static StringRef ToolName;64 65static void error(const Twine &Message) {66  WithColor::error(errs(), ToolName) << Message << '\n';67  exit(1);68}69 70// Quote Undecorated with "" if asked for and not already followed by a '"'.71static std::string optionalQuote(const std::string &Undecorated,72                                 StringRef Delimiters) {73  if (Quote && (Delimiters.empty() || Delimiters[0] != '"'))74    return '"' + Undecorated + '"';75  return Undecorated;76}77 78static std::string demangle(const std::string &Mangled, StringRef Delimiters) {79  using llvm::itanium_demangle::starts_with;80  std::string_view DecoratedStr = Mangled;81  bool CanHaveLeadingDot = true;82  if (StripUnderscore && DecoratedStr[0] == '_') {83    DecoratedStr.remove_prefix(1);84    CanHaveLeadingDot = false;85  }86 87  std::string Result;88  if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot,89                           ParseParams))90    return optionalQuote(Result, Delimiters);91 92  std::string Prefix;93  char *Undecorated = nullptr;94 95  if (Types)96    Undecorated = itaniumDemangle(DecoratedStr, ParseParams);97 98  if (!Undecorated && starts_with(DecoratedStr, "__imp_")) {99    Prefix = "import thunk for ";100    Undecorated = itaniumDemangle(DecoratedStr.substr(6), ParseParams);101  }102 103  Result =104      Undecorated ? optionalQuote(Prefix + Undecorated, Delimiters) : Mangled;105  free(Undecorated);106  return Result;107}108 109// Split 'Source' on any character that fails to pass 'IsLegalChar'.  The110// returned vector consists of pairs where 'first' is the delimited word, and111// 'second' are the delimiters following that word.112static void SplitStringDelims(113    StringRef Source,114    SmallVectorImpl<std::pair<StringRef, StringRef>> &OutFragments,115    function_ref<bool(char)> IsLegalChar) {116  // The beginning of the input string.117  const auto Head = Source.begin();118 119  // Obtain any leading delimiters.120  auto Start = std::find_if(Head, Source.end(), IsLegalChar);121  if (Start != Head)122    OutFragments.push_back({"", Source.slice(0, Start - Head)});123 124  // Capture each word and the delimiters following that word.125  while (Start != Source.end()) {126    Start = std::find_if(Start, Source.end(), IsLegalChar);127    auto End = std::find_if_not(Start, Source.end(), IsLegalChar);128    auto DEnd = std::find_if(End, Source.end(), IsLegalChar);129    OutFragments.push_back({Source.slice(Start - Head, End - Head),130                            Source.slice(End - Head, DEnd - Head)});131    Start = DEnd;132  }133}134 135// This returns true if 'C' is a character that can show up in an136// Itanium-mangled string.137static bool IsLegalItaniumChar(char C) {138  // Itanium CXX ABI [External Names]p5.1.1:139  // '$' and '.' in mangled names are reserved for private implementations.140  return isAlnum(C) || C == '.' || C == '$' || C == '_';141}142 143// If 'Split' is true, then 'Mangled' is broken into individual words and each144// word is demangled.  Otherwise, the entire string is treated as a single145// mangled item.  The result is output to 'OS'.146static void demangleLine(llvm::raw_ostream &OS, StringRef Mangled, bool Split) {147  std::string Result;148  if (Split) {149    SmallVector<std::pair<StringRef, StringRef>, 16> Words;150    SplitStringDelims(Mangled, Words, IsLegalItaniumChar);151    for (const auto &Word : Words)152      Result +=153          ::demangle(std::string(Word.first), Word.second) + Word.second.str();154  } else155    Result = ::demangle(std::string(Mangled), "");156  OS << Result << '\n';157  OS.flush();158}159 160int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) {161  BumpPtrAllocator A;162  StringSaver Saver(A);163  CxxfiltOptTable Tbl;164  ToolName = argv[0];165  opt::InputArgList Args = Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver,166                                         [&](StringRef Msg) { error(Msg); });167  if (Args.hasArg(OPT_help)) {168    Tbl.printHelp(outs(),169                  (Twine(ToolName) + " [options] <mangled>").str().c_str(),170                  "LLVM symbol undecoration tool");171    // TODO Replace this with OptTable API once it adds extrahelp support.172    outs() << "\nPass @FILE as argument to read options from FILE.\n";173    return 0;174  }175  if (Args.hasArg(OPT_version)) {176    outs() << ToolName << '\n';177    cl::PrintVersionMessage();178    return 0;179  }180 181  StripUnderscore =182      Args.hasFlag(OPT_strip_underscore, OPT_no_strip_underscore, false);183 184  ParseParams = !Args.hasArg(OPT_no_params);185 186  Quote = Args.hasArg(OPT_quote);187 188  Types = Args.hasArg(OPT_types);189 190  std::vector<std::string> Decorated = Args.getAllArgValues(OPT_INPUT);191  if (Decorated.empty())192    for (std::string Mangled; std::getline(std::cin, Mangled);)193      demangleLine(llvm::outs(), Mangled, true);194  else195    for (const auto &Symbol : Decorated)196      demangleLine(llvm::outs(), Symbol, false);197 198  return EXIT_SUCCESS;199}200