llvm-cxxfilt.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ADT/StringExtras.h"
  9. #include "llvm/ADT/Triple.h"
  10. #include "llvm/Demangle/Demangle.h"
  11. #include "llvm/Support/CommandLine.h"
  12. #include "llvm/Support/Host.h"
  13. #include "llvm/Support/InitLLVM.h"
  14. #include "llvm/Support/raw_ostream.h"
  15. #include <cstdlib>
  16. #include <iostream>
  17. using namespace llvm;
  18. enum Style {
  19. Auto, ///< auto-detect mangling
  20. GNU, ///< GNU
  21. Lucid, ///< Lucid compiler (lcc)
  22. ARM,
  23. HP, ///< HP compiler (xCC)
  24. EDG, ///< EDG compiler
  25. GNUv3, ///< GNU C++ v3 ABI
  26. Java, ///< Java (gcj)
  27. GNAT ///< ADA compiler (gnat)
  28. };
  29. static cl::opt<Style>
  30. Format("format", cl::desc("decoration style"),
  31. cl::values(clEnumValN(Auto, "auto", "auto-detect style"),
  32. clEnumValN(GNU, "gnu", "GNU (itanium) style")),
  33. cl::init(Auto));
  34. static cl::alias FormatShort("s", cl::desc("alias for --format"),
  35. cl::aliasopt(Format));
  36. static cl::opt<bool> StripUnderscore("strip-underscore",
  37. cl::desc("strip the leading underscore"),
  38. cl::init(false));
  39. static cl::alias StripUnderscoreShort("_",
  40. cl::desc("alias for --strip-underscore"),
  41. cl::aliasopt(StripUnderscore));
  42. static cl::opt<bool>
  43. NoStripUnderscore("no-strip-underscore",
  44. cl::desc("do not strip the leading underscore"),
  45. cl::init(false));
  46. static cl::alias
  47. NoStripUnderscoreShort("n", cl::desc("alias for --no-strip-underscore"),
  48. cl::aliasopt(NoStripUnderscore));
  49. static cl::opt<bool>
  50. Types("types",
  51. cl::desc("attempt to demangle types as well as function names"),
  52. cl::init(false));
  53. static cl::alias TypesShort("t", cl::desc("alias for --types"),
  54. cl::aliasopt(Types));
  55. static cl::list<std::string>
  56. Decorated(cl::Positional, cl::desc("<mangled>"), cl::ZeroOrMore);
  57. static cl::extrahelp
  58. HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
  59. static bool shouldStripUnderscore() {
  60. if (StripUnderscore)
  61. return true;
  62. if (NoStripUnderscore)
  63. return false;
  64. // If none of them are set, use the default value for platform.
  65. // macho has symbols prefix with "_" so strip by default.
  66. return Triple(sys::getProcessTriple()).isOSBinFormatMachO();
  67. }
  68. static std::string demangle(const std::string &Mangled) {
  69. int Status;
  70. std::string Prefix;
  71. const char *DecoratedStr = Mangled.c_str();
  72. if (shouldStripUnderscore())
  73. if (DecoratedStr[0] == '_')
  74. ++DecoratedStr;
  75. size_t DecoratedLength = strlen(DecoratedStr);
  76. char *Undecorated = nullptr;
  77. if (Types ||
  78. ((DecoratedLength >= 2 && strncmp(DecoratedStr, "_Z", 2) == 0) ||
  79. (DecoratedLength >= 4 && strncmp(DecoratedStr, "___Z", 4) == 0)))
  80. Undecorated = itaniumDemangle(DecoratedStr, nullptr, nullptr, &Status);
  81. if (!Undecorated &&
  82. (DecoratedLength > 6 && strncmp(DecoratedStr, "__imp_", 6) == 0)) {
  83. Prefix = "import thunk for ";
  84. Undecorated = itaniumDemangle(DecoratedStr + 6, nullptr, nullptr, &Status);
  85. }
  86. std::string Result(Undecorated ? Prefix + Undecorated : Mangled);
  87. free(Undecorated);
  88. return Result;
  89. }
  90. // Split 'Source' on any character that fails to pass 'IsLegalChar'. The
  91. // returned vector consists of pairs where 'first' is the delimited word, and
  92. // 'second' are the delimiters following that word.
  93. static void SplitStringDelims(
  94. StringRef Source,
  95. SmallVectorImpl<std::pair<StringRef, StringRef>> &OutFragments,
  96. function_ref<bool(char)> IsLegalChar) {
  97. // The beginning of the input string.
  98. const auto Head = Source.begin();
  99. // Obtain any leading delimiters.
  100. auto Start = std::find_if(Head, Source.end(), IsLegalChar);
  101. if (Start != Head)
  102. OutFragments.push_back({"", Source.slice(0, Start - Head)});
  103. // Capture each word and the delimiters following that word.
  104. while (Start != Source.end()) {
  105. Start = std::find_if(Start, Source.end(), IsLegalChar);
  106. auto End = std::find_if_not(Start, Source.end(), IsLegalChar);
  107. auto DEnd = std::find_if(End, Source.end(), IsLegalChar);
  108. OutFragments.push_back({Source.slice(Start - Head, End - Head),
  109. Source.slice(End - Head, DEnd - Head)});
  110. Start = DEnd;
  111. }
  112. }
  113. // This returns true if 'C' is a character that can show up in an
  114. // Itanium-mangled string.
  115. static bool IsLegalItaniumChar(char C) {
  116. // Itanium CXX ABI [External Names]p5.1.1:
  117. // '$' and '.' in mangled names are reserved for private implementations.
  118. return isalnum(C) || C == '.' || C == '$' || C == '_';
  119. }
  120. // If 'Split' is true, then 'Mangled' is broken into individual words and each
  121. // word is demangled. Otherwise, the entire string is treated as a single
  122. // mangled item. The result is output to 'OS'.
  123. static void demangleLine(llvm::raw_ostream &OS, StringRef Mangled, bool Split) {
  124. std::string Result;
  125. if (Split) {
  126. SmallVector<std::pair<StringRef, StringRef>, 16> Words;
  127. SplitStringDelims(Mangled, Words, IsLegalItaniumChar);
  128. for (const auto &Word : Words)
  129. Result += ::demangle(std::string(Word.first)) + Word.second.str();
  130. } else
  131. Result = ::demangle(std::string(Mangled));
  132. OS << Result << '\n';
  133. OS.flush();
  134. }
  135. int main(int argc, char **argv) {
  136. InitLLVM X(argc, argv);
  137. cl::ParseCommandLineOptions(argc, argv, "llvm symbol undecoration tool\n");
  138. if (Decorated.empty())
  139. for (std::string Mangled; std::getline(std::cin, Mangled);)
  140. demangleLine(llvm::outs(), Mangled, true);
  141. else
  142. for (const auto &Symbol : Decorated)
  143. demangleLine(llvm::outs(), Symbol, false);
  144. return EXIT_SUCCESS;
  145. }