in src/backward.h [3145:3244]
Dwarf_Die find_die(dwarf_fileobject& fobj, Dwarf_Addr addr)
{
// Let's get to work! First see if we have a debug_aranges section so
// we can speed up the search
Dwarf_Debug dwarf = fobj.dwarf_handle.get();
Dwarf_Error error = DW_DLE_NE;
Dwarf_Arange* aranges;
Dwarf_Signed arange_count;
Dwarf_Die returnDie;
bool found = false;
if (dwarf_get_aranges(dwarf, &aranges, &arange_count, &error) != DW_DLV_OK) {
aranges = NULL;
}
if (aranges) {
// We have aranges. Get the one where our address is.
Dwarf_Arange arange;
if (dwarf_get_arange(aranges, arange_count, addr, &arange, &error) == DW_DLV_OK) {
// We found our address. Get the compilation-unit DIE offset
// represented by the given address range.
Dwarf_Off cu_die_offset;
if (dwarf_get_cu_die_offset(arange, &cu_die_offset, &error) == DW_DLV_OK) {
// Get the DIE at the offset returned by the aranges search.
// We set is_info to 1 to specify that the offset is from
// the .debug_info section (and not .debug_types)
int dwarf_result = dwarf_offdie_b(dwarf, cu_die_offset, 1, &returnDie, &error);
found = dwarf_result == DW_DLV_OK;
}
dwarf_dealloc(dwarf, arange, DW_DLA_ARANGE);
}
}
if (found)
return returnDie; // The caller is responsible for freeing the die
// The search for aranges failed. Try to find our address by scanning
// all compilation units.
Dwarf_Unsigned next_cu_header;
Dwarf_Half tag = 0;
returnDie = 0;
while (!found &&
dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, &next_cu_header, 0, &error) == DW_DLV_OK) {
if (returnDie)
dwarf_dealloc(dwarf, returnDie, DW_DLA_DIE);
if (dwarf_siblingof(dwarf, 0, &returnDie, &error) == DW_DLV_OK) {
if ((dwarf_tag(returnDie, &tag, &error) == DW_DLV_OK) && tag == DW_TAG_compile_unit) {
if (die_has_pc(fobj, returnDie, addr)) {
found = true;
}
}
}
}
if (found) {
while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, &next_cu_header, 0, &error) == DW_DLV_OK) {
// Reset the cu header state. Libdwarf's next_cu_header API
// keeps its own iterator per Dwarf_Debug that can't be reset.
// We need to keep fetching elements until the end.
}
}
if (found)
return returnDie;
// We couldn't find any compilation units with ranges or a high/low pc.
// Try again by looking at all DIEs in all compilation units.
Dwarf_Die cudie;
while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, &next_cu_header, 0, &error) == DW_DLV_OK) {
if (dwarf_siblingof(dwarf, 0, &cudie, &error) == DW_DLV_OK) {
Dwarf_Die die_mem = 0;
Dwarf_Die resultDie = find_fundie_by_pc(fobj, cudie, addr, die_mem);
if (resultDie) {
found = true;
break;
}
}
}
if (found) {
while (dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, &next_cu_header, 0, &error) == DW_DLV_OK) {
// Reset the cu header state. Libdwarf's next_cu_header API
// keeps its own iterator per Dwarf_Debug that can't be reset.
// We need to keep fetching elements until the end.
}
}
if (found)
return cudie;
// We failed.
return NULL;
}