aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/dsymutil
diff options
context:
space:
mode:
authorAndres Villegas <andresvi@google.com>2024-03-19 10:58:31 -0700
committerGitHub <noreply@github.com>2024-03-19 13:58:31 -0400
commit3176c157190c80b4279dec86c4b9b84472d8ccac (patch)
tree31751c0814ab695cf76a6ab63ca23d7612c04512 /llvm/tools/dsymutil
parent4bade55cc65db8b7f977dba4f13bf335e93317a8 (diff)
downloadllvm-3176c157190c80b4279dec86c4b9b84472d8ccac.zip
llvm-3176c157190c80b4279dec86c4b9b84472d8ccac.tar.gz
llvm-3176c157190c80b4279dec86c4b9b84472d8ccac.tar.bz2
Revert "[dsymutil] Remove support for obfuscated bitcode" (#85826)
Reverts llvm/llvm-project#85713 Since it is breaking Linux x64 builds.
Diffstat (limited to 'llvm/tools/dsymutil')
-rw-r--r--llvm/tools/dsymutil/CMakeLists.txt1
-rw-r--r--llvm/tools/dsymutil/DwarfLinkerForBinary.cpp14
-rw-r--r--llvm/tools/dsymutil/LinkUtils.h5
-rw-r--r--llvm/tools/dsymutil/MachOUtils.cpp7
-rw-r--r--llvm/tools/dsymutil/MachOUtils.h4
-rw-r--r--llvm/tools/dsymutil/Options.td6
-rw-r--r--llvm/tools/dsymutil/SymbolMap.cpp157
-rw-r--r--llvm/tools/dsymutil/SymbolMap.h53
-rw-r--r--llvm/tools/dsymutil/dsymutil.cpp15
9 files changed, 254 insertions, 8 deletions
diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt
index efe28bd..53f882e 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -32,6 +32,7 @@ add_llvm_tool(dsymutil
MachOUtils.cpp
Reproducer.cpp
RelocationMap.cpp
+ SymbolMap.cpp
DEPENDS
intrinsics_gen
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 677dfc4..5ae5ecd 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -634,19 +634,25 @@ bool DwarfLinkerForBinary::linkImpl(
DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
+ std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) {
+ assert(Options.Translator);
+ return Options.Translator(Input);
+ };
+
std::unique_ptr<Linker> GeneralLinker = Linker::createLinker(
[&](const Twine &Error, StringRef Context, const DWARFDie *DIE) {
reportError(Error, Context, DIE);
},
[&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) {
reportWarning(Warning, Context, DIE);
- });
+ },
+ Options.Translator ? TranslationLambda : nullptr);
std::unique_ptr<classic::DwarfStreamer> Streamer;
if (!Options.NoOutput) {
if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr =
classic::DwarfStreamer::createStreamer(
- Map.getTriple(), ObjectType, OutFile,
+ Map.getTriple(), ObjectType, OutFile, Options.Translator,
[&](const Twine &Warning, StringRef Context,
const DWARFDie *DIE) {
reportWarning(Warning, Context, DIE);
@@ -860,8 +866,8 @@ bool DwarfLinkerForBinary::linkImpl(
if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() &&
ObjectType == Linker::OutputFileType::Object)
return MachOUtils::generateDsymCompanion(
- Options.VFS, Map, *Streamer->getAsmPrinter().OutStreamer, OutFile,
- RelocationsToApply);
+ Options.VFS, Map, Options.Translator,
+ *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply);
Streamer->finish();
return true;
diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h
index 6aa0b84..fd9d985 100644
--- a/llvm/tools/dsymutil/LinkUtils.h
+++ b/llvm/tools/dsymutil/LinkUtils.h
@@ -9,6 +9,8 @@
#ifndef LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
#define LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
+#include "SymbolMap.h"
+
#include "llvm/ADT/Twine.h"
#include "llvm/Remarks/RemarkFormat.h"
#include "llvm/Support/VirtualFileSystem.h"
@@ -85,6 +87,9 @@ struct LinkOptions {
/// The Resources directory in the .dSYM bundle.
std::optional<std::string> ResourceDir;
+ /// Symbol map translator.
+ SymbolMapTranslator Translator;
+
/// Virtual File System.
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
vfs::getRealFileSystem();
diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp
index 8e144d6..3efc1af 100644
--- a/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/llvm/tools/dsymutil/MachOUtils.cpp
@@ -373,7 +373,7 @@ static unsigned segmentLoadCommandSize(bool Is64Bit, unsigned NumSections) {
// \a OutFile and it must be using a MachObjectWriter object to do so.
bool generateDsymCompanion(
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM,
- MCStreamer &MS, raw_fd_ostream &OutFile,
+ SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile,
const std::vector<MachOUtils::DwarfRelocationApplicationInfo>
&RelocationsToApply) {
auto &ObjectStreamer = static_cast<MCObjectStreamer &>(MS);
@@ -509,9 +509,12 @@ bool generateDsymCompanion(
}
SmallString<0> NewSymtab;
+ std::function<StringRef(StringRef)> TranslationLambda =
+ Translator ? [&](StringRef Input) { return Translator(Input); }
+ : static_cast<std::function<StringRef(StringRef)>>(nullptr);
// Legacy dsymutil puts an empty string at the start of the line table.
// thus we set NonRelocatableStringpool(,PutEmptyString=true)
- NonRelocatableStringpool NewStrings(true);
+ NonRelocatableStringpool NewStrings(TranslationLambda, true);
unsigned NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
unsigned NumSyms = 0;
uint64_t NewStringsSize = 0;
diff --git a/llvm/tools/dsymutil/MachOUtils.h b/llvm/tools/dsymutil/MachOUtils.h
index 0229647..059d9fd 100644
--- a/llvm/tools/dsymutil/MachOUtils.h
+++ b/llvm/tools/dsymutil/MachOUtils.h
@@ -8,6 +8,8 @@
#ifndef LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
#define LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
+#include "SymbolMap.h"
+
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/VirtualFileSystem.h"
@@ -57,7 +59,7 @@ bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
StringRef SDKPath, bool Fat64 = false);
bool generateDsymCompanion(
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM,
- MCStreamer &MS, raw_fd_ostream &OutFile,
+ SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile,
const std::vector<MachOUtils::DwarfRelocationApplicationInfo>
&RelocationsToApply);
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index d8cec0c..a4e4c6c 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -128,6 +128,12 @@ def object_prefix_map: Separate<["--", "-"], "object-prefix-map">,
Group<grp_general>;
def: Joined<["--", "-"], "object-prefix-map=">, Alias<object_prefix_map>;
+def symbolmap: Separate<["--", "-"], "symbol-map">,
+ MetaVarName<"<bcsymbolmap>">,
+ HelpText<"Updates the existing dSYMs inplace using symbol map specified.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "symbol-map=">, Alias<symbolmap>;
+
def arch: Separate<["--", "-"], "arch">,
MetaVarName<"<arch>">,
HelpText<"Link DWARF debug information only for specified CPU architecture"
diff --git a/llvm/tools/dsymutil/SymbolMap.cpp b/llvm/tools/dsymutil/SymbolMap.cpp
new file mode 100644
index 0000000..c55362e
--- /dev/null
+++ b/llvm/tools/dsymutil/SymbolMap.cpp
@@ -0,0 +1,157 @@
+//===- tools/dsymutil/SymbolMap.cpp ---------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolMap.h"
+#include "DebugMap.h"
+#include "MachOUtils.h"
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/WithColor.h"
+
+#ifdef __APPLE__
+#include <CoreFoundation/CoreFoundation.h>
+#include <uuid/uuid.h>
+#endif
+
+namespace llvm {
+namespace dsymutil {
+
+StringRef SymbolMapTranslator::operator()(StringRef Input) {
+ if (!Input.starts_with("__hidden#") && !Input.starts_with("___hidden#"))
+ return Input;
+
+ StringRef Line = Input.drop_front(sizeof("__hidden#") - 1);
+ bool MightNeedUnderscore = Line.consume_front("#");
+
+ std::size_t LineNumber = std::numeric_limits<std::size_t>::max();
+ Line.split('_').first.getAsInteger(10, LineNumber);
+ if (LineNumber >= UnobfuscatedStrings.size()) {
+ WithColor::warning() << "reference to a unexisting unobfuscated string "
+ << Input << ": symbol map mismatch?\n"
+ << Line << '\n';
+ return Input;
+ }
+
+ const std::string &Translation = UnobfuscatedStrings[LineNumber];
+ if (!MightNeedUnderscore || !MangleNames)
+ return Translation;
+
+ // Objective-C symbols for the MachO symbol table start with a \1. Please see
+ // `MangleContext::mangleObjCMethodName` in clang.
+ if (Translation[0] == 1)
+ return StringRef(Translation).drop_front();
+
+ // We need permanent storage for the string we are about to create. Just
+ // append it to the vector containing translations. This should only happen
+ // during MachO symbol table translation, thus there should be no risk on
+ // exponential growth.
+ UnobfuscatedStrings.emplace_back("_" + Translation);
+ return UnobfuscatedStrings.back();
+}
+
+SymbolMapTranslator SymbolMapLoader::Load(StringRef InputFile,
+ const DebugMap &Map) const {
+ if (SymbolMap.empty())
+ return {};
+
+ std::string SymbolMapPath = SymbolMap;
+
+#if __APPLE__
+ // Look through the UUID Map.
+ if (sys::fs::is_directory(SymbolMapPath) && !Map.getUUID().empty()) {
+ uuid_string_t UUIDString;
+ uuid_unparse_upper((const uint8_t *)Map.getUUID().data(), UUIDString);
+
+ SmallString<256> PlistPath(
+ sys::path::parent_path(sys::path::parent_path(InputFile)));
+ sys::path::append(PlistPath, StringRef(UUIDString).str() + ".plist");
+
+ CFStringRef plistFile = CFStringCreateWithCString(
+ kCFAllocatorDefault, PlistPath.c_str(), kCFStringEncodingUTF8);
+ CFURLRef fileURL = CFURLCreateWithFileSystemPath(
+ kCFAllocatorDefault, plistFile, kCFURLPOSIXPathStyle, false);
+ CFReadStreamRef resourceData =
+ CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
+ if (resourceData) {
+ CFReadStreamOpen(resourceData);
+ CFDictionaryRef plist = (CFDictionaryRef)CFPropertyListCreateWithStream(
+ kCFAllocatorDefault, resourceData, 0, kCFPropertyListImmutable,
+ nullptr, nullptr);
+
+ if (plist) {
+ if (CFDictionaryContainsKey(plist, CFSTR("DBGOriginalUUID"))) {
+ CFStringRef OldUUID = (CFStringRef)CFDictionaryGetValue(
+ plist, CFSTR("DBGOriginalUUID"));
+
+ StringRef UUID(CFStringGetCStringPtr(OldUUID, kCFStringEncodingUTF8));
+ SmallString<256> BCSymbolMapPath(SymbolMapPath);
+ sys::path::append(BCSymbolMapPath, UUID.str() + ".bcsymbolmap");
+ SymbolMapPath = std::string(BCSymbolMapPath);
+ }
+ CFRelease(plist);
+ }
+ CFReadStreamClose(resourceData);
+ CFRelease(resourceData);
+ }
+ CFRelease(fileURL);
+ CFRelease(plistFile);
+ }
+#endif
+
+ if (sys::fs::is_directory(SymbolMapPath)) {
+ SymbolMapPath += (Twine("/") + sys::path::filename(InputFile) + "-" +
+ MachOUtils::getArchName(Map.getTriple().getArchName()) +
+ ".bcsymbolmap")
+ .str();
+ }
+
+ auto ErrOrMemBuffer = MemoryBuffer::getFile(SymbolMapPath);
+ if (auto EC = ErrOrMemBuffer.getError()) {
+ WithColor::warning() << SymbolMapPath << ": " << EC.message()
+ << ": not unobfuscating.\n";
+ return {};
+ }
+
+ std::vector<std::string> UnobfuscatedStrings;
+ auto &MemBuf = **ErrOrMemBuffer;
+ StringRef Data(MemBuf.getBufferStart(),
+ MemBuf.getBufferEnd() - MemBuf.getBufferStart());
+ StringRef LHS;
+ std::tie(LHS, Data) = Data.split('\n');
+ bool MangleNames = false;
+
+ // Check version string first.
+ if (!LHS.starts_with("BCSymbolMap Version:")) {
+ // Version string not present, warns but try to parse it.
+ WithColor::warning() << SymbolMapPath
+ << " is missing version string: assuming 1.0.\n";
+ UnobfuscatedStrings.emplace_back(LHS);
+ } else if (LHS.equals("BCSymbolMap Version: 1.0")) {
+ MangleNames = true;
+ } else if (LHS.equals("BCSymbolMap Version: 2.0")) {
+ MangleNames = false;
+ } else {
+ StringRef VersionNum;
+ std::tie(LHS, VersionNum) = LHS.split(':');
+ WithColor::warning() << SymbolMapPath
+ << " has unsupported symbol map version" << VersionNum
+ << ": not unobfuscating.\n";
+ return {};
+ }
+
+ while (!Data.empty()) {
+ std::tie(LHS, Data) = Data.split('\n');
+ UnobfuscatedStrings.emplace_back(LHS);
+ }
+
+ return SymbolMapTranslator(std::move(UnobfuscatedStrings), MangleNames);
+}
+
+} // namespace dsymutil
+} // namespace llvm
diff --git a/llvm/tools/dsymutil/SymbolMap.h b/llvm/tools/dsymutil/SymbolMap.h
new file mode 100644
index 0000000..977de31
--- /dev/null
+++ b/llvm/tools/dsymutil/SymbolMap.h
@@ -0,0 +1,53 @@
+//=- tools/dsymutil/SymbolMap.h -----------------------------------*- C++ -*-=//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
+#define LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace dsymutil {
+class DebugMap;
+
+/// Callable class to unobfuscate strings based on a BCSymbolMap.
+class SymbolMapTranslator {
+public:
+ SymbolMapTranslator() : MangleNames(false) {}
+
+ SymbolMapTranslator(std::vector<std::string> UnobfuscatedStrings,
+ bool MangleNames)
+ : UnobfuscatedStrings(std::move(UnobfuscatedStrings)),
+ MangleNames(MangleNames) {}
+
+ StringRef operator()(StringRef Input);
+
+ operator bool() const { return !UnobfuscatedStrings.empty(); }
+
+private:
+ std::vector<std::string> UnobfuscatedStrings;
+ bool MangleNames;
+};
+
+/// Class to initialize SymbolMapTranslators from a BCSymbolMap.
+class SymbolMapLoader {
+public:
+ SymbolMapLoader(std::string SymbolMap) : SymbolMap(std::move(SymbolMap)) {}
+
+ SymbolMapTranslator Load(StringRef InputFile, const DebugMap &Map) const;
+
+private:
+ const std::string SymbolMap;
+};
+} // namespace dsymutil
+} // namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index bc968b6..25e281c 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -108,6 +108,7 @@ struct DsymutilOptions {
bool Flat = false;
bool InputIsYAMLDebugMap = false;
bool ForceKeepFunctionForStatic = false;
+ std::string SymbolMap;
std::string OutputFile;
std::string Toolchain;
std::string ReproducerPath;
@@ -340,6 +341,12 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
return DWARFLinkerType.takeError();
}
+ if (opt::Arg *SymbolMap = Args.getLastArg(OPT_symbolmap))
+ Options.SymbolMap = SymbolMap->getValue();
+
+ if (Args.hasArg(OPT_symbolmap))
+ Options.LinkOpts.Update = true;
+
if (Expected<std::vector<std::string>> InputFiles =
getInputs(Args, Options.LinkOpts.Update)) {
Options.InputFiles = std::move(*InputFiles);
@@ -553,7 +560,8 @@ getOutputFileName(StringRef InputFile, const DsymutilOptions &Options) {
return OutputLocation(Options.OutputFile);
// When updating, do in place replacement.
- if (Options.OutputFile.empty() && Options.LinkOpts.Update)
+ if (Options.OutputFile.empty() &&
+ (Options.LinkOpts.Update || !Options.SymbolMap.empty()))
return OutputLocation(std::string(InputFile));
// When dumping the debug map, just return an empty output location. This
@@ -660,6 +668,8 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
return EXIT_FAILURE;
}
+ SymbolMapLoader SymMapLoader(Options.SymbolMap);
+
for (auto &InputFile : Options.InputFiles) {
// Dump the symbol table for each input file and requested arch
if (Options.DumpStab) {
@@ -750,6 +760,9 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
if (Options.DumpDebugMap)
continue;
+ if (!Options.SymbolMap.empty())
+ Options.LinkOpts.Translator = SymMapLoader.Load(InputFile, *Map);
+
if (Map->begin() == Map->end()) {
std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
WithColor::warning()