diff --git a/test/tools/dsymutil/debug-map-parsing.test b/test/tools/dsymutil/debug-map-parsing.test index 3422316191f..180689ba68a 100644 --- a/test/tools/dsymutil/debug-map-parsing.test +++ b/test/tools/dsymutil/debug-map-parsing.test @@ -8,33 +8,35 @@ RUN: not llvm-dsymutil -v -parse-only %p/Inputs/inexistant 2>&1 | FileCheck %s - Check that We can parse the debug map of the basic executable. CHECK-NOT: error -CHECK: DEBUG MAP: x86_64-unknown-unknown-macho -CHECK: /Inputs/basic1.macho.x86_64.o: -CHECK: 0000000000000000 => 0000000100000ea0+0x24 _main -CHECK: /Inputs/basic2.macho.x86_64.o: -CHECK: 0000000000000310 => 0000000100001000+0x0 _baz -CHECK: 0000000000000020 => 0000000100000ed0+0x50 _foo -CHECK: 0000000000000070 => 0000000100000f20+0x17 _inc -CHECK: 0000000000000560 => 0000000100001008+0x0 _private_int -CHECK: /Inputs/basic3.macho.x86_64.o: -CHECK: 0000000000000020 => 0000000100000f40+0x50 _bar -CHECK: 0000000000000070 => 0000000100000f90+0x19 _inc -CHECK: 0000000000000004 => 0000000100001004+0x0 _val -CHECK: END DEBUG MAP +CHECK: --- +CHECK: triple: 'x86_64-unknown-unknown-macho' +CHECK: filename:{{.*}}/Inputs/basic1.macho.x86_64.o +CHECK-DAG: sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000EA0, size: 0x00000024 +CHECK: filename{{.*}}/Inputs/basic2.macho.x86_64.o +CHECK-DAG: sym: _baz, objAddr: 0x0000000000000310, binAddr: 0x0000000100001000, size: 0x00000000 +CHECK-DAG: sym: _foo, objAddr: 0x0000000000000020, binAddr: 0x0000000100000ED0, size: 0x00000050 +CHECK-DAG: sym: _inc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000F20, size: 0x00000017 +CHECK-DAG: sym: _private_int, objAddr: 0x0000000000000560, binAddr: 0x0000000100001008, size: 0x00000000 +CHECK: filename{{.*}}/Inputs/basic3.macho.x86_64.o +CHECK-DAG: sym: _bar, objAddr: 0x0000000000000020, binAddr: 0x0000000100000F40, size: 0x00000050 +CHECK-DAG: sym: _inc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000F90, size: 0x00000019 +CHECK-DAG: sym: _val, objAddr: 0x0000000000000004, binAddr: 0x0000000100001004, size: 0x00000000 +CHECK: ... Check that we can parse the debug-map of the basic-lto executable CHECK-LTO-NOT: error -CHECK-LTO: DEBUG MAP: x86_64-unknown-unknown-macho -CHECK-LTO: /Inputs/basic-lto.macho.x86_64.o: -CHECK-LTO: 0000000000000050 => 0000000100000f90+0x24 _bar -CHECK-LTO: 0000000000000658 => 0000000100001000+0x0 _baz -CHECK-LTO: 0000000000000010 => 0000000100000f50+0x40 _foo -CHECK-LTO: 0000000000000000 => 0000000100000f40+0x10 _main -CHECK-LTO: 00000000000008e8 => 0000000100001008+0x0 _private_int -CHECK-LTO: 00000000000008ec => 0000000100001004+0x0 _val -CHECK-LTO: END DEBUG MAP +CHECK-LTO: --- +CHECK-LTO: triple: 'x86_64-unknown-unknown-macho' +CHECK-LTO: /Inputs/basic-lto.macho.x86_64.o +CHECK-LTO-DAG: sym: _bar, objAddr: 0x0000000000000050, binAddr: 0x0000000100000F90, size: 0x00000024 +CHECK-LTO-DAG: sym: _baz, objAddr: 0x0000000000000658, binAddr: 0x0000000100001000, size: 0x00000000 +CHECK-LTO-DAG: sym: _foo, objAddr: 0x0000000000000010, binAddr: 0x0000000100000F50, size: 0x00000040 +CHECK-LTO-DAG: sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000F40, size: 0x00000010 +CHECK-LTO-DAG: sym: _private_int, objAddr: 0x00000000000008E8, binAddr: 0x0000000100001008, size: 0x00000000 +CHECK-LTO-DAG: sym: _val, objAddr: 0x00000000000008EC, binAddr: 0x0000000100001004, size: 0x00000000 +CHECK-LTO: ... Check thet we correctly handle debug maps with archive members (including only opening the archive once if mulitple of its members are used). @@ -48,20 +50,20 @@ CHECK-ARCHIVE-NEXT: opened new archive {{.*}}/libbasic.a' CHECK-ARCHIVE-NEXT: found member in current archive. CHECK-ARCHIVE-NEXT: trying to open {{.*}}/libbasic.a(basic3.macho.x86_64.o)' CHECK-ARCHIVE-NEXT: found member in current archive. -CHECK-ARCHIVE: DEBUG MAP: x86_64-unknown-unknown-macho -CHECK-ARCHIVE: object addr => executable addr symbol name -CHECK-ARCHIVE: /Inputs/basic1.macho.x86_64.o: -CHECK-ARCHIVE: 0000000000000000 => 0000000100000ea0+0x24 _main -CHECK-ARCHIVE: /Inputs/./libbasic.a(basic2.macho.x86_64.o): -CHECK-ARCHIVE: 0000000000000310 => 0000000100001000+0x0 _baz -CHECK-ARCHIVE: 0000000000000020 => 0000000100000ed0+0x50 _foo -CHECK-ARCHIVE: 0000000000000070 => 0000000100000f20+0x17 _inc -CHECK-ARCHIVE: 0000000000000560 => 0000000100001004+0x0 _private_int -CHECK-ARCHIVE: /Inputs/./libbasic.a(basic3.macho.x86_64.o): -CHECK-ARCHIVE: 0000000000000020 => 0000000100000f40+0x50 _bar -CHECK-ARCHIVE: 0000000000000070 => 0000000100000f90+0x19 _inc -CHECK-ARCHIVE: 0000000000000004 => 0000000100001008+0x0 _val -CHECK-ARCHIVE: END DEBUG MAP +CHECK-ARCHIVE: --- +CHECK-ARCHIVE: triple: 'x86_64-unknown-unknown-macho' +CHECK-ARCHIVE: /Inputs/basic1.macho.x86_64.o +CHECK-ARCHIVE-DAG: sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000EA0, size: 0x00000024 +CHECK-ARCHIVE: /Inputs/./libbasic.a(basic2.macho.x86_64.o) +CHECK-ARCHIVE-DAG: sym: _baz, objAddr: 0x0000000000000310, binAddr: 0x0000000100001000, size: 0x00000000 +CHECK-ARCHIVE-DAG: sym: _foo, objAddr: 0x0000000000000020, binAddr: 0x0000000100000ED0, size: 0x00000050 +CHECK-ARCHIVE-DAG: sym: _inc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000F20, size: 0x00000017 +CHECK-ARCHIVE-DAG: sym: _private_int, objAddr: 0x0000000000000560, binAddr: 0x0000000100001004, size: 0x00000000 +CHECK-ARCHIVE: /Inputs/./libbasic.a(basic3.macho.x86_64.o) +CHECK-ARCHIVE-DAG: sym: _bar, objAddr: 0x0000000000000020, binAddr: 0x0000000100000F40, size: 0x00000050 +CHECK-ARCHIVE-DAG: sym: _inc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000F90, size: 0x00000019 +CHECK-ARCHIVE-DAG: sym: _val, objAddr: 0x0000000000000004, binAddr: 0x0000000100001008, size: 0x00000000 +CHECK-ARCHIVE: ... Check that we warn about missing object files (this presumes that the files aren't present in the machine's /Inputs/ folder, which should be a pretty safe bet). @@ -69,11 +71,11 @@ present in the machine's /Inputs/ folder, which should be a pretty safe bet). NOT-FOUND: cannot open{{.*}}"/Inputs/basic1.macho.x86_64.o": {{[Nn]o}} such file NOT-FOUND: cannot open{{.*}}"/Inputs/basic2.macho.x86_64.o": {{[Nn]o}} such file NOT-FOUND: cannot open{{.*}}"/Inputs/basic3.macho.x86_64.o": {{[Nn]o}} such file -NOT-FOUND: DEBUG MAP: -NOT-FOUND-NEXT: object addr => executable addr symbol name -NOT-FOUND-NEXT: END DEBUG MAP +NOT-FOUND: --- +NOT-FOUND-NEXT: triple: 'x86_64-unknown-unknown-macho' +NOT-FOUND-NEXT: ... Check that we correctly error out on invalid executatble. NO-EXECUTABLE: cannot parse{{.*}}/inexistant": {{[Nn]o}} such file -NO-EXECUTABLE-NOT: DEBUG MAP +NO-EXECUTABLE-NOT: --- diff --git a/tools/dsymutil/DebugMap.cpp b/tools/dsymutil/DebugMap.cpp index 9fa3f788a89..dcbba19b107 100644 --- a/tools/dsymutil/DebugMap.cpp +++ b/tools/dsymutil/DebugMap.cpp @@ -46,8 +46,9 @@ void DebugMapObject::print(raw_ostream &OS) const { [](const Entry &LHS, const Entry &RHS) { return LHS.first < RHS.first; }); for (const auto &Sym : Entries) { OS << format("\t%016" PRIx64 " => %016" PRIx64 "+0x%x\t%s\n", - Sym.second.ObjectAddress, Sym.second.BinaryAddress, - Sym.second.Size, Sym.first.data()); + uint64_t(Sym.second.ObjectAddress), + uint64_t(Sym.second.BinaryAddress), + uint32_t(Sym.second.Size), Sym.first.data()); } OS << '\n'; } @@ -78,11 +79,8 @@ DebugMapObject::lookupObjectAddress(uint64_t Address) const { } void DebugMap::print(raw_ostream &OS) const { - OS << "DEBUG MAP: " << BinaryTriple.getTriple() - << "\n\tobject addr => executable addr\tsymbol name\n"; - for (const auto &Obj : objects()) - Obj->print(OS); - OS << "END DEBUG MAP\n"; + yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0); + yout << const_cast(*this); } #ifndef NDEBUG diff --git a/tools/dsymutil/DebugMap.h b/tools/dsymutil/DebugMap.h index ee48b093d4f..ab806c9cd1c 100644 --- a/tools/dsymutil/DebugMap.h +++ b/tools/dsymutil/DebugMap.h @@ -28,6 +28,7 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/Format.h" +#include "llvm/Support/YAMLTraits.h" #include namespace llvm { @@ -66,6 +67,11 @@ class DebugMap { typedef std::vector> ObjectContainer; ObjectContainer Objects; + /// For YAML IO support. + ///@{ + friend yaml::MappingTraits; + DebugMap() = default; + ///@} public: DebugMap(const Triple &BinaryTriple) : BinaryTriple(BinaryTriple) {} @@ -99,12 +105,14 @@ public: class DebugMapObject { public: struct SymbolMapping { - uint64_t ObjectAddress; - uint64_t BinaryAddress; - uint32_t Size; + yaml::Hex64 ObjectAddress; + yaml::Hex64 BinaryAddress; + yaml::Hex32 Size; SymbolMapping(uint64_t ObjectAddress, uint64_t BinaryAddress, uint32_t Size) : ObjectAddress(ObjectAddress), BinaryAddress(BinaryAddress), Size(Size) {} + /// For YAML IO support + SymbolMapping() = default; }; typedef StringMapEntry DebugMapEntry; @@ -141,6 +149,109 @@ private: std::string Filename; StringMap Symbols; DenseMap AddressToMapping; + + /// For YAMLIO support. + ///@{ + typedef std::pair YAMLSymbolMapping; + friend yaml::MappingTraits; + friend yaml::SequenceTraits>>; + friend yaml::SequenceTraits>; + DebugMapObject() = default; + ///@} +}; +} +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping); + +namespace llvm { +namespace yaml { + +using namespace llvm::dsymutil; + +template <> +struct MappingTraits> { + + static void + mapping(IO &io, std::pair &s) { + io.mapRequired("sym", s.first); + io.mapRequired("objAddr", s.second.ObjectAddress); + io.mapRequired("binAddr", s.second.BinaryAddress); + io.mapOptional("size", s.second.Size); + } + + static const bool flow = true; +}; + +template <> struct MappingTraits { + typedef StringMap SymbolMap; + + struct SequencedStringMap { + SequencedStringMap(IO &io) {} + + SequencedStringMap(IO &io, SymbolMap &Map) { + Entries.reserve(Map.size()); + for (auto &Entry : Map) + Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue())); + } + + SymbolMap denormalize(IO &) { + SymbolMap Res; + + for (auto &Entry : Entries) + Res[Entry.first] = Entry.second; + + return std::move(Res); + } + + 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); + } +}; + +template <> struct ScalarTraits { + + static void output(const Triple &val, void *, llvm::raw_ostream &out) { + out << val.str(); + } + + static StringRef input(StringRef scalar, void *, Triple &value) { + value = Triple(scalar); + return value.str(); + } + + static bool mustQuote(StringRef) { return true; } +}; + +template <> +struct SequenceTraits>> { + + static size_t + size(IO &io, std::vector> &seq) { + return seq.size(); + } + + static dsymutil::DebugMapObject & + element(IO &, std::vector> &seq, + size_t index) { + if (index >= seq.size()) { + seq.resize(index + 1); + seq[index].reset(new dsymutil::DebugMapObject); + } + return *seq[index]; + } +}; + +template <> struct MappingTraits { + static void mapping(IO &io, dsymutil::DebugMap &DM) { + io.mapRequired("triple", DM.BinaryTriple); + io.mapOptional("objects", DM.Objects); + } }; } } diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index e3e7e82eab6..fd79526fbac 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -1508,15 +1508,15 @@ bool DwarfLinker::hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset, return false; const auto &ValidReloc = ValidRelocs[NextValidReloc++]; + const auto &Mapping = ValidReloc.Mapping->getValue(); if (Options.Verbose) outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey() << " " << format("\t%016" PRIx64 " => %016" PRIx64, - ValidReloc.Mapping->getValue().ObjectAddress, - ValidReloc.Mapping->getValue().BinaryAddress); + uint64_t(Mapping.ObjectAddress), + uint64_t(Mapping.BinaryAddress)); - Info.AddrAdjust = int64_t(ValidReloc.Mapping->getValue().BinaryAddress) + - ValidReloc.Addend - - ValidReloc.Mapping->getValue().ObjectAddress; + Info.AddrAdjust = int64_t(Mapping.BinaryAddress) + + ValidReloc.Addend - Mapping.ObjectAddress; Info.InDebugMap = true; return true; }