diff options
author | Andres Villegas <andresvi@google.com> | 2024-03-19 10:58:31 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-19 13:58:31 -0400 |
commit | 3176c157190c80b4279dec86c4b9b84472d8ccac (patch) | |
tree | 31751c0814ab695cf76a6ab63ca23d7612c04512 /llvm/tools/dsymutil | |
parent | 4bade55cc65db8b7f977dba4f13bf335e93317a8 (diff) | |
download | llvm-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.txt | 1 | ||||
-rw-r--r-- | llvm/tools/dsymutil/DwarfLinkerForBinary.cpp | 14 | ||||
-rw-r--r-- | llvm/tools/dsymutil/LinkUtils.h | 5 | ||||
-rw-r--r-- | llvm/tools/dsymutil/MachOUtils.cpp | 7 | ||||
-rw-r--r-- | llvm/tools/dsymutil/MachOUtils.h | 4 | ||||
-rw-r--r-- | llvm/tools/dsymutil/Options.td | 6 | ||||
-rw-r--r-- | llvm/tools/dsymutil/SymbolMap.cpp | 157 | ||||
-rw-r--r-- | llvm/tools/dsymutil/SymbolMap.h | 53 | ||||
-rw-r--r-- | llvm/tools/dsymutil/dsymutil.cpp | 15 |
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() |