mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 05:24:01 +00:00
DWARF: Generate the address lookup table from the DIE tree if .debug_aranges is not available.
Ported from LLDB. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139732 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -200,3 +200,40 @@ size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) {
|
|||||||
setDIERelations();
|
setDIERelations();
|
||||||
return DieArray.size();
|
return DieArray.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) {
|
||||||
|
if (DieArray.size() > 1) {
|
||||||
|
// std::vectors never get any smaller when resized to a smaller size,
|
||||||
|
// or when clear() or erase() are called, the size will report that it
|
||||||
|
// is smaller, but the memory allocated remains intact (call capacity()
|
||||||
|
// to see this). So we need to create a temporary vector and swap the
|
||||||
|
// contents which will cause just the internal pointers to be swapped
|
||||||
|
// so that when "tmp_array" goes out of scope, it will destroy the
|
||||||
|
// contents.
|
||||||
|
|
||||||
|
// Save at least the compile unit DIE
|
||||||
|
std::vector<DWARFDebugInfoEntryMinimal> tmpArray;
|
||||||
|
DieArray.swap(tmpArray);
|
||||||
|
if (keep_compile_unit_die)
|
||||||
|
DieArray.push_back(tmpArray.front());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
||||||
|
bool clear_dies_if_already_not_parsed){
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
DieArray[0].buildAddressRangeTable(this, debug_aranges);
|
||||||
|
|
||||||
|
// Keep memory down by clearing DIEs if this generate function
|
||||||
|
// caused them to be parsed.
|
||||||
|
if (clear_dies)
|
||||||
|
clearDIEs(true);
|
||||||
|
}
|
||||||
|
@ -91,6 +91,11 @@ public:
|
|||||||
DieArray.reserve(getDebugInfoSize() / 14);
|
DieArray.reserve(getDebugInfoSize() / 14);
|
||||||
DieArray.push_back(die);
|
DieArray.push_back(die);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearDIEs(bool keep_compile_unit_die);
|
||||||
|
|
||||||
|
void buildAddressRangeTable(DWARFDebugAranges *debug_aranges,
|
||||||
|
bool clear_dies_if_already_not_parsed);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,8 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() {
|
|||||||
|
|
||||||
Aranges.reset(new DWARFDebugAranges());
|
Aranges.reset(new DWARFDebugAranges());
|
||||||
Aranges->extract(arangesData);
|
Aranges->extract(arangesData);
|
||||||
|
if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs.
|
||||||
|
Aranges->generate(this);
|
||||||
return Aranges.get();
|
return Aranges.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +83,19 @@ bool DWARFDebugAranges::extract(DataExtractor debug_aranges_data) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DWARFDebugAranges::generate(DWARFContext *ctx) {
|
||||||
|
clear();
|
||||||
|
if (ctx) {
|
||||||
|
const uint32_t num_compile_units = ctx->getNumCompileUnits();
|
||||||
|
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
|
||||||
|
DWARFCompileUnit *cu = ctx->getCompileUnitAtIndex(cu_idx);
|
||||||
|
if (cu)
|
||||||
|
cu->buildAddressRangeTable(this, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
void DWARFDebugAranges::dump(raw_ostream &OS) const {
|
void DWARFDebugAranges::dump(raw_ostream &OS) const {
|
||||||
const uint32_t num_ranges = getNumRanges();
|
const uint32_t num_ranges = getNumRanges();
|
||||||
for (uint32_t i = 0; i < num_ranges; ++i) {
|
for (uint32_t i = 0; i < num_ranges; ++i) {
|
||||||
|
@ -64,6 +64,7 @@ public:
|
|||||||
bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const;
|
bool allRangesAreContiguous(uint64_t& LoPC, uint64_t& HiPC) const;
|
||||||
bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const;
|
bool getMaxRange(uint64_t& LoPC, uint64_t& HiPC) const;
|
||||||
bool extract(DataExtractor debug_aranges_data);
|
bool extract(DataExtractor debug_aranges_data);
|
||||||
|
bool generate(DWARFContext *ctx);
|
||||||
|
|
||||||
// Use append range multiple times and then call sort
|
// Use append range multiple times and then call sort
|
||||||
void appendRange(uint32_t cu_offset, uint64_t low_pc, uint64_t high_pc);
|
void appendRange(uint32_t cu_offset, uint64_t low_pc, uint64_t high_pc);
|
||||||
|
@ -397,7 +397,8 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned(
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(const DWARFCompileUnit* cu,
|
DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
|
||||||
|
const DWARFCompileUnit* cu,
|
||||||
const uint16_t attr,
|
const uint16_t attr,
|
||||||
uint64_t fail_value) const {
|
uint64_t fail_value) const {
|
||||||
DWARFFormValue form_value;
|
DWARFFormValue form_value;
|
||||||
@ -405,3 +406,26 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(const DWARFCompileUnit*
|
|||||||
return form_value.getReference(cu);
|
return form_value.getReference(cu);
|
||||||
return fail_value;
|
return fail_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu,
|
||||||
|
DWARFDebugAranges *debug_aranges)
|
||||||
|
const {
|
||||||
|
if (AbbrevDecl) {
|
||||||
|
uint16_t tag = AbbrevDecl->getTag();
|
||||||
|
if (tag == DW_TAG_subprogram) {
|
||||||
|
uint64_t hi_pc = -1ULL;
|
||||||
|
uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL);
|
||||||
|
if (lo_pc != -1ULL)
|
||||||
|
hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL);
|
||||||
|
if (hi_pc != -1ULL)
|
||||||
|
debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DWARFDebugInfoEntryMinimal *child = getFirstChild();
|
||||||
|
while (child) {
|
||||||
|
child->buildAddressRangeTable(cu, debug_aranges);
|
||||||
|
child = child->getSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class DWARFDebugAranges;
|
||||||
class DWARFCompileUnit;
|
class DWARFCompileUnit;
|
||||||
class DWARFContext;
|
class DWARFContext;
|
||||||
class DWARFFormValue;
|
class DWARFFormValue;
|
||||||
@ -124,6 +125,9 @@ public:
|
|||||||
int64_t getAttributeValueAsSigned(const DWARFCompileUnit* cu,
|
int64_t getAttributeValueAsSigned(const DWARFCompileUnit* cu,
|
||||||
const uint16_t attr,
|
const uint16_t attr,
|
||||||
int64_t fail_value) const;
|
int64_t fail_value) const;
|
||||||
|
|
||||||
|
void buildAddressRangeTable(const DWARFCompileUnit *cu,
|
||||||
|
DWARFDebugAranges *debug_aranges) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user