[lldb/DWARF] Simplify DWARFDebugInfoEntry::LookupAddress

Summary:
This method was doing a lot more than it's only caller needed
(DWARFDIE::LookupDeepestBlock) needed, so I inline it into the caller,
and remove any code which is not actually used. This includes code for
searching for the deepest function, and the code for working around
incomplete DW_AT_low_pc/high_pc attributes on a compile unit DIE (modern
compiler get this right, and this method is called on function DIEs
anyway).

This also improves our llvm consistency, as llvm::DWARFDebugInfoEntry is
just a very simple struct with no nontrivial logic.

Reviewers: JDevlieghere, aprantl

Subscribers: lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D72920
This commit is contained in:
Pavel Labath 2020-01-17 14:58:46 +01:00
parent 8248190a73
commit b7af1bfa6e
3 changed files with 55 additions and 223 deletions

View File

@ -140,25 +140,64 @@ DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
}
DWARFDIE
DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
if (IsValid()) {
SymbolFileDWARF *dwarf = GetDWARF();
DWARFUnit *cu = GetCU();
DWARFDebugInfoEntry *function_die = nullptr;
DWARFDebugInfoEntry *block_die = nullptr;
if (m_die->LookupAddress(file_addr, cu, &function_die, &block_die)) {
if (block_die && block_die != function_die) {
if (cu->ContainsDIEOffset(block_die->GetOffset()))
return DWARFDIE(cu, block_die);
else
return DWARFDIE(dwarf->DebugInfo()->GetUnit(DIERef(
cu->GetSymbolFileDWARF().GetDwoNum(),
cu->GetDebugSection(), block_die->GetOffset())),
block_die);
DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const {
if (!IsValid())
return DWARFDIE();
DWARFDIE result;
bool check_children = false;
bool match_addr_range = false;
switch (Tag()) {
case DW_TAG_class_type:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_common_block:
check_children = true;
break;
case DW_TAG_compile_unit:
case DW_TAG_module:
case DW_TAG_catch_block:
case DW_TAG_subprogram:
case DW_TAG_try_block:
case DW_TAG_partial_unit:
match_addr_range = true;
break;
case DW_TAG_lexical_block:
case DW_TAG_inlined_subroutine:
check_children = true;
match_addr_range = true;
break;
default:
break;
}
if (match_addr_range) {
DWARFRangeList ranges;
if (m_die->GetAttributeAddressRanges(m_cu, ranges,
/*check_hi_lo_pc=*/true) &&
ranges.FindEntryThatContains(address)) {
check_children = true;
switch (Tag()) {
default:
break;
case DW_TAG_inlined_subroutine: // Inlined Function
case DW_TAG_lexical_block: // Block { } in code
result = *this;
break;
}
} else {
check_children = false;
}
}
return DWARFDIE();
if (check_children) {
for (DWARFDIE child = GetFirstChild(); child; child = child.GetSibling()) {
if (DWARFDIE child_result = child.LookupDeepestBlock(address))
return child_result;
}
}
return result;
}
const char *DWARFDIE::GetMangledName() const {

View File

@ -993,209 +993,6 @@ DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
return storage.c_str();
}
bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die) {
bool found_address = false;
if (m_tag) {
bool check_children = false;
bool match_addr_range = false;
// printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset,
// DW_TAG_value_to_name(tag), address);
switch (m_tag) {
case DW_TAG_array_type:
break;
case DW_TAG_class_type:
check_children = true;
break;
case DW_TAG_entry_point:
case DW_TAG_enumeration_type:
case DW_TAG_formal_parameter:
case DW_TAG_imported_declaration:
case DW_TAG_label:
break;
case DW_TAG_lexical_block:
check_children = true;
match_addr_range = true;
break;
case DW_TAG_member:
case DW_TAG_pointer_type:
case DW_TAG_reference_type:
break;
case DW_TAG_compile_unit:
match_addr_range = true;
break;
case DW_TAG_string_type:
break;
case DW_TAG_structure_type:
check_children = true;
break;
case DW_TAG_subroutine_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
case DW_TAG_unspecified_parameters:
case DW_TAG_variant:
break;
case DW_TAG_common_block:
check_children = true;
break;
case DW_TAG_common_inclusion:
case DW_TAG_inheritance:
break;
case DW_TAG_inlined_subroutine:
check_children = true;
match_addr_range = true;
break;
case DW_TAG_module:
match_addr_range = true;
break;
case DW_TAG_ptr_to_member_type:
case DW_TAG_set_type:
case DW_TAG_subrange_type:
case DW_TAG_with_stmt:
case DW_TAG_access_declaration:
case DW_TAG_base_type:
break;
case DW_TAG_catch_block:
match_addr_range = true;
break;
case DW_TAG_const_type:
case DW_TAG_constant:
case DW_TAG_enumerator:
case DW_TAG_file_type:
case DW_TAG_friend:
case DW_TAG_namelist:
case DW_TAG_namelist_item:
case DW_TAG_packed_type:
break;
case DW_TAG_subprogram:
match_addr_range = true;
break;
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
case DW_TAG_GNU_template_parameter_pack:
case DW_TAG_thrown_type:
break;
case DW_TAG_try_block:
match_addr_range = true;
break;
case DW_TAG_variant_part:
case DW_TAG_variable:
case DW_TAG_volatile_type:
case DW_TAG_dwarf_procedure:
case DW_TAG_restrict_type:
case DW_TAG_interface_type:
break;
case DW_TAG_namespace:
check_children = true;
break;
case DW_TAG_imported_module:
case DW_TAG_unspecified_type:
break;
case DW_TAG_partial_unit:
match_addr_range = true;
break;
case DW_TAG_imported_unit:
case DW_TAG_shared_type:
default:
break;
}
if (match_addr_range) {
dw_addr_t lo_pc =
GetAttributeValueAsAddress(cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (lo_pc != LLDB_INVALID_ADDRESS) {
dw_addr_t hi_pc = GetAttributeHighPC(cu, lo_pc, LLDB_INVALID_ADDRESS);
if (hi_pc != LLDB_INVALID_ADDRESS) {
// printf("\n0x%8.8x: %30s: address = 0x%8.8x [0x%8.8x - 0x%8.8x) ",
// m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc);
if ((lo_pc <= address) && (address < hi_pc)) {
found_address = true;
// puts("***MATCH***");
switch (m_tag) {
case DW_TAG_compile_unit: // File
case DW_TAG_partial_unit: // File
check_children =
((function_die != nullptr) || (block_die != nullptr));
break;
case DW_TAG_subprogram: // Function
if (function_die)
*function_die = this;
check_children = (block_die != nullptr);
break;
case DW_TAG_inlined_subroutine: // Inlined Function
case DW_TAG_lexical_block: // Block { } in code
if (block_die) {
*block_die = this;
check_children = true;
}
break;
default:
check_children = true;
break;
}
}
} else {
// Compile units may not have a valid high/low pc when there
// are address gaps in subroutines so we must always search
// if there is no valid high and low PC.
check_children =
(m_tag == DW_TAG_compile_unit || m_tag == DW_TAG_partial_unit) &&
((function_die != nullptr) || (block_die != nullptr));
}
} else {
DWARFRangeList ranges;
if (GetAttributeAddressRanges(cu, ranges, /*check_hi_lo_pc*/ false) &&
ranges.FindEntryThatContains(address)) {
found_address = true;
// puts("***MATCH***");
switch (m_tag) {
case DW_TAG_compile_unit: // File
case DW_TAG_partial_unit: // File
check_children =
((function_die != nullptr) || (block_die != nullptr));
break;
case DW_TAG_subprogram: // Function
if (function_die)
*function_die = this;
check_children = (block_die != nullptr);
break;
case DW_TAG_inlined_subroutine: // Inlined Function
case DW_TAG_lexical_block: // Block { } in code
if (block_die) {
*block_die = this;
check_children = true;
}
break;
default:
check_children = true;
break;
}
} else {
check_children = false;
}
}
}
if (check_children) {
// printf("checking children\n");
DWARFDebugInfoEntry *child = GetFirstChild();
while (child) {
if (child->LookupAddress(address, cu, function_die, block_die))
return true;
child = child->GetSibling();
}
}
}
return found_address;
}
lldb::offset_t DWARFDebugInfoEntry::GetFirstAttributeOffset() const {
return GetOffset() + llvm::getULEB128Size(m_abbr_idx);
}

View File

@ -50,10 +50,6 @@ public:
bool Extract(const lldb_private::DWARFDataExtractor &data,
const DWARFUnit *cu, lldb::offset_t *offset_ptr);
bool LookupAddress(const dw_addr_t address, DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die);
size_t GetAttributes(const DWARFUnit *cu,
DWARFAttributes &attrs,
uint32_t curr_depth = 0)