From dfbf8971ca4a14c0e6e7671ff004ad3e13cb305b Mon Sep 17 00:00:00 2001 From: Frederic Riss Date: Fri, 5 Jun 2015 21:12:07 +0000 Subject: [PATCH] [dsymutil] Have the YAML deserialization rewrite the object address of symbols. The main use of the YAML debug map format is for testing inside LLVM. If we have IR files in the tests used to generate object files, then we obviously don't know the addresses of the symbols inside the object files beforehand. This change lets the YAML import lookup the addresses in the object files and rewrite them. This will allow to have test that really don't need any binary input. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239189 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../dsymutil/yaml-object-address-rewrite.test | 44 ++++++++++++++++ tools/dsymutil/DebugMap.cpp | 52 ++++++++++++++++--- 2 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 test/tools/dsymutil/yaml-object-address-rewrite.test diff --git a/test/tools/dsymutil/yaml-object-address-rewrite.test b/test/tools/dsymutil/yaml-object-address-rewrite.test new file mode 100644 index 00000000000..dcb39be891c --- /dev/null +++ b/test/tools/dsymutil/yaml-object-address-rewrite.test @@ -0,0 +1,44 @@ +# RUN: llvm-dsymutil -v -dump-debug-map -oso-prepend-path=%p -y %s | FileCheck %s +# +# The YAML debug map bellow is the one from basic-archive.macho.x86_64 with +# the object addresses set to zero. Check that the YAML import is able to +# rewrite these addresses to the right values. +# +# CHECK: --- +# CHECK-NEXT: triple:{{.*}}'x86_64-unknown-unknown-macho' +# CHECK-NEXT: objects: +# CHECK-NEXT: filename:{{.*}}/Inputs/basic1.macho.x86_64.o +# CHECK-NEXT: symbols: +# CHECK-NEXT: sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000EA0, size: 0x00000024 +# CHECK-NEXT: filename:{{.*}}/Inputs/./libbasic.a(basic2.macho.x86_64.o)' +# CHECK-NEXT: symbols: +# CHECK-DAG: sym: _foo, objAddr: 0x0000000000000020, binAddr: 0x0000000100000ED0, size: 0x00000050 +# CHECK-DAG: sym: _private_int, objAddr: 0x0000000000000560, binAddr: 0x0000000100001004, size: 0x00000000 +# CHECK-DAG: sym: _inc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000F20, size: 0x00000017 +# CHECK-DAG: sym: _baz, objAddr: 0x0000000000000310, binAddr: 0x0000000100001000, size: 0x00000000 +# CHECK-NOT: { sym: +# CHECK-NEXT: filename:{{.*}}/Inputs/./libbasic.a(basic3.macho.x86_64.o)' +# CHECK-NEXT: symbols: +# CHECK-DAG: sym: _val, objAddr: 0x0000000000000004, binAddr: 0x0000000100001008, size: 0x00000000 +# CHECK-DAG: sym: _bar, objAddr: 0x0000000000000020, binAddr: 0x0000000100000F40, size: 0x00000050 +# CHECK-DAG: sym: _inc, objAddr: 0x0000000000000070, binAddr: 0x0000000100000F90, size: 0x00000019 +# CHECK-NOT: { sym: +# CHECK-NEXT: ... +--- +triple: 'x86_64-unknown-unknown-macho' +objects: + - filename: /Inputs/basic1.macho.x86_64.o + symbols: + - { sym: _main, objAddr: 0x0, binAddr: 0x0000000100000EA0, size: 0x00000024 } + - filename: /Inputs/./libbasic.a(basic2.macho.x86_64.o) + symbols: + - { sym: _foo, objAddr: 0x0, binAddr: 0x0000000100000ED0, size: 0x00000050 } + - { sym: _private_int, objAddr: 0x0, binAddr: 0x0000000100001004, size: 0x00000000 } + - { sym: _inc, objAddr: 0x0, binAddr: 0x0000000100000F20, size: 0x00000017 } + - { sym: _baz, objAddr: 0x0, binAddr: 0x0000000100001000, size: 0x00000000 } + - filename: /Inputs/./libbasic.a(basic3.macho.x86_64.o) + symbols: + - { sym: _val, objAddr: 0x0, binAddr: 0x0000000100001008, size: 0x00000000 } + - { sym: _bar, objAddr: 0x0, binAddr: 0x0000000100000F40, size: 0x00000050 } + - { sym: _inc, objAddr: 0x0, binAddr: 0x0000000100000F90, size: 0x00000019 } +... diff --git a/tools/dsymutil/DebugMap.cpp b/tools/dsymutil/DebugMap.cpp index 5ffb123f1b9..6a8e49ca86f 100644 --- a/tools/dsymutil/DebugMap.cpp +++ b/tools/dsymutil/DebugMap.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// #include "DebugMap.h" +#include "BinaryHolder.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/DataTypes.h" @@ -87,6 +88,13 @@ void DebugMap::print(raw_ostream &OS) const { void DebugMap::dump() const { print(errs()); } #endif +namespace { +struct YAMLContext { + StringRef PrependPath; + Triple Triple; +}; +} + ErrorOr> DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose) { @@ -94,8 +102,12 @@ DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, if (auto Err = ErrOrFile.getError()) return Err; + YAMLContext Ctxt; + + Ctxt.PrependPath = PrependPath; + std::unique_ptr Res; - yaml::Input yin((*ErrOrFile)->getBuffer(), &PrependPath); + yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt); yin >> Res; if (auto EC = yin.error()) @@ -163,6 +175,8 @@ void MappingTraits::mapping(IO &io, dsymutil::DebugMap &DM) { io.mapRequired("triple", DM.BinaryTriple); io.mapOptional("objects", DM.Objects); + if (void *Ctxt = io.getContext()) + reinterpret_cast(Ctxt)->Triple = DM.BinaryTriple; } void MappingTraits>::mapping( @@ -171,6 +185,8 @@ void MappingTraits>::mapping( DM.reset(new DebugMap()); io.mapRequired("triple", DM->BinaryTriple); io.mapOptional("objects", DM->Objects); + if (void *Ctxt = io.getContext()) + reinterpret_cast(Ctxt)->Triple = DM->BinaryTriple; } MappingTraits::YamlDMO::YamlDMO( @@ -183,15 +199,39 @@ MappingTraits::YamlDMO::YamlDMO( dsymutil::DebugMapObject MappingTraits::YamlDMO::denormalize(IO &IO) { - void *Ctxt = IO.getContext(); - StringRef PrependPath = *reinterpret_cast(Ctxt); - SmallString<80> Path(PrependPath); + BinaryHolder BinHolder(/* Verbose =*/false); + const auto &Ctxt = *reinterpret_cast(IO.getContext()); + SmallString<80> Path(Ctxt.PrependPath); + StringMap SymbolAddresses; + sys::path::append(Path, Filename); + auto ErrOrObjectFile = BinHolder.GetObjectFile(Path); + if (auto EC = ErrOrObjectFile.getError()) { + llvm::errs() << "warning: Unable to open " << Path << " " << EC.message() + << '\n'; + } else { + // Rewrite the object file symbol addresses in the debug map. The + // YAML input is mainly used to test llvm-dsymutil without + // requiring binaries checked-in. If we generate the object files + // during the test, we can't hardcode the symbols addresses, so + // look them up here and rewrite them. + for (const auto &Sym : ErrOrObjectFile->symbols()) { + StringRef Name; + uint64_t Address; + if (Sym.getName(Name) || Sym.getAddress(Address)) + continue; + SymbolAddresses[Name] = Address; + } + } + dsymutil::DebugMapObject Res(Path); for (auto &Entry : Entries) { auto &Mapping = Entry.second; - Res.addSymbol(Entry.first, Mapping.ObjectAddress, Mapping.BinaryAddress, - Mapping.Size); + uint64_t ObjAddress = Mapping.ObjectAddress; + auto AddressIt = SymbolAddresses.find(Entry.first); + if (AddressIt != SymbolAddresses.end()) + ObjAddress = AddressIt->getValue(); + Res.addSymbol(Entry.first, ObjAddress, Mapping.BinaryAddress, Mapping.Size); } return Res; } -- 2.34.1