[dsymutil] Use YAMLIO to dump debug map.

Doing so will allow us to also accept a YAML debug map in input as using
YAMLIO gives us the parsing for free. Being able to have textual debug
maps will in turn allow much more control over the tests, because 1/
no need to check-in a binary containing the debug map and 2/ it will allow
to use the same objects/IR files with made-up debug-maps to test
different scenari.

llvm-svn: 238781
This commit is contained in:
Frederic Riss 2015-06-01 21:12:45 +00:00
parent fd99e01b91
commit 08462f7859
4 changed files with 166 additions and 55 deletions

View File

@ -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: ---

View File

@ -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<DebugMap&>(*this);
}
#ifndef NDEBUG

View File

@ -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 <vector>
namespace llvm {
@ -66,6 +67,11 @@ class DebugMap {
typedef std::vector<std::unique_ptr<DebugMapObject>> ObjectContainer;
ObjectContainer Objects;
/// For YAML IO support.
///@{
friend yaml::MappingTraits<DebugMap>;
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<SymbolMapping> DebugMapEntry;
@ -141,6 +149,109 @@ private:
std::string Filename;
StringMap<SymbolMapping> Symbols;
DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
/// For YAMLIO support.
///@{
typedef std::pair<std::string, SymbolMapping> YAMLSymbolMapping;
friend yaml::MappingTraits<dsymutil::DebugMapObject>;
friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
friend yaml::SequenceTraits<std::vector<YAMLSymbolMapping>>;
DebugMapObject() = default;
///@}
};
}
}
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping);
namespace llvm {
namespace yaml {
using namespace llvm::dsymutil;
template <>
struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
static void
mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &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<dsymutil::DebugMapObject> {
typedef StringMap<dsymutil::DebugMapObject::SymbolMapping> 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<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
};
static void mapping(IO &io, dsymutil::DebugMapObject &s) {
MappingNormalization<SequencedStringMap, SymbolMap> seq(io, s.Symbols);
io.mapRequired("filename", s.Filename);
io.mapRequired("symbols", seq->Entries);
}
};
template <> struct ScalarTraits<Triple> {
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<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
static size_t
size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) {
return seq.size();
}
static dsymutil::DebugMapObject &
element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
size_t index) {
if (index >= seq.size()) {
seq.resize(index + 1);
seq[index].reset(new dsymutil::DebugMapObject);
}
return *seq[index];
}
};
template <> struct MappingTraits<dsymutil::DebugMap> {
static void mapping(IO &io, dsymutil::DebugMap &DM) {
io.mapRequired("triple", DM.BinaryTriple);
io.mapOptional("objects", DM.Objects);
}
};
}
}

View File

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