mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-16 12:24:03 +00: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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206624 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -58,8 +58,13 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) {
|
|||||||
// manually build aranges for the rest of them.
|
// manually build aranges for the rest of them.
|
||||||
for (const auto &CU : CTX->compile_units()) {
|
for (const auto &CU : CTX->compile_units()) {
|
||||||
uint32_t CUOffset = CU->getOffset();
|
uint32_t CUOffset = CU->getOffset();
|
||||||
if (ParsedCUOffsets.insert(CUOffset).second)
|
if (ParsedCUOffsets.insert(CUOffset).second) {
|
||||||
CU->buildAddressRangeTable(this, true, CUOffset);
|
DWARFAddressRangesVector CURanges;
|
||||||
|
CU->collectAddressRanges(CURanges);
|
||||||
|
for (const auto &R : CURanges) {
|
||||||
|
appendRange(CUOffset, R.first, R.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sortAndMinimize();
|
sortAndMinimize();
|
||||||
|
@ -226,39 +226,47 @@ bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
|
|||||||
return (HighPC != -1ULL);
|
return (HighPC != -1ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFDebugInfoEntryMinimal::buildAddressRangeTable(
|
DWARFAddressRangesVector
|
||||||
const DWARFUnit *U, DWARFDebugAranges *DebugAranges,
|
DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const {
|
||||||
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 {
|
|
||||||
if (isNULL())
|
if (isNULL())
|
||||||
return false;
|
return DWARFAddressRangesVector{};
|
||||||
|
// Single range specified by low/high PC.
|
||||||
uint64_t LowPC, HighPC;
|
uint64_t LowPC, HighPC;
|
||||||
if (getLowAndHighPC(U, LowPC, HighPC))
|
if (getLowAndHighPC(U, LowPC, HighPC)) {
|
||||||
return (LowPC <= Address && Address <= HighPC);
|
return DWARFAddressRangesVector{std::make_pair(LowPC, HighPC)};
|
||||||
// Try to get address ranges from .debug_ranges section.
|
}
|
||||||
|
// Multiple ranges from .debug_ranges section.
|
||||||
uint32_t RangesOffset =
|
uint32_t RangesOffset =
|
||||||
getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
|
getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
|
||||||
if (RangesOffset != -1U) {
|
if (RangesOffset != -1U) {
|
||||||
DWARFDebugRangeList RangeList;
|
DWARFDebugRangeList RangeList;
|
||||||
if (U->extractRangeList(RangesOffset, 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
|
#define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H
|
||||||
|
|
||||||
#include "DWARFAbbreviationDeclaration.h"
|
#include "DWARFAbbreviationDeclaration.h"
|
||||||
|
#include "DWARFDebugRangeList.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
|
||||||
@ -135,9 +136,10 @@ public:
|
|||||||
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
|
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC,
|
||||||
uint64_t &HighPC) const;
|
uint64_t &HighPC) const;
|
||||||
|
|
||||||
void buildAddressRangeTable(const DWARFUnit *U,
|
DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const;
|
||||||
DWARFDebugAranges *DebugAranges,
|
|
||||||
uint32_t CUOffsetInAranges) const;
|
void collectChildrenAddressRanges(const DWARFUnit *U,
|
||||||
|
DWARFAddressRangesVector &Ranges) const;
|
||||||
|
|
||||||
bool addressRangeContainsAddress(const DWARFUnit *U,
|
bool addressRangeContainsAddress(const DWARFUnit *U,
|
||||||
const uint64_t Address) const;
|
const uint64_t Address) const;
|
||||||
|
@ -54,13 +54,16 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const {
|
|||||||
OS << format("%08x <End of list>\n", Offset);
|
OS << format("%08x <End of list>\n", Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DWARFDebugRangeList::containsAddress(uint64_t BaseAddress,
|
DWARFAddressRangesVector
|
||||||
uint64_t Address) const {
|
DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const {
|
||||||
|
DWARFAddressRangesVector Res;
|
||||||
for (const RangeListEntry &RLE : Entries) {
|
for (const RangeListEntry &RLE : Entries) {
|
||||||
if (RLE.isBaseAddressSelectionEntry(AddressSize))
|
if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
|
||||||
BaseAddress = RLE.EndAddress;
|
BaseAddress = RLE.EndAddress;
|
||||||
else if (RLE.containsAddress(BaseAddress, Address))
|
} else {
|
||||||
return true;
|
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;
|
class raw_ostream;
|
||||||
|
|
||||||
|
/// DWARFAddressRangesVector - represents a set of absolute address ranges.
|
||||||
|
typedef std::vector<std::pair<uint64_t, uint64_t>> DWARFAddressRangesVector;
|
||||||
|
|
||||||
class DWARFDebugRangeList {
|
class DWARFDebugRangeList {
|
||||||
public:
|
public:
|
||||||
struct RangeListEntry {
|
struct RangeListEntry {
|
||||||
@ -50,10 +53,6 @@ public:
|
|||||||
else
|
else
|
||||||
return StartAddress == -1ULL;
|
return StartAddress == -1ULL;
|
||||||
}
|
}
|
||||||
bool containsAddress(uint64_t BaseAddress, uint64_t Address) const {
|
|
||||||
return (BaseAddress + StartAddress <= Address) &&
|
|
||||||
(Address < BaseAddress + EndAddress);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -67,10 +66,10 @@ public:
|
|||||||
void clear();
|
void clear();
|
||||||
void dump(raw_ostream &OS) const;
|
void dump(raw_ostream &OS) const;
|
||||||
bool extract(DataExtractor data, uint32_t *offset_ptr);
|
bool extract(DataExtractor data, uint32_t *offset_ptr);
|
||||||
/// containsAddress - Returns true if range list contains the given
|
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
|
||||||
/// address. Has to be passed base address of the compile unit that
|
/// list. Has to be passed base address of the compile unit referencing this
|
||||||
/// references this range list.
|
/// range list.
|
||||||
bool containsAddress(uint64_t BaseAddress, uint64_t Address) const;
|
DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
@ -298,33 +298,26 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
|
||||||
DWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
|
||||||
bool clear_dies_if_already_not_parsed,
|
|
||||||
uint32_t CUOffsetInAranges) {
|
|
||||||
// This function is usually called if there in no .debug_aranges section
|
// 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
|
// 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
|
// 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
|
// 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
|
// up parsing the DWARF and then throwing them all away to keep memory usage
|
||||||
// down.
|
// down.
|
||||||
const bool clear_dies = extractDIEsIfNeeded(false) > 1 &&
|
const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
|
||||||
clear_dies_if_already_not_parsed;
|
DieArray[0].collectChildrenAddressRanges(this, CURanges);
|
||||||
DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges);
|
|
||||||
|
// Collect address ranges from DIEs in .dwo if necessary.
|
||||||
bool DWOCreated = parseDWO();
|
bool DWOCreated = parseDWO();
|
||||||
if (DWO.get()) {
|
if (DWO.get())
|
||||||
// If there is a .dwo file for this compile unit, then skeleton CU DIE
|
DWO->getUnit()->collectAddressRanges(CURanges);
|
||||||
// doesn't have children, and we should instead build address range table
|
if (DWOCreated)
|
||||||
// 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)
|
|
||||||
DWO.reset();
|
DWO.reset();
|
||||||
|
|
||||||
// Keep memory down by clearing DIEs if this generate function
|
// Keep memory down by clearing DIEs if this generate function
|
||||||
// caused them to be parsed.
|
// caused them to be parsed.
|
||||||
if (clear_dies)
|
if (ClearDIEs)
|
||||||
clearDIEs(true);
|
clearDIEs(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,9 +129,7 @@ public:
|
|||||||
const char *getCompilationDir();
|
const char *getCompilationDir();
|
||||||
uint64_t getDWOId();
|
uint64_t getDWOId();
|
||||||
|
|
||||||
void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
void collectAddressRanges(DWARFAddressRangesVector &CURanges);
|
||||||
bool clear_dies_if_already_not_parsed,
|
|
||||||
uint32_t CUOffsetInAranges);
|
|
||||||
|
|
||||||
/// getInlinedChainForAddress - fetches inlined chain for a given address.
|
/// getInlinedChainForAddress - fetches inlined chain for a given address.
|
||||||
/// Returns empty chain if there is no subprogram containing address. The
|
/// Returns empty chain if there is no subprogram containing address. The
|
||||||
|
Reference in New Issue
Block a user