mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[DWARF parser] Refactor fetching DIE address ranges.
Add a helper method to get address ranges specified in a DIE (either by DW_AT_low_pc/DW_AT_high_pc, or by DW_AT_ranges). Use it to untangle and simplify the code. No functionality change. llvm-svn: 206624
This commit is contained in:
parent
cf746f5ff0
commit
ea5a42fe9c
@ -58,8 +58,13 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) {
|
||||
// manually build aranges for the rest of them.
|
||||
for (const auto &CU : CTX->compile_units()) {
|
||||
uint32_t CUOffset = CU->getOffset();
|
||||
if (ParsedCUOffsets.insert(CUOffset).second)
|
||||
CU->buildAddressRangeTable(this, true, CUOffset);
|
||||
if (ParsedCUOffsets.insert(CUOffset).second) {
|
||||
DWARFAddressRangesVector CURanges;
|
||||
CU->collectAddressRanges(CURanges);
|
||||
for (const auto &R : CURanges) {
|
||||
appendRange(CUOffset, R.first, R.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortAndMinimize();
|
||||
|
@ -226,39 +226,47 @@ bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
|
||||
return (HighPC != -1ULL);
|
||||
}
|
||||
|
||||
void DWARFDebugInfoEntryMinimal::buildAddressRangeTable(
|
||||
const DWARFUnit *U, DWARFDebugAranges *DebugAranges,
|
||||
uint32_t UOffsetInAranges) const {
|
||||
if (AbbrevDecl) {
|
||||
if (isSubprogramDIE()) {
|
||||
uint64_t LowPC, HighPC;
|
||||
if (getLowAndHighPC(U, LowPC, HighPC))
|
||||
DebugAranges->appendRange(UOffsetInAranges, LowPC, HighPC);
|
||||
// FIXME: try to append ranges from .debug_ranges section.
|
||||
}
|
||||
|
||||
const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
|
||||
while (Child) {
|
||||
Child->buildAddressRangeTable(U, DebugAranges, UOffsetInAranges);
|
||||
Child = Child->getSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
|
||||
const DWARFUnit *U, const uint64_t Address) const {
|
||||
DWARFAddressRangesVector
|
||||
DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const {
|
||||
if (isNULL())
|
||||
return false;
|
||||
return DWARFAddressRangesVector{};
|
||||
// Single range specified by low/high PC.
|
||||
uint64_t LowPC, HighPC;
|
||||
if (getLowAndHighPC(U, LowPC, HighPC))
|
||||
return (LowPC <= Address && Address <= HighPC);
|
||||
// Try to get address ranges from .debug_ranges section.
|
||||
if (getLowAndHighPC(U, LowPC, HighPC)) {
|
||||
return DWARFAddressRangesVector{std::make_pair(LowPC, HighPC)};
|
||||
}
|
||||
// Multiple ranges from .debug_ranges section.
|
||||
uint32_t RangesOffset =
|
||||
getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
|
||||
if (RangesOffset != -1U) {
|
||||
DWARFDebugRangeList RangeList;
|
||||
if (U->extractRangeList(RangesOffset, RangeList))
|
||||
return RangeList.containsAddress(U->getBaseAddress(), Address);
|
||||
return RangeList.getAbsoluteRanges(U->getBaseAddress());
|
||||
}
|
||||
return DWARFAddressRangesVector{};
|
||||
}
|
||||
|
||||
void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges(
|
||||
const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const {
|
||||
if (isNULL())
|
||||
return;
|
||||
if (isSubprogramDIE()) {
|
||||
const auto &DIERanges = getAddressRanges(U);
|
||||
Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
|
||||
}
|
||||
|
||||
const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
|
||||
while (Child) {
|
||||
Child->collectChildrenAddressRanges(U, Ranges);
|
||||
Child = Child->getSibling();
|
||||
}
|
||||
}
|
||||
|
||||
bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
|
||||
const DWARFUnit *U, const uint64_t Address) const {
|
||||
for (const auto& R : getAddressRanges(U)) {
|
||||
if (R.first <= Address && Address < R.second)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
|
||||
|
||||
#include "DWARFAbbreviationDeclaration.h"
|
||||
#include "DWARFDebugRangeList.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
@ -135,9 +136,10 @@ public:
|
||||
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
|
||||
uint64_t &HighPC) const;
|
||||
|
||||
void buildAddressRangeTable(const DWARFUnit *U,
|
||||
DWARFDebugAranges *DebugAranges,
|
||||
uint32_t CUOffsetInAranges) const;
|
||||
DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const;
|
||||
|
||||
void collectChildrenAddressRanges(const DWARFUnit *U,
|
||||
DWARFAddressRangesVector &Ranges) const;
|
||||
|
||||
bool addressRangeContainsAddress(const DWARFUnit *U,
|
||||
const uint64_t Address) const;
|
||||
|
@ -54,13 +54,16 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const {
|
||||
OS << format("%08x <End of list>\n", Offset);
|
||||
}
|
||||
|
||||
bool DWARFDebugRangeList::containsAddress(uint64_t BaseAddress,
|
||||
uint64_t Address) const {
|
||||
DWARFAddressRangesVector
|
||||
DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const {
|
||||
DWARFAddressRangesVector Res;
|
||||
for (const RangeListEntry &RLE : Entries) {
|
||||
if (RLE.isBaseAddressSelectionEntry(AddressSize))
|
||||
if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
|
||||
BaseAddress = RLE.EndAddress;
|
||||
else if (RLE.containsAddress(BaseAddress, Address))
|
||||
return true;
|
||||
} else {
|
||||
Res.push_back(std::make_pair(BaseAddress + RLE.StartAddress,
|
||||
BaseAddress + RLE.EndAddress));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return Res;
|
||||
}
|
||||
|
@ -17,6 +17,9 @@ namespace llvm {
|
||||
|
||||
class raw_ostream;
|
||||
|
||||
/// DWARFAddressRangesVector - represents a set of absolute address ranges.
|
||||
typedef std::vector<std::pair<uint64_t, uint64_t>> DWARFAddressRangesVector;
|
||||
|
||||
class DWARFDebugRangeList {
|
||||
public:
|
||||
struct RangeListEntry {
|
||||
@ -50,10 +53,6 @@ public:
|
||||
else
|
||||
return StartAddress == -1ULL;
|
||||
}
|
||||
bool containsAddress(uint64_t BaseAddress, uint64_t Address) const {
|
||||
return (BaseAddress + StartAddress <= Address) &&
|
||||
(Address < BaseAddress + EndAddress);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
@ -67,10 +66,10 @@ public:
|
||||
void clear();
|
||||
void dump(raw_ostream &OS) const;
|
||||
bool extract(DataExtractor data, uint32_t *offset_ptr);
|
||||
/// containsAddress - Returns true if range list contains the given
|
||||
/// address. Has to be passed base address of the compile unit that
|
||||
/// references this range list.
|
||||
bool containsAddress(uint64_t BaseAddress, uint64_t Address) const;
|
||||
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
|
||||
/// list. Has to be passed base address of the compile unit referencing this
|
||||
/// range list.
|
||||
DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -298,33 +298,26 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
||||
bool clear_dies_if_already_not_parsed,
|
||||
uint32_t CUOffsetInAranges) {
|
||||
void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
|
||||
// This function is usually called if there in no .debug_aranges section
|
||||
// in order to produce a compile unit level set of address ranges that
|
||||
// is accurate. If the DIEs weren't parsed, then we don't want all dies for
|
||||
// all compile units to stay loaded when they weren't needed. So we can end
|
||||
// up parsing the DWARF and then throwing them all away to keep memory usage
|
||||
// down.
|
||||
const bool clear_dies = extractDIEsIfNeeded(false) > 1 &&
|
||||
clear_dies_if_already_not_parsed;
|
||||
DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges);
|
||||
const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
|
||||
DieArray[0].collectChildrenAddressRanges(this, CURanges);
|
||||
|
||||
// Collect address ranges from DIEs in .dwo if necessary.
|
||||
bool DWOCreated = parseDWO();
|
||||
if (DWO.get()) {
|
||||
// If there is a .dwo file for this compile unit, then skeleton CU DIE
|
||||
// doesn't have children, and we should instead build address range table
|
||||
// from DIEs in the .debug_info.dwo section of .dwo file.
|
||||
DWO->getUnit()->buildAddressRangeTable(
|
||||
debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges);
|
||||
}
|
||||
if (DWOCreated && clear_dies_if_already_not_parsed)
|
||||
if (DWO.get())
|
||||
DWO->getUnit()->collectAddressRanges(CURanges);
|
||||
if (DWOCreated)
|
||||
DWO.reset();
|
||||
|
||||
// Keep memory down by clearing DIEs if this generate function
|
||||
// caused them to be parsed.
|
||||
if (clear_dies)
|
||||
if (ClearDIEs)
|
||||
clearDIEs(true);
|
||||
}
|
||||
|
||||
|
@ -129,9 +129,7 @@ public:
|
||||
const char *getCompilationDir();
|
||||
uint64_t getDWOId();
|
||||
|
||||
void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
||||
bool clear_dies_if_already_not_parsed,
|
||||
uint32_t CUOffsetInAranges);
|
||||
void collectAddressRanges(DWARFAddressRangesVector &CURanges);
|
||||
|
||||
/// getInlinedChainForAddress - fetches inlined chain for a given address.
|
||||
/// Returns empty chain if there is no subprogram containing address. The
|
||||
|
Loading…
Reference in New Issue
Block a user