forked from OSchip/llvm-project
[dsymutil] Gather function ranges during DIE selection.
Gather the function ranges [low_pc, high_pc) during DIE selection and store them along with the offset to apply to them to get the linked addresses. This is just the data collection part, it comes with no tests. That information will be used in multiple followup commits to perform the relocation of line tables and range sections among other things, and these commits will add tests. llvm-svn: 231957
This commit is contained in:
parent
aa983ce0fe
commit
ce98470d1d
|
@ -10,6 +10,7 @@
|
||||||
#include "BinaryHolder.h"
|
#include "BinaryHolder.h"
|
||||||
#include "DebugMap.h"
|
#include "DebugMap.h"
|
||||||
#include "dsymutil.h"
|
#include "dsymutil.h"
|
||||||
|
#include "llvm/ADT/IntervalMap.h"
|
||||||
#include "llvm/CodeGen/AsmPrinter.h"
|
#include "llvm/CodeGen/AsmPrinter.h"
|
||||||
#include "llvm/CodeGen/DIE.h"
|
#include "llvm/CodeGen/DIE.h"
|
||||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||||
|
@ -47,6 +48,11 @@ bool error(const Twine &Error, const Twine &Context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename KeyT, typename ValT>
|
||||||
|
using HalfOpenIntervalMap =
|
||||||
|
IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
|
||||||
|
IntervalMapHalfOpenInfo<KeyT>>;
|
||||||
|
|
||||||
/// \brief Stores all information relating to a compile unit, be it in
|
/// \brief Stores all information relating to a compile unit, be it in
|
||||||
/// its original instance in the object file to its brand new cloned
|
/// its original instance in the object file to its brand new cloned
|
||||||
/// and linked DIE tree.
|
/// and linked DIE tree.
|
||||||
|
@ -61,15 +67,19 @@ public:
|
||||||
bool InDebugMap; ///< Was this DIE's entity found in the map?
|
bool InDebugMap; ///< Was this DIE's entity found in the map?
|
||||||
};
|
};
|
||||||
|
|
||||||
CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) {
|
CompileUnit(DWARFUnit &OrigUnit)
|
||||||
|
: OrigUnit(OrigUnit), RangeAlloc(), Ranges(RangeAlloc) {
|
||||||
Info.resize(OrigUnit.getNumDIEs());
|
Info.resize(OrigUnit.getNumDIEs());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround MSVC not supporting implicit move ops
|
|
||||||
CompileUnit(CompileUnit &&RHS)
|
CompileUnit(CompileUnit &&RHS)
|
||||||
: OrigUnit(RHS.OrigUnit), Info(std::move(RHS.Info)),
|
: OrigUnit(RHS.OrigUnit), Info(std::move(RHS.Info)),
|
||||||
CUDie(std::move(RHS.CUDie)), StartOffset(RHS.StartOffset),
|
CUDie(std::move(RHS.CUDie)), StartOffset(RHS.StartOffset),
|
||||||
NextUnitOffset(RHS.NextUnitOffset) {}
|
NextUnitOffset(RHS.NextUnitOffset), RangeAlloc(), Ranges(RangeAlloc) {
|
||||||
|
// The CompileUnit container has been 'reserve()'d with the right
|
||||||
|
// size. We cannot move the IntervalMap anyway.
|
||||||
|
llvm_unreachable("CompileUnits should not be moved.");
|
||||||
|
}
|
||||||
|
|
||||||
DWARFUnit &getOrigUnit() const { return OrigUnit; }
|
DWARFUnit &getOrigUnit() const { return OrigUnit; }
|
||||||
|
|
||||||
|
@ -98,6 +108,10 @@ public:
|
||||||
/// \brief Apply all fixups recored by noteForwardReference().
|
/// \brief Apply all fixups recored by noteForwardReference().
|
||||||
void fixupForwardReferences();
|
void fixupForwardReferences();
|
||||||
|
|
||||||
|
/// \brief Add a function range [\p LowPC, \p HighPC) that is
|
||||||
|
/// relocatad by applying offset \p PCOffset.
|
||||||
|
void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DWARFUnit &OrigUnit;
|
DWARFUnit &OrigUnit;
|
||||||
std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
|
std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
|
||||||
|
@ -113,6 +127,12 @@ private:
|
||||||
/// cloning because for forward refences the target DIE's offset isn't
|
/// cloning because for forward refences the target DIE's offset isn't
|
||||||
/// known you emit the reference attribute.
|
/// known you emit the reference attribute.
|
||||||
std::vector<std::pair<DIE *, DIEInteger *>> ForwardDIEReferences;
|
std::vector<std::pair<DIE *, DIEInteger *>> ForwardDIEReferences;
|
||||||
|
|
||||||
|
HalfOpenIntervalMap<uint64_t, int64_t>::Allocator RangeAlloc;
|
||||||
|
/// \brief The ranges in that interval map are the PC ranges for
|
||||||
|
/// functions in this unit, associated with the PC offset to apply
|
||||||
|
/// to the addresses to get the linked address.
|
||||||
|
HalfOpenIntervalMap<uint64_t, int64_t> Ranges;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t CompileUnit::computeNextUnitOffset() {
|
uint64_t CompileUnit::computeNextUnitOffset() {
|
||||||
|
@ -136,6 +156,11 @@ void CompileUnit::fixupForwardReferences() {
|
||||||
Ref.second->setValue(Ref.first->getOffset() + getStartOffset());
|
Ref.second->setValue(Ref.first->getOffset() + getStartOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompileUnit::addFunctionRange(uint64_t LowPC, uint64_t HighPC,
|
||||||
|
int64_t PCOffset) {
|
||||||
|
Ranges.insert(LowPC, HighPC, PCOffset);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief A string table that doesn't need relocations.
|
/// \brief A string table that doesn't need relocations.
|
||||||
///
|
///
|
||||||
/// We are doing a final link, no need for a string table that
|
/// We are doing a final link, no need for a string table that
|
||||||
|
@ -942,7 +967,25 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
|
||||||
if (Options.Verbose)
|
if (Options.Verbose)
|
||||||
DIE.dump(outs(), const_cast<DWARFUnit *>(&OrigUnit), 0, 8 /* Indent */);
|
DIE.dump(outs(), const_cast<DWARFUnit *>(&OrigUnit), 0, 8 /* Indent */);
|
||||||
|
|
||||||
return Flags | TF_Keep;
|
Flags |= TF_Keep;
|
||||||
|
|
||||||
|
DWARFFormValue HighPcValue;
|
||||||
|
if (!DIE.getAttributeValue(&OrigUnit, dwarf::DW_AT_high_pc, HighPcValue)) {
|
||||||
|
reportWarning("Function without high_pc. Range will be discarded.\n",
|
||||||
|
&OrigUnit, &DIE);
|
||||||
|
return Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t HighPc;
|
||||||
|
if (HighPcValue.isFormClass(DWARFFormValue::FC_Address)) {
|
||||||
|
HighPc = *HighPcValue.getAsAddress(&OrigUnit);
|
||||||
|
} else {
|
||||||
|
assert(HighPcValue.isFormClass(DWARFFormValue::FC_Constant));
|
||||||
|
HighPc = LowPc + *HighPcValue.getAsUnsignedConstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Unit.addFunctionRange(LowPc, HighPc, MyInfo.AddrAdjust);
|
||||||
|
return Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Check if a DIE should be kept.
|
/// \brief Check if a DIE should be kept.
|
||||||
|
|
Loading…
Reference in New Issue