diff --git a/llvm/test/tools/dsymutil/yaml-object-address-rewrite.test b/llvm/test/tools/dsymutil/yaml-object-address-rewrite.test new file mode 100644 index 000000000000..dcb39be891cd --- /dev/null +++ b/llvm/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/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp index 5ffb123f1b99..6a8e49ca86ff 100644 --- a/llvm/tools/dsymutil/DebugMap.cpp +++ b/llvm/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; }