SymbolMap.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. //===- tools/dsymutil/SymbolMap.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 "SymbolMap.h"
  9. #include "DebugMap.h"
  10. #include "MachOUtils.h"
  11. #include "llvm/Support/FileSystem.h"
  12. #include "llvm/Support/Path.h"
  13. #include "llvm/Support/WithColor.h"
  14. #ifdef __APPLE__
  15. #include <CoreFoundation/CoreFoundation.h>
  16. #include <uuid/uuid.h>
  17. #endif
  18. namespace llvm {
  19. namespace dsymutil {
  20. StringRef SymbolMapTranslator::operator()(StringRef Input) {
  21. if (!Input.startswith("__hidden#") && !Input.startswith("___hidden#"))
  22. return Input;
  23. bool MightNeedUnderscore = false;
  24. StringRef Line = Input.drop_front(sizeof("__hidden#") - 1);
  25. if (Line[0] == '#') {
  26. Line = Line.drop_front();
  27. MightNeedUnderscore = true;
  28. }
  29. std::size_t LineNumber = std::numeric_limits<std::size_t>::max();
  30. Line.split('_').first.getAsInteger(10, LineNumber);
  31. if (LineNumber >= UnobfuscatedStrings.size()) {
  32. WithColor::warning() << "reference to a unexisting unobfuscated string "
  33. << Input << ": symbol map mismatch?\n"
  34. << Line << '\n';
  35. return Input;
  36. }
  37. const std::string &Translation = UnobfuscatedStrings[LineNumber];
  38. if (!MightNeedUnderscore || !MangleNames)
  39. return Translation;
  40. // Objective-C symbols for the MachO symbol table start with a \1. Please see
  41. // `MangleContext::mangleObjCMethodName` in clang.
  42. if (Translation[0] == 1)
  43. return StringRef(Translation).drop_front();
  44. // We need permanent storage for the string we are about to create. Just
  45. // append it to the vector containing translations. This should only happen
  46. // during MachO symbol table translation, thus there should be no risk on
  47. // exponential growth.
  48. UnobfuscatedStrings.emplace_back("_" + Translation);
  49. return UnobfuscatedStrings.back();
  50. }
  51. SymbolMapTranslator SymbolMapLoader::Load(StringRef InputFile,
  52. const DebugMap &Map) const {
  53. if (SymbolMap.empty())
  54. return {};
  55. std::string SymbolMapPath = SymbolMap;
  56. #if __APPLE__
  57. // Look through the UUID Map.
  58. if (sys::fs::is_directory(SymbolMapPath) && !Map.getUUID().empty()) {
  59. uuid_string_t UUIDString;
  60. uuid_unparse_upper((const uint8_t *)Map.getUUID().data(), UUIDString);
  61. SmallString<256> PlistPath(
  62. sys::path::parent_path(sys::path::parent_path(InputFile)));
  63. sys::path::append(PlistPath, StringRef(UUIDString).str() + ".plist");
  64. CFStringRef plistFile = CFStringCreateWithCString(
  65. kCFAllocatorDefault, PlistPath.c_str(), kCFStringEncodingUTF8);
  66. CFURLRef fileURL = CFURLCreateWithFileSystemPath(
  67. kCFAllocatorDefault, plistFile, kCFURLPOSIXPathStyle, false);
  68. CFReadStreamRef resourceData =
  69. CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
  70. if (resourceData) {
  71. CFReadStreamOpen(resourceData);
  72. CFDictionaryRef plist = (CFDictionaryRef)CFPropertyListCreateWithStream(
  73. kCFAllocatorDefault, resourceData, 0, kCFPropertyListImmutable,
  74. nullptr, nullptr);
  75. if (plist) {
  76. if (CFDictionaryContainsKey(plist, CFSTR("DBGOriginalUUID"))) {
  77. CFStringRef OldUUID = (CFStringRef)CFDictionaryGetValue(
  78. plist, CFSTR("DBGOriginalUUID"));
  79. StringRef UUID(CFStringGetCStringPtr(OldUUID, kCFStringEncodingUTF8));
  80. SmallString<256> BCSymbolMapPath(SymbolMapPath);
  81. sys::path::append(BCSymbolMapPath, UUID.str() + ".bcsymbolmap");
  82. SymbolMapPath = std::string(BCSymbolMapPath);
  83. }
  84. CFRelease(plist);
  85. }
  86. CFReadStreamClose(resourceData);
  87. CFRelease(resourceData);
  88. }
  89. CFRelease(fileURL);
  90. CFRelease(plistFile);
  91. }
  92. #endif
  93. if (sys::fs::is_directory(SymbolMapPath)) {
  94. SymbolMapPath += (Twine("/") + sys::path::filename(InputFile) + "-" +
  95. MachOUtils::getArchName(Map.getTriple().getArchName()) +
  96. ".bcsymbolmap")
  97. .str();
  98. }
  99. auto ErrOrMemBuffer = MemoryBuffer::getFile(SymbolMapPath);
  100. if (auto EC = ErrOrMemBuffer.getError()) {
  101. WithColor::warning() << SymbolMapPath << ": " << EC.message()
  102. << ": not unobfuscating.\n";
  103. return {};
  104. }
  105. std::vector<std::string> UnobfuscatedStrings;
  106. auto &MemBuf = **ErrOrMemBuffer;
  107. StringRef Data(MemBuf.getBufferStart(),
  108. MemBuf.getBufferEnd() - MemBuf.getBufferStart());
  109. StringRef LHS;
  110. std::tie(LHS, Data) = Data.split('\n');
  111. bool MangleNames = false;
  112. // Check version string first.
  113. if (!LHS.startswith("BCSymbolMap Version:")) {
  114. // Version string not present, warns but try to parse it.
  115. WithColor::warning() << SymbolMapPath
  116. << " is missing version string: assuming 1.0.\n";
  117. UnobfuscatedStrings.emplace_back(LHS);
  118. } else if (LHS.equals("BCSymbolMap Version: 1.0")) {
  119. MangleNames = true;
  120. } else if (LHS.equals("BCSymbolMap Version: 2.0")) {
  121. MangleNames = false;
  122. } else {
  123. StringRef VersionNum;
  124. std::tie(LHS, VersionNum) = LHS.split(':');
  125. WithColor::warning() << SymbolMapPath
  126. << " has unsupported symbol map version" << VersionNum
  127. << ": not unobfuscating.\n";
  128. return {};
  129. }
  130. while (!Data.empty()) {
  131. std::tie(LHS, Data) = Data.split('\n');
  132. UnobfuscatedStrings.emplace_back(LHS);
  133. }
  134. return SymbolMapTranslator(std::move(UnobfuscatedStrings), MangleNames);
  135. }
  136. } // namespace dsymutil
  137. } // namespace llvm