[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.

llvm-svn: 239189
This commit is contained in:
Frederic Riss 2015-06-05 21:12:07 +00:00
parent bb2cc9cf56
commit 4f5874a51f
2 changed files with 90 additions and 6 deletions

View File

@ -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 }
...

View File

@ -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<std::unique_ptr<DebugMap>>
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<DebugMap> 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<dsymutil::DebugMap>::mapping(IO &io,
dsymutil::DebugMap &DM) {
io.mapRequired("triple", DM.BinaryTriple);
io.mapOptional("objects", DM.Objects);
if (void *Ctxt = io.getContext())
reinterpret_cast<YAMLContext *>(Ctxt)->Triple = DM.BinaryTriple;
}
void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
@ -171,6 +185,8 @@ void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
DM.reset(new DebugMap());
io.mapRequired("triple", DM->BinaryTriple);
io.mapOptional("objects", DM->Objects);
if (void *Ctxt = io.getContext())
reinterpret_cast<YAMLContext *>(Ctxt)->Triple = DM->BinaryTriple;
}
MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
@ -183,15 +199,39 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
dsymutil::DebugMapObject
MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
void *Ctxt = IO.getContext();
StringRef PrependPath = *reinterpret_cast<StringRef *>(Ctxt);
SmallString<80> Path(PrependPath);
BinaryHolder BinHolder(/* Verbose =*/false);
const auto &Ctxt = *reinterpret_cast<YAMLContext *>(IO.getContext());
SmallString<80> Path(Ctxt.PrependPath);
StringMap<uint64_t> 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;
}