+void DwarfLinker::endDebugObject() {
+ Units.clear();
+ ValidRelocs.clear();
+}
+
+/// \brief Iterate over the relocations of the given \p Section and
+/// store the ones that correspond to debug map entries into the
+/// ValidRelocs array.
+void DwarfLinker::findValidRelocsMachO(const object::SectionRef &Section,
+ const object::MachOObjectFile &Obj,
+ const DebugMapObject &DMO) {
+ StringRef Contents;
+ Section.getContents(Contents);
+ DataExtractor Data(Contents, Obj.isLittleEndian(), 0);
+
+ for (const object::RelocationRef &Reloc : Section.relocations()) {
+ object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
+ MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
+ unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);
+ uint64_t Offset64;
+ if ((RelocSize != 4 && RelocSize != 8) || Reloc.getOffset(Offset64)) {
+ errs() << "warning: unsupported relocation in debug_info section.\n";
+ continue;
+ }
+ uint32_t Offset = Offset64;
+ // Mach-o uses REL relocations, the addend is at the relocation offset.
+ uint64_t Addend = Data.getUnsigned(&Offset, RelocSize);
+
+ auto Sym = Reloc.getSymbol();
+ if (Sym != Obj.symbol_end()) {
+ StringRef SymbolName;
+ if (Sym->getName(SymbolName)) {
+ errs() << "warning: error getting relocation symbol name.\n";
+ continue;
+ }
+ if (const auto *Mapping = DMO.lookupSymbol(SymbolName))
+ ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
+ } else if (const auto *Mapping = DMO.lookupObjectAddress(Addend)) {
+ // Do not store the addend. The addend was the address of the
+ // symbol in the object file, the address in the binary that is
+ // stored in the debug map doesn't need to be offseted.
+ ValidRelocs.emplace_back(Offset64, RelocSize, 0, Mapping);
+ }
+ }
+}
+
+/// \brief Dispatch the valid relocation finding logic to the
+/// appropriate handler depending on the object file format.
+bool DwarfLinker::findValidRelocs(const object::SectionRef &Section,
+ const object::ObjectFile &Obj,
+ const DebugMapObject &DMO) {
+ // Dispatch to the right handler depending on the file type.
+ if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj))
+ findValidRelocsMachO(Section, *MachOObj, DMO);
+ else
+ errs() << "warning: unsupported object file type: " << Obj.getFileName()
+ << '\n';
+
+ if (ValidRelocs.empty())
+ return false;
+
+ // Sort the relocations by offset. We will walk the DIEs linearly in
+ // the file, this allows us to just keep an index in the relocation
+ // array that we advance during our walk, rather than resorting to
+ // some associative container. See DwarfLinker::NextValidReloc.
+ std::sort(ValidRelocs.begin(), ValidRelocs.end());
+ return true;
+}
+
+/// \brief Look for relocations in the debug_info section that match
+/// entries in the debug map. These relocations will drive the Dwarf
+/// link by indicating which DIEs refer to symbols present in the
+/// linked binary.
+/// \returns wether there are any valid relocations in the debug info.
+bool DwarfLinker::findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
+ const DebugMapObject &DMO) {
+ // Find the debug_info section.
+ for (const object::SectionRef &Section : Obj.sections()) {
+ StringRef SectionName;
+ Section.getName(SectionName);
+ SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
+ if (SectionName != "debug_info")
+ continue;
+ return findValidRelocs(Section, Obj, DMO);
+ }
+ return false;
+}