mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-06 06:33:24 +00:00
[dsymutil] Find relocations that correspond to debug map entries.
These 'valid relocations' in the debug_info section will be how dsymutil identifies the DIEs it needs to keep in the linked debug information. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229178 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e9483b84f0
commit
16acc91bc4
@ -12,6 +12,7 @@
|
||||
#include "dsymutil.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
@ -44,6 +45,19 @@ private:
|
||||
};
|
||||
|
||||
/// \brief The core of the Dwarf linking logic.
|
||||
///
|
||||
/// The link of the dwarf information from the object files will be
|
||||
/// driven by the selection of 'root DIEs', which are DIEs that
|
||||
/// describe variables or functions that are present in the linked
|
||||
/// binary (and thus have entries in the debug map). All the debug
|
||||
/// information that will be linked (the DIEs, but also the line
|
||||
/// tables, ranges, ...) is derived from that set of root DIEs.
|
||||
///
|
||||
/// The root DIEs are identified because they contain relocations that
|
||||
/// correspond to a debug map entry at specific places (the low_pc for
|
||||
/// a function, the location for a variable). These relocations are
|
||||
/// called ValidRelocs in the DwarfLinker and are gathered as a very
|
||||
/// first step when we start processing a DebugMapObject.
|
||||
class DwarfLinker {
|
||||
public:
|
||||
DwarfLinker(StringRef OutputFilename, bool Verbose)
|
||||
@ -59,6 +73,45 @@ private:
|
||||
/// \brief Called at the end of a debug object link.
|
||||
void endDebugObject();
|
||||
|
||||
/// \defgroup FindValidRelocations Translate debug map into a list
|
||||
/// of relevant relocations
|
||||
///
|
||||
/// @{
|
||||
struct ValidReloc {
|
||||
uint32_t Offset;
|
||||
uint32_t Size;
|
||||
uint64_t Addend;
|
||||
const DebugMapObject::DebugMapEntry *Mapping;
|
||||
|
||||
ValidReloc(uint32_t Offset, uint32_t Size, uint64_t Addend,
|
||||
const DebugMapObject::DebugMapEntry *Mapping)
|
||||
: Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
|
||||
|
||||
bool operator<(const ValidReloc &RHS) const { return Offset < RHS.Offset; }
|
||||
};
|
||||
|
||||
/// \brief The valid relocations for the current DebugMapObject.
|
||||
/// This vector is sorted by relocation offset.
|
||||
std::vector<ValidReloc> ValidRelocs;
|
||||
|
||||
/// \brief Index into ValidRelocs of the next relocation to
|
||||
/// consider. As we walk the DIEs in acsending file offset and as
|
||||
/// ValidRelocs is sorted by file offset, keeping this index
|
||||
/// uptodate is all we have to do to have a cheap lookup during the
|
||||
/// root DIE selection.
|
||||
unsigned NextValidReloc;
|
||||
|
||||
bool findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
|
||||
const DebugMapObject &DMO);
|
||||
|
||||
bool findValidRelocs(const object::SectionRef &Section,
|
||||
const object::ObjectFile &Obj,
|
||||
const DebugMapObject &DMO);
|
||||
|
||||
void findValidRelocsMachO(const object::SectionRef &Section,
|
||||
const object::MachOObjectFile &Obj,
|
||||
const DebugMapObject &DMO);
|
||||
/// @}
|
||||
private:
|
||||
std::string OutputFilename;
|
||||
bool Verbose;
|
||||
@ -83,9 +136,96 @@ void GatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE, unsigned ParentIdx,
|
||||
|
||||
void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
|
||||
Units.reserve(Dwarf.getNumCompileUnits());
|
||||
NextValidReloc = 0;
|
||||
}
|
||||
|
||||
void DwarfLinker::endDebugObject() { Units.clear(); }
|
||||
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;
|
||||
}
|
||||
|
||||
bool DwarfLinker::link(const DebugMap &Map) {
|
||||
|
||||
@ -103,6 +243,13 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look for relocations that correspond to debug map entries.
|
||||
if (!findValidRelocsInDebugInfo(*ErrOrObj, *Obj)) {
|
||||
if (Verbose)
|
||||
outs() << "No valid relocations found. Skipping.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Setup access to the debug info.
|
||||
DWARFContextInMemory DwarfContext(*ErrOrObj);
|
||||
startDebugObject(DwarfContext);
|
||||
|
Loading…
x
Reference in New Issue
Block a user