aboutsummaryrefslogtreecommitdiff
path: root/tools/dsymutil/DebugMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dsymutil/DebugMap.cpp')
-rw-r--r--tools/dsymutil/DebugMap.cpp161
1 files changed, 154 insertions, 7 deletions
diff --git a/tools/dsymutil/DebugMap.cpp b/tools/dsymutil/DebugMap.cpp
index 9fa3f788a89f..1a81848847f6 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"
@@ -46,8 +47,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,15 +80,160 @@ 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
void DebugMap::dump() const { print(errs()); }
#endif
+
+namespace {
+struct YAMLContext {
+ StringRef PrependPath;
+ Triple BinaryTriple;
+};
+}
+
+ErrorOr<std::unique_ptr<DebugMap>>
+DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
+ bool Verbose) {
+ auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
+ if (auto Err = ErrOrFile.getError())
+ return Err;
+
+ YAMLContext Ctxt;
+
+ Ctxt.PrependPath = PrependPath;
+
+ std::unique_ptr<DebugMap> Res;
+ yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
+ yin >> Res;
+
+ if (auto EC = yin.error())
+ return EC;
+
+ return std::move(Res);
+}
+}
+
+namespace yaml {
+
+// Normalize/Denormalize between YAML and a DebugMapObject.
+struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO {
+ YamlDMO(IO &io) {}
+ YamlDMO(IO &io, dsymutil::DebugMapObject &Obj);
+ dsymutil::DebugMapObject denormalize(IO &IO);
+
+ std::string Filename;
+ std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
+};
+
+void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
+ 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);
+}
+
+void MappingTraits<dsymutil::DebugMapObject>::mapping(
+ IO &io, dsymutil::DebugMapObject &DMO) {
+ MappingNormalization<YamlDMO, dsymutil::DebugMapObject> Norm(io, DMO);
+ io.mapRequired("filename", Norm->Filename);
+ io.mapRequired("symbols", Norm->Entries);
+}
+
+void ScalarTraits<Triple>::output(const Triple &val, void *,
+ llvm::raw_ostream &out) {
+ out << val.str();
+}
+
+StringRef ScalarTraits<Triple>::input(StringRef scalar, void *, Triple &value) {
+ value = Triple(scalar);
+ return StringRef();
+}
+
+size_t
+SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::size(
+ IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) {
+ return seq.size();
+}
+
+dsymutil::DebugMapObject &
+SequenceTraits<std::vector<std::unique_ptr<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];
+}
+
+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)->BinaryTriple = DM.BinaryTriple;
+}
+
+void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
+ IO &io, std::unique_ptr<dsymutil::DebugMap> &DM) {
+ if (!DM)
+ DM.reset(new DebugMap());
+ io.mapRequired("triple", DM->BinaryTriple);
+ io.mapOptional("objects", DM->Objects);
+ if (void *Ctxt = io.getContext())
+ reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple;
+}
+
+MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
+ IO &io, dsymutil::DebugMapObject &Obj) {
+ Filename = Obj.Filename;
+ Entries.reserve(Obj.Symbols.size());
+ for (auto &Entry : Obj.Symbols)
+ Entries.push_back(std::make_pair(Entry.getKey(), Entry.getValue()));
+}
+
+dsymutil::DebugMapObject
+MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
+ 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;
+ 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;
+}
}
}