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