namespace {
+/// \brief Stores all information relating to a compile unit, be it in
+/// its original instance in the object file to its brand new cloned
+/// and linked DIE tree.
+class CompileUnit {
+public:
+ /// \brief Information gathered about a DIE in the object file.
+ struct DIEInfo {
+ uint32_t ParentIdx;
+ };
+
+ CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) {
+ Info.resize(OrigUnit.getNumDIEs());
+ }
+
+ DWARFUnit &getOrigUnit() { return OrigUnit; }
+
+ DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
+ const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
+
+private:
+ DWARFUnit &OrigUnit;
+ std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
+};
+
/// \brief The core of the Dwarf linking logic.
class DwarfLinker {
public:
/// \brief Link the contents of the DebugMap.
bool link(const DebugMap &);
+private:
+ /// \brief Called at the start of a debug object link.
+ void startDebugObject(DWARFContext &);
+
+ /// \brief Called at the end of a debug object link.
+ void endDebugObject();
+
private:
std::string OutputFilename;
bool Verbose;
BinaryHolder BinHolder;
+
+ /// The units of the current debug map object.
+ std::vector<CompileUnit> Units;
};
+/// \brief Recursive helper to gather the child->parent relationships in the
+/// original compile unit.
+void GatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE, unsigned ParentIdx,
+ CompileUnit &CU) {
+ unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
+ CU.getInfo(MyIdx).ParentIdx = ParentIdx;
+
+ if (DIE->hasChildren())
+ for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL();
+ Child = Child->getSibling())
+ GatherDIEParents(Child, MyIdx, CU);
+}
+
+void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
+ Units.reserve(Dwarf.getNumCompileUnits());
+}
+
+void DwarfLinker::endDebugObject() { Units.clear(); }
+
bool DwarfLinker::link(const DebugMap &Map) {
if (Map.begin() == Map.end()) {
continue;
}
+ // Setup access to the debug info.
DWARFContextInMemory DwarfContext(*ErrOrObj);
+ startDebugObject(DwarfContext);
+ // In a first phase, just read in the debug info and store the DIE
+ // parent links that we will use during the next phase.
for (const auto &CU : DwarfContext.compile_units()) {
auto *CUDie = CU->getCompileUnitDIE(false);
if (Verbose) {
outs() << "Input compilation unit:";
CUDie->dump(outs(), CU.get(), 0);
}
+ Units.emplace_back(*CU);
+ GatherDIEParents(CUDie, 0, Units.back());
}
+
+ // Clean-up before starting working on the next object.
+ endDebugObject();
}
return true;