mirror of
https://github.com/RPCSX/llvm.git
synced 2025-04-02 16:21:36 +00:00
dsymutil: Factor out the relocation handling into a RelocationManager (NFC)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247490 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
830d0f8976
commit
0a0a960468
@ -1103,52 +1103,74 @@ 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;
|
||||
/// Keeps track of relocations.
|
||||
class RelocationManager {
|
||||
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) {}
|
||||
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; }
|
||||
bool operator<(const ValidReloc &RHS) const {
|
||||
return Offset < RHS.Offset;
|
||||
}
|
||||
};
|
||||
|
||||
DwarfLinker &Linker;
|
||||
|
||||
/// \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 and during DIE cloning.
|
||||
unsigned NextValidReloc;
|
||||
|
||||
public:
|
||||
RelocationManager(DwarfLinker &Linker)
|
||||
: Linker(Linker), NextValidReloc(0) {}
|
||||
|
||||
bool hasValidRelocs() const { return !ValidRelocs.empty(); }
|
||||
/// \brief Reset the NextValidReloc counter.
|
||||
void resetValidRelocs() { NextValidReloc = 0; }
|
||||
|
||||
/// \defgroup FindValidRelocations Translate debug map into a list
|
||||
/// of relevant relocations
|
||||
///
|
||||
/// @{
|
||||
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);
|
||||
/// @}
|
||||
|
||||
bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
|
||||
CompileUnit::DIEInfo &Info);
|
||||
|
||||
bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
|
||||
bool isLittleEndian);
|
||||
};
|
||||
|
||||
/// \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 and during DIE cloning.
|
||||
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);
|
||||
/// @}
|
||||
|
||||
/// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries.
|
||||
///
|
||||
/// @{
|
||||
/// \brief Recursively walk the \p DIE tree and look for DIEs to
|
||||
/// keep. Store that information in \p CU's DIEInfo.
|
||||
void lookForDIEsToKeep(const DWARFDebugInfoEntryMinimal &DIE,
|
||||
void lookForDIEsToKeep(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE,
|
||||
const DebugMapObject &DMO, CompileUnit &CU,
|
||||
unsigned Flags);
|
||||
|
||||
@ -1164,20 +1186,24 @@ private:
|
||||
|
||||
/// \brief Mark the passed DIE as well as all the ones it depends on
|
||||
/// as kept.
|
||||
void keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &DIE,
|
||||
void keepDIEAndDenpendencies(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
const DebugMapObject &DMO, CompileUnit &CU,
|
||||
bool UseODR);
|
||||
|
||||
unsigned shouldKeepDIE(const DWARFDebugInfoEntryMinimal &DIE,
|
||||
unsigned shouldKeepDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE,
|
||||
CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags);
|
||||
|
||||
unsigned shouldKeepVariableDIE(const DWARFDebugInfoEntryMinimal &DIE,
|
||||
unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE,
|
||||
CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo, unsigned Flags);
|
||||
|
||||
unsigned shouldKeepSubprogramDIE(const DWARFDebugInfoEntryMinimal &DIE,
|
||||
unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE,
|
||||
CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags);
|
||||
@ -1200,9 +1226,19 @@ private:
|
||||
/// applied to the entry point of the function to get the linked address.
|
||||
///
|
||||
/// \returns the root of the cloned tree.
|
||||
DIE *cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &U,
|
||||
DIE *cloneDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &U,
|
||||
int64_t PCOffset, uint32_t OutOffset, unsigned Flags);
|
||||
|
||||
/// Construct the output DIE tree by cloning the DIEs we chose to
|
||||
/// keep above. If there are no valid relocs, then there's nothing
|
||||
/// to clone/emit.
|
||||
void cloneCompileUnit(RelocationManager &RelocMgr,
|
||||
MutableArrayRef<CompileUnit> CompileUnit,
|
||||
DWARFContextInMemory &DwarfContext);
|
||||
|
||||
|
||||
|
||||
typedef DWARFAbbreviationDeclaration::AttributeSpec AttributeSpec;
|
||||
|
||||
/// \brief Information gathered and exchanged between the various
|
||||
@ -1257,10 +1293,6 @@ private:
|
||||
const DWARFFormValue &Val, unsigned AttrSize,
|
||||
AttributesInfo &Info);
|
||||
|
||||
/// \brief Helper for cloneDIE.
|
||||
bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
|
||||
bool isLittleEndian);
|
||||
|
||||
/// \brief Assign an abbreviation number to \p Abbrev
|
||||
void AssignAbbrev(DIEAbbrev &Abbrev);
|
||||
|
||||
@ -1334,6 +1366,7 @@ private:
|
||||
LinkOptions Options;
|
||||
BinaryHolder BinHolder;
|
||||
std::unique_ptr<DwarfStreamer> Streamer;
|
||||
uint64_t OutputDebugInfoSize;
|
||||
|
||||
/// The units of the current debug map object.
|
||||
std::vector<CompileUnit> Units;
|
||||
@ -1701,7 +1734,6 @@ static unsigned getRefAddrSize(const DWARFUnit &U) {
|
||||
|
||||
void DwarfLinker::startDebugObject(DWARFContext &Dwarf, DebugMapObject &Obj) {
|
||||
Units.reserve(Dwarf.getNumCompileUnits());
|
||||
NextValidReloc = 0;
|
||||
// Iterate over the debug map entries and put all the ones that are
|
||||
// functions (because they have a size) into the Ranges map. This
|
||||
// map is very similar to the FunctionRanges that are stored in each
|
||||
@ -1727,7 +1759,6 @@ void DwarfLinker::startDebugObject(DWARFContext &Dwarf, DebugMapObject &Obj) {
|
||||
|
||||
void DwarfLinker::endDebugObject() {
|
||||
Units.clear();
|
||||
ValidRelocs.clear();
|
||||
Ranges.clear();
|
||||
|
||||
for (auto I = DIEBlocks.begin(), E = DIEBlocks.end(); I != E; ++I)
|
||||
@ -1743,9 +1774,10 @@ void DwarfLinker::endDebugObject() {
|
||||
/// \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) {
|
||||
void DwarfLinker::RelocationManager::
|
||||
findValidRelocsMachO(const object::SectionRef &Section,
|
||||
const object::MachOObjectFile &Obj,
|
||||
const DebugMapObject &DMO) {
|
||||
StringRef Contents;
|
||||
Section.getContents(Contents);
|
||||
DataExtractor Data(Contents, Obj.isLittleEndian(), 0);
|
||||
@ -1756,7 +1788,7 @@ void DwarfLinker::findValidRelocsMachO(const object::SectionRef &Section,
|
||||
unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);
|
||||
uint64_t Offset64 = Reloc.getOffset();
|
||||
if ((RelocSize != 4 && RelocSize != 8)) {
|
||||
reportWarning(" unsupported relocation in debug_info section.");
|
||||
Linker.reportWarning(" unsupported relocation in debug_info section.");
|
||||
continue;
|
||||
}
|
||||
uint32_t Offset = Offset64;
|
||||
@ -1767,7 +1799,7 @@ void DwarfLinker::findValidRelocsMachO(const object::SectionRef &Section,
|
||||
if (Sym != Obj.symbol_end()) {
|
||||
ErrorOr<StringRef> SymbolName = Sym->getName();
|
||||
if (!SymbolName) {
|
||||
reportWarning("error getting relocation symbol name.");
|
||||
Linker.reportWarning("error getting relocation symbol name.");
|
||||
continue;
|
||||
}
|
||||
if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
|
||||
@ -1783,14 +1815,15 @@ void DwarfLinker::findValidRelocsMachO(const object::SectionRef &Section,
|
||||
|
||||
/// \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) {
|
||||
bool DwarfLinker::RelocationManager::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
|
||||
reportWarning(Twine("unsupported object file type: ") + Obj.getFileName());
|
||||
Linker.reportWarning(Twine("unsupported object file type: ") +
|
||||
Obj.getFileName());
|
||||
|
||||
if (ValidRelocs.empty())
|
||||
return false;
|
||||
@ -1808,8 +1841,9 @@ bool DwarfLinker::findValidRelocs(const object::SectionRef &Section,
|
||||
/// 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) {
|
||||
bool DwarfLinker::RelocationManager::
|
||||
findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
|
||||
const DebugMapObject &DMO) {
|
||||
// Find the debug_info section.
|
||||
for (const object::SectionRef &Section : Obj.sections()) {
|
||||
StringRef SectionName;
|
||||
@ -1828,8 +1862,9 @@ bool DwarfLinker::findValidRelocsInDebugInfo(const object::ObjectFile &Obj,
|
||||
/// This function must be called with offsets in strictly ascending
|
||||
/// order because it never looks back at relocations it already 'went past'.
|
||||
/// \returns true and sets Info.InDebugMap if it is the case.
|
||||
bool DwarfLinker::hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
|
||||
CompileUnit::DIEInfo &Info) {
|
||||
bool DwarfLinker::RelocationManager::
|
||||
hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
|
||||
CompileUnit::DIEInfo &Info) {
|
||||
assert(NextValidReloc == 0 ||
|
||||
StartOffset > ValidRelocs[NextValidReloc - 1].Offset);
|
||||
if (NextValidReloc >= ValidRelocs.size())
|
||||
@ -1849,7 +1884,7 @@ bool DwarfLinker::hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
|
||||
|
||||
const auto &ValidReloc = ValidRelocs[NextValidReloc++];
|
||||
const auto &Mapping = ValidReloc.Mapping->getValue();
|
||||
if (Options.Verbose)
|
||||
if (Linker.Options.Verbose)
|
||||
outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey()
|
||||
<< " " << format("\t%016" PRIx64 " => %016" PRIx64,
|
||||
uint64_t(Mapping.ObjectAddress),
|
||||
@ -1882,9 +1917,11 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
|
||||
|
||||
/// \brief Check if a variable describing DIE should be kept.
|
||||
/// \returns updated TraversalFlags.
|
||||
unsigned DwarfLinker::shouldKeepVariableDIE(
|
||||
const DWARFDebugInfoEntryMinimal &DIE, CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo, unsigned Flags) {
|
||||
unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE,
|
||||
CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags) {
|
||||
const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
|
||||
|
||||
// Global variables with constant value can always be kept.
|
||||
@ -1909,7 +1946,7 @@ unsigned DwarfLinker::shouldKeepVariableDIE(
|
||||
// always check in the variable has a valid relocation, so that the
|
||||
// DIEInfo is filled. However, we don't want a static variable in a
|
||||
// function to force us to keep the enclosing function.
|
||||
if (!hasValidRelocation(LocationOffset, LocationEndOffset, MyInfo) ||
|
||||
if (!RelocMgr.hasValidRelocation(LocationOffset, LocationEndOffset, MyInfo) ||
|
||||
(Flags & TF_InFunctionScope))
|
||||
return Flags;
|
||||
|
||||
@ -1922,6 +1959,7 @@ unsigned DwarfLinker::shouldKeepVariableDIE(
|
||||
/// \brief Check if a function describing DIE should be kept.
|
||||
/// \returns updated TraversalFlags.
|
||||
unsigned DwarfLinker::shouldKeepSubprogramDIE(
|
||||
RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE, CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo, unsigned Flags) {
|
||||
const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
|
||||
@ -1942,7 +1980,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
|
||||
DIE.getAttributeValueAsAddress(&OrigUnit, dwarf::DW_AT_low_pc, -1ULL);
|
||||
assert(LowPc != -1ULL && "low_pc attribute is not an address.");
|
||||
if (LowPc == -1ULL ||
|
||||
!hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo))
|
||||
!RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo))
|
||||
return Flags;
|
||||
|
||||
if (Options.Verbose)
|
||||
@ -1973,16 +2011,17 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
|
||||
|
||||
/// \brief Check if a DIE should be kept.
|
||||
/// \returns updated TraversalFlags.
|
||||
unsigned DwarfLinker::shouldKeepDIE(const DWARFDebugInfoEntryMinimal &DIE,
|
||||
unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &DIE,
|
||||
CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags) {
|
||||
switch (DIE.getTag()) {
|
||||
case dwarf::DW_TAG_constant:
|
||||
case dwarf::DW_TAG_variable:
|
||||
return shouldKeepVariableDIE(DIE, Unit, MyInfo, Flags);
|
||||
return shouldKeepVariableDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
|
||||
case dwarf::DW_TAG_subprogram:
|
||||
return shouldKeepSubprogramDIE(DIE, Unit, MyInfo, Flags);
|
||||
return shouldKeepSubprogramDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
|
||||
case dwarf::DW_TAG_module:
|
||||
case dwarf::DW_TAG_imported_module:
|
||||
case dwarf::DW_TAG_imported_declaration:
|
||||
@ -2002,7 +2041,8 @@ unsigned DwarfLinker::shouldKeepDIE(const DWARFDebugInfoEntryMinimal &DIE,
|
||||
/// back to lookForDIEsToKeep while adding TF_DependencyWalk to the
|
||||
/// TraversalFlags to inform it that it's not doing the primary DIE
|
||||
/// tree walk.
|
||||
void DwarfLinker::keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &Die,
|
||||
void DwarfLinker::keepDIEAndDenpendencies(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &Die,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
const DebugMapObject &DMO,
|
||||
CompileUnit &CU, bool UseODR) {
|
||||
@ -2013,7 +2053,7 @@ void DwarfLinker::keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &Die,
|
||||
unsigned AncestorIdx = MyInfo.ParentIdx;
|
||||
while (!CU.getInfo(AncestorIdx).Keep) {
|
||||
unsigned ODRFlag = UseODR ? TF_ODR : 0;
|
||||
lookForDIEsToKeep(*Unit.getDIEAtIndex(AncestorIdx), DMO, CU,
|
||||
lookForDIEsToKeep(RelocMgr, *Unit.getDIEAtIndex(AncestorIdx), DMO, CU,
|
||||
TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag);
|
||||
AncestorIdx = CU.getInfo(AncestorIdx).ParentIdx;
|
||||
}
|
||||
@ -2053,7 +2093,7 @@ void DwarfLinker::keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &Die,
|
||||
continue;
|
||||
|
||||
unsigned ODRFlag = UseODR ? TF_ODR : 0;
|
||||
lookForDIEsToKeep(*RefDIE, DMO, *ReferencedCU,
|
||||
lookForDIEsToKeep(RelocMgr, *RefDIE, DMO, *ReferencedCU,
|
||||
TF_Keep | TF_DependencyWalk | ODRFlag);
|
||||
}
|
||||
}
|
||||
@ -2071,7 +2111,8 @@ void DwarfLinker::keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &Die,
|
||||
/// also called, but during these dependency walks the file order is
|
||||
/// not respected. The TF_DependencyWalk flag tells us which kind of
|
||||
/// traversal we are currently doing.
|
||||
void DwarfLinker::lookForDIEsToKeep(const DWARFDebugInfoEntryMinimal &Die,
|
||||
void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &Die,
|
||||
const DebugMapObject &DMO, CompileUnit &CU,
|
||||
unsigned Flags) {
|
||||
unsigned Idx = CU.getOrigUnit().getDIEIndex(&Die);
|
||||
@ -2087,12 +2128,12 @@ void DwarfLinker::lookForDIEsToKeep(const DWARFDebugInfoEntryMinimal &Die,
|
||||
// We must not call shouldKeepDIE while called from keepDIEAndDenpendencies,
|
||||
// because it would screw up the relocation finding logic.
|
||||
if (!(Flags & TF_DependencyWalk))
|
||||
Flags = shouldKeepDIE(Die, CU, MyInfo, Flags);
|
||||
Flags = shouldKeepDIE(RelocMgr, Die, CU, MyInfo, Flags);
|
||||
|
||||
// If it is a newly kept DIE mark it as well as all its dependencies as kept.
|
||||
if (!AlreadyKept && (Flags & TF_Keep)) {
|
||||
bool UseOdr = (Flags & TF_DependencyWalk) ? (Flags & TF_ODR) : CU.hasODR();
|
||||
keepDIEAndDenpendencies(Die, MyInfo, DMO, CU, UseOdr);
|
||||
keepDIEAndDenpendencies(RelocMgr, Die, MyInfo, DMO, CU, UseOdr);
|
||||
}
|
||||
// The TF_ParentWalk flag tells us that we are currently walking up
|
||||
// the parent chain of a required DIE, and we don't want to mark all
|
||||
@ -2108,7 +2149,7 @@ void DwarfLinker::lookForDIEsToKeep(const DWARFDebugInfoEntryMinimal &Die,
|
||||
|
||||
for (auto *Child = Die.getFirstChild(); Child && !Child->isNULL();
|
||||
Child = Child->getSibling())
|
||||
lookForDIEsToKeep(*Child, DMO, CU, Flags);
|
||||
lookForDIEsToKeep(RelocMgr, *Child, DMO, CU, Flags);
|
||||
}
|
||||
|
||||
/// \brief Assign an abbreviation numer to \p Abbrev.
|
||||
@ -2412,8 +2453,9 @@ unsigned DwarfLinker::cloneAttribute(DIE &Die,
|
||||
/// monotonic \p BaseOffset values.
|
||||
///
|
||||
/// \returns wether any reloc has been applied.
|
||||
bool DwarfLinker::applyValidRelocs(MutableArrayRef<char> Data,
|
||||
uint32_t BaseOffset, bool isLittleEndian) {
|
||||
bool DwarfLinker::RelocationManager::
|
||||
applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
|
||||
bool isLittleEndian) {
|
||||
assert((NextValidReloc == 0 ||
|
||||
BaseOffset > ValidRelocs[NextValidReloc - 1].Offset) &&
|
||||
"BaseOffset should only be increasing.");
|
||||
@ -2512,7 +2554,8 @@ shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
/// lie in the linked compile unit.
|
||||
///
|
||||
/// \returns the cloned DIE object or null if nothing was selected.
|
||||
DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
DIE *DwarfLinker::cloneDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
CompileUnit &Unit, int64_t PCOffset,
|
||||
uint32_t OutOffset, unsigned Flags) {
|
||||
DWARFUnit &U = Unit.getOrigUnit();
|
||||
@ -2551,7 +2594,7 @@ DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
|
||||
Data = DataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
|
||||
// Modify the copy with relocated addresses.
|
||||
if (applyValidRelocs(DIECopy, Offset, Data.isLittleEndian())) {
|
||||
if (RelocMgr.applyValidRelocs(DIECopy, Offset, Data.isLittleEndian())) {
|
||||
// If we applied relocations, we store the value of high_pc that was
|
||||
// potentially stored in the input DIE. If high_pc is an address
|
||||
// (Dwarf version == 2), then it might have been relocated to a
|
||||
@ -2652,7 +2695,8 @@ DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
// Recursively clone children.
|
||||
for (auto *Child = InputDIE.getFirstChild(); Child && !Child->isNULL();
|
||||
Child = Child->getSibling()) {
|
||||
if (DIE *Clone = cloneDIE(*Child, Unit, PCOffset, OutOffset, Flags)) {
|
||||
if (DIE *Clone =
|
||||
cloneDIE(RelocMgr, *Child, Unit, PCOffset, OutOffset, Flags)) {
|
||||
Die->addChild(Clone);
|
||||
OutOffset = Clone->getOffset() + Clone->getSize();
|
||||
}
|
||||
@ -3020,13 +3064,53 @@ DwarfLinker::loadObject(BinaryHolder &BinaryHolder, DebugMapObject &Obj,
|
||||
return ErrOrObj;
|
||||
}
|
||||
|
||||
void DwarfLinker::cloneCompileUnit(RelocationManager &RelocMgr,
|
||||
MutableArrayRef<CompileUnit> CompileUnits,
|
||||
DWARFContextInMemory &DwarfContext) {
|
||||
if (!Streamer)
|
||||
return;
|
||||
|
||||
for (auto &CurrentUnit : CompileUnits) {
|
||||
const auto *InputDIE = CurrentUnit.getOrigUnit().getUnitDIE();
|
||||
CurrentUnit.setStartOffset(OutputDebugInfoSize);
|
||||
DIE *OutputDIE = cloneDIE(RelocMgr, *InputDIE, CurrentUnit,
|
||||
0 /* PC offset */, 11 /* Unit Header size */, 0);
|
||||
CurrentUnit.setOutputUnitDIE(OutputDIE);
|
||||
OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset();
|
||||
if (Options.NoOutput)
|
||||
continue;
|
||||
// FIXME: for compatibility with the classic dsymutil, we emit
|
||||
// an empty line table for the unit, even if the unit doesn't
|
||||
// actually exist in the DIE tree.
|
||||
patchLineTableForUnit(CurrentUnit, DwarfContext);
|
||||
if (!OutputDIE)
|
||||
continue;
|
||||
patchRangesForUnit(CurrentUnit, DwarfContext);
|
||||
Streamer->emitLocationsForUnit(CurrentUnit, DwarfContext);
|
||||
emitAcceleratorEntriesForUnit(CurrentUnit);
|
||||
}
|
||||
|
||||
if (Options.NoOutput)
|
||||
return;
|
||||
|
||||
// Emit all the compile unit's debug information.
|
||||
for (auto &CurrentUnit : CompileUnits) {
|
||||
generateUnitRanges(CurrentUnit);
|
||||
CurrentUnit.fixupForwardReferences();
|
||||
Streamer->emitCompileUnitHeader(CurrentUnit);
|
||||
if (!CurrentUnit.getOutputUnitDIE())
|
||||
continue;
|
||||
Streamer->emitDIE(*CurrentUnit.getOutputUnitDIE());
|
||||
}
|
||||
}
|
||||
|
||||
bool DwarfLinker::link(const DebugMap &Map) {
|
||||
|
||||
if (!createStreamer(Map.getTriple(), OutputFilename))
|
||||
return false;
|
||||
|
||||
// Size of the DIEs (and headers) generated for the linked output.
|
||||
uint64_t OutputDebugInfoSize = 0;
|
||||
OutputDebugInfoSize = 0;
|
||||
// A unique ID that identifies each compile unit.
|
||||
unsigned UnitID = 0;
|
||||
for (const auto &Obj : Map.objects()) {
|
||||
@ -3039,7 +3123,8 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
||||
continue;
|
||||
|
||||
// Look for relocations that correspond to debug map entries.
|
||||
if (!findValidRelocsInDebugInfo(*ErrOrObj, *Obj)) {
|
||||
RelocationManager RelocMgr(*this);
|
||||
if (!RelocMgr.findValidRelocsInDebugInfo(*ErrOrObj, *Obj)) {
|
||||
if (Options.Verbose)
|
||||
outs() << "No valid relocations found. Skipping.\n";
|
||||
continue;
|
||||
@ -3068,50 +3153,16 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
||||
// references require the ParentIdx to be setup for every CU in
|
||||
// the object file before calling this.
|
||||
for (auto &CurrentUnit : Units)
|
||||
lookForDIEsToKeep(*CurrentUnit.getOrigUnit().getUnitDIE(), *Obj,
|
||||
lookForDIEsToKeep(RelocMgr, *CurrentUnit.getOrigUnit().getUnitDIE(), *Obj,
|
||||
CurrentUnit, 0);
|
||||
|
||||
// The calls to applyValidRelocs inside cloneDIE will walk the
|
||||
// reloc array again (in the same way findValidRelocsInDebugInfo()
|
||||
// did). We need to reset the NextValidReloc index to the beginning.
|
||||
NextValidReloc = 0;
|
||||
|
||||
// Construct the output DIE tree by cloning the DIEs we chose to
|
||||
// keep above. If there are no valid relocs, then there's nothing
|
||||
// to clone/emit.
|
||||
if (!ValidRelocs.empty())
|
||||
for (auto &CurrentUnit : Units) {
|
||||
const auto *InputDIE = CurrentUnit.getOrigUnit().getUnitDIE();
|
||||
CurrentUnit.setStartOffset(OutputDebugInfoSize);
|
||||
DIE *OutputDIE = cloneDIE(*InputDIE, CurrentUnit, 0 /* PCOffset */,
|
||||
11 /* Unit Header size */, /* Flags =*/0);
|
||||
CurrentUnit.setOutputUnitDIE(OutputDIE);
|
||||
OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset();
|
||||
if (Options.NoOutput)
|
||||
continue;
|
||||
// FIXME: for compatibility with the classic dsymutil, we emit
|
||||
// an empty line table for the unit, even if the unit doesn't
|
||||
// actually exist in the DIE tree.
|
||||
patchLineTableForUnit(CurrentUnit, DwarfContext);
|
||||
if (!OutputDIE)
|
||||
continue;
|
||||
patchRangesForUnit(CurrentUnit, DwarfContext);
|
||||
Streamer->emitLocationsForUnit(CurrentUnit, DwarfContext);
|
||||
emitAcceleratorEntriesForUnit(CurrentUnit);
|
||||
}
|
||||
|
||||
// Emit all the compile unit's debug information.
|
||||
if (!ValidRelocs.empty() && !Options.NoOutput)
|
||||
for (auto &CurrentUnit : Units) {
|
||||
generateUnitRanges(CurrentUnit);
|
||||
CurrentUnit.fixupForwardReferences();
|
||||
Streamer->emitCompileUnitHeader(CurrentUnit);
|
||||
if (!CurrentUnit.getOutputUnitDIE())
|
||||
continue;
|
||||
Streamer->emitDIE(*CurrentUnit.getOutputUnitDIE());
|
||||
}
|
||||
|
||||
if (!ValidRelocs.empty() && !Options.NoOutput && !Units.empty())
|
||||
RelocMgr.resetValidRelocs();
|
||||
if (RelocMgr.hasValidRelocs())
|
||||
cloneCompileUnit(RelocMgr, Units, DwarfContext);
|
||||
if (!Options.NoOutput && !Units.empty())
|
||||
patchFrameInfoForObject(*Obj, DwarfContext,
|
||||
Units[0].getOrigUnit().getAddressByteSize());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user