From 90e0bd96ff732cfec9b5fdc10ad4279b1184a394 Mon Sep 17 00:00:00 2001 From: Frederic Riss Date: Wed, 3 Jun 2015 20:29:24 +0000 Subject: [PATCH] Reapply r238941 - [dsymutil] Accept a YAML debug map as input instead of a binary. With a couple more constructors that GCC thinks are necessary. Original commit message: [dsymutil] Accept a YAML debug map as input instead of a binary. To do this, the user needs to pass the new -y flag. As it wasn't tested before, the debug map YAML deserialization was completely buggy (mainly because the DebugMapObject has a dual mapping that allows to search by name and by address, but only the StringMap got populated). It's fixed and tested in this commit by augmenting some test with a 2 stage dwarf link: a frist llvm-dsymutil reads the debug map and pipes it in a second instance that does the actual link without touching the initial binary. llvm-svn: 238959 --- .../tools/dsymutil/X86/basic-linking-x86.test | 2 + .../dsymutil/X86/basic-lto-linking-x86.test | 1 + llvm/tools/dsymutil/DebugMap.h | 60 +++++++++++++------ llvm/tools/dsymutil/MachODebugMapParser.cpp | 26 +++++++- llvm/tools/dsymutil/dsymutil.cpp | 8 ++- llvm/tools/dsymutil/dsymutil.h | 4 +- 6 files changed, 77 insertions(+), 24 deletions(-) diff --git a/llvm/test/tools/dsymutil/X86/basic-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-linking-x86.test index 1059e233f94b..e6d42e464a9c 100644 --- a/llvm/test/tools/dsymutil/X86/basic-linking-x86.test +++ b/llvm/test/tools/dsymutil/X86/basic-linking-x86.test @@ -6,6 +6,8 @@ RUN: llvm-dsymutil -o %t2 -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_6 RUN: llvm-dwarfdump %t2 | FileCheck %s RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=BASIC RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic-archive.macho.x86_64 | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=ARCHIVE +RUN: llvm-dsymutil -dump-debug-map -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 | llvm-dsymutil -y -o - - | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=BASIC +RUN: llvm-dsymutil -dump-debug-map -oso-prepend-path=%p/.. %p/../Inputs/basic-archive.macho.x86_64 | llvm-dsymutil -o - -oso-prepend-path=%p/.. -y - | llvm-dwarfdump - | FileCheck %s --check-prefix=CHECK --check-prefix=ARCHIVE CHECK: file format Mach-O 64-bit x86-64 diff --git a/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test b/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test index 22b6e0808d8a..44997ee523fb 100644 --- a/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test +++ b/llvm/test/tools/dsymutil/X86/basic-lto-linking-x86.test @@ -1,5 +1,6 @@ REQUIRES: shell RUN: llvm-dsymutil -o - -oso-prepend-path=%p/.. %p/../Inputs/basic-lto.macho.x86_64 | llvm-dwarfdump - | FileCheck %s +RUN: llvm-dsymutil -oso-prepend-path=%p/.. -dump-debug-map %p/../Inputs/basic-lto.macho.x86_64 | llvm-dsymutil -o - -oso-prepend-path=%p/.. -y - | llvm-dwarfdump - | FileCheck %s CHECK: file format Mach-O 64-bit x86-64 diff --git a/llvm/tools/dsymutil/DebugMap.h b/llvm/tools/dsymutil/DebugMap.h index 8d76f113e91e..08bba18602c7 100644 --- a/llvm/tools/dsymutil/DebugMap.h +++ b/llvm/tools/dsymutil/DebugMap.h @@ -69,6 +69,7 @@ class DebugMap { /// For YAML IO support. ///@{ + friend yaml::MappingTraits>; friend yaml::MappingTraits; DebugMap() = default; ///@} @@ -157,6 +158,18 @@ private: friend yaml::SequenceTraits>>; friend yaml::SequenceTraits>; DebugMapObject() = default; + public: + DebugMapObject &operator=(DebugMapObject RHS) { + std::swap(Filename, RHS.Filename); + std::swap(Symbols, RHS.Symbols); + std::swap(AddressToMapping, RHS.AddressToMapping); + return *this; + } + DebugMapObject(DebugMapObject &&RHS) { + Filename = std::move(RHS.Filename); + Symbols = std::move(RHS.Symbols); + AddressToMapping = std::move(RHS.AddressToMapping); + } ///@} }; } @@ -184,33 +197,35 @@ struct MappingTraits> { }; template <> struct MappingTraits { - typedef StringMap SymbolMap; + // Normalize/Denormalize between YAML and a DebugMapObject. + struct YamlDMO { + YamlDMO(IO &io) {} - struct SequencedStringMap { - SequencedStringMap(IO &io) {} - - SequencedStringMap(IO &io, SymbolMap &Map) { - Entries.reserve(Map.size()); - for (auto &Entry : Map) + YamlDMO(IO &io, dsymutil::DebugMapObject &Obj) { + Filename = Obj.Filename; + Entries.reserve(Obj.Symbols.size()); + for (auto &Entry : Obj.Symbols) Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue())); } - SymbolMap denormalize(IO &) { - SymbolMap Res; - - for (auto &Entry : Entries) - Res[Entry.first] = Entry.second; - + dsymutil::DebugMapObject denormalize(IO &) { + dsymutil::DebugMapObject Res(Filename); + for (auto &Entry : Entries) { + auto &Mapping = Entry.second; + Res.addSymbol(Entry.first, Mapping.ObjectAddress, Mapping.BinaryAddress, + Mapping.Size); + } return Res; } + std::string Filename; std::vector Entries; }; - static void mapping(IO &io, dsymutil::DebugMapObject &s) { - MappingNormalization seq(io, s.Symbols); - io.mapRequired("filename", s.Filename); - io.mapRequired("symbols", seq->Entries); + static void mapping(IO &io, dsymutil::DebugMapObject &DMO) { + MappingNormalization Norm(io, DMO); + io.mapRequired("filename", Norm->Filename); + io.mapRequired("symbols", Norm->Entries); } }; @@ -222,7 +237,7 @@ template <> struct ScalarTraits { static StringRef input(StringRef scalar, void *, Triple &value) { value = Triple(scalar); - return value.str(); + return StringRef(); } static bool mustQuote(StringRef) { return true; } @@ -253,6 +268,15 @@ template <> struct MappingTraits { io.mapOptional("objects", DM.Objects); } }; + + template <> struct MappingTraits> { + static void mapping(IO &io, std::unique_ptr &DM) { + if (!DM) + DM.reset(new DebugMap()); + io.mapRequired("triple", DM->BinaryTriple); + io.mapOptional("objects", DM->Objects); + } +}; } } diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp index bf64303b9eab..c8b48823f989 100644 --- a/llvm/tools/dsymutil/MachODebugMapParser.cpp +++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp @@ -242,12 +242,32 @@ void MachODebugMapParser::loadMainBinarySymbols() { } } +ErrorOr> +parseYAMLDebugMap(StringRef InputFile, bool Verbose) { + auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile); + if (auto Err =ErrOrFile.getError()) + return Err; + + std::unique_ptr Res; + yaml::Input yin((*ErrOrFile)->getBuffer()); + yin >> Res; + + if (auto EC = yin.error()) + return EC; + + return std::move(Res); +} + namespace llvm { namespace dsymutil { llvm::ErrorOr> -parseDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose) { - MachODebugMapParser Parser(InputFile, PrependPath, Verbose); - return Parser.parse(); +parseDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose, bool InputIsYAML) { + if (!InputIsYAML) { + MachODebugMapParser Parser(InputFile, PrependPath, Verbose); + return Parser.parse(); + } else { + return parseYAMLDebugMap(InputFile, Verbose); + } } } } diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp index b4a480d70127..50091935a44e 100644 --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -52,6 +52,10 @@ static opt DumpDebugMap( desc("Parse and dump the debug map to standard output. Not DWARF link " "will take place."), init(false)); + +static opt InputIsYAMLDebugMap( + "y", desc("Treat the input file is a YAML debug map rather than a binary."), + init(false)); } int main(int argc, char **argv) { @@ -61,7 +65,9 @@ int main(int argc, char **argv) { LinkOptions Options; llvm::cl::ParseCommandLineOptions(argc, argv, "llvm dsymutil\n"); - auto DebugMapPtrOrErr = parseDebugMap(InputFile, OsoPrependPath, Verbose); + + auto DebugMapPtrOrErr = + parseDebugMap(InputFile, OsoPrependPath, Verbose, InputIsYAMLDebugMap); Options.Verbose = Verbose; Options.NoOutput = NoOutput; diff --git a/llvm/tools/dsymutil/dsymutil.h b/llvm/tools/dsymutil/dsymutil.h index e9f7cd951878..0cbdaf5503a8 100644 --- a/llvm/tools/dsymutil/dsymutil.h +++ b/llvm/tools/dsymutil/dsymutil.h @@ -34,8 +34,8 @@ struct LinkOptions { /// \brief Extract the DebugMap from the given file. /// The file has to be a MachO object file. llvm::ErrorOr> -parseDebugMap(StringRef InputFile, StringRef PrependPath = "", - bool Verbose = false); +parseDebugMap(StringRef InputFile, StringRef PrependPath, + bool Verbose, bool InputIsYAML); /// \brief Link the Dwarf debuginfo as directed by the passed DebugMap /// \p DM into a DwarfFile named \p OutputFilename.