diff options
Diffstat (limited to 'tools/dsymutil/DebugMap.cpp')
-rw-r--r-- | tools/dsymutil/DebugMap.cpp | 161 |
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; +} } } |