Parse DW_AT_ranges for compile units on Darwin when .debug_aranges is not available for the current compile unit.
<rdar://problem/16321434> llvm-svn: 203985
This commit is contained in:
parent
e3b5c99fde
commit
26c1fe3568
|
@ -361,18 +361,43 @@ DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)
|
||||||
|
|
||||||
void
|
void
|
||||||
DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
|
DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
|
||||||
DWARFDebugAranges* debug_aranges,
|
DWARFDebugAranges* debug_aranges)
|
||||||
bool clear_dies_if_already_not_parsed)
|
|
||||||
{
|
{
|
||||||
// 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.
|
||||||
// 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
|
// First get the compile unit DIE only and check if it has a DW_AT_ranges
|
||||||
// down.
|
const DWARFDebugInfoEntry* die = GetCompileUnitDIEOnly();
|
||||||
|
|
||||||
|
const dw_offset_t cu_offset = GetOffset();
|
||||||
|
if (die)
|
||||||
|
{
|
||||||
|
DWARFDebugRanges::RangeList ranges;
|
||||||
|
const size_t num_ranges = die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false);
|
||||||
|
if (num_ranges > 0)
|
||||||
|
{
|
||||||
|
// This compile unit has DW_AT_ranges, assume this is correct if it
|
||||||
|
// is present since clang no longer makes .debug_aranges by default
|
||||||
|
// and it emits DW_AT_ranges for DW_TAG_compile_units. GCC also does
|
||||||
|
// this with recent GCC builds.
|
||||||
|
for (size_t i=0; i<num_ranges; ++i)
|
||||||
|
{
|
||||||
|
const DWARFDebugRanges::RangeList::Entry &range = ranges.GetEntryRef(i);
|
||||||
|
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
return; // We got all of our ranges from the DW_AT_ranges attribute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
|
||||||
|
|
||||||
|
// 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;
|
const bool clear_dies = ExtractDIEsIfNeeded (false) > 1;
|
||||||
|
|
||||||
const DWARFDebugInfoEntry* die = DIE();
|
die = DIE();
|
||||||
if (die)
|
if (die)
|
||||||
die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
|
die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
|
||||||
|
|
||||||
|
@ -397,7 +422,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
|
||||||
for (uint32_t idx=0; idx<num_ranges; ++idx)
|
for (uint32_t idx=0; idx<num_ranges; ++idx)
|
||||||
{
|
{
|
||||||
const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
|
const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
|
||||||
debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
|
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
|
||||||
printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
|
printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,7 @@ public:
|
||||||
dw_addr_t GetBaseAddress() const { return m_base_addr; }
|
dw_addr_t GetBaseAddress() const { return m_base_addr; }
|
||||||
void ClearDIEs(bool keep_compile_unit_die);
|
void ClearDIEs(bool keep_compile_unit_die);
|
||||||
void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
|
void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
|
||||||
DWARFDebugAranges* debug_aranges,
|
DWARFDebugAranges* debug_aranges);
|
||||||
bool clear_dies_if_already_not_parsed);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SetBaseAddress(dw_addr_t base_addr)
|
SetBaseAddress(dw_addr_t base_addr)
|
||||||
|
|
|
@ -93,14 +93,13 @@ DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data)
|
||||||
DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
|
DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
|
||||||
if (debug_info)
|
if (debug_info)
|
||||||
{
|
{
|
||||||
const bool clear_dies_if_already_not_parsed = true;
|
|
||||||
uint32_t cu_idx = 0;
|
uint32_t cu_idx = 0;
|
||||||
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
|
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
|
||||||
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
|
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
|
||||||
{
|
{
|
||||||
DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
|
DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
|
||||||
if (cu)
|
if (cu)
|
||||||
cu->BuildAddressRangeTable(dwarf2Data, this, clear_dies_if_already_not_parsed);
|
cu->BuildAddressRangeTable(dwarf2Data, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !IsEmpty();
|
return !IsEmpty();
|
||||||
|
|
|
@ -79,7 +79,6 @@ DWARFDebugInfo::GetCompileUnitAranges ()
|
||||||
// Manually build arange data for everything that wasn't in the .debug_aranges table.
|
// Manually build arange data for everything that wasn't in the .debug_aranges table.
|
||||||
bool printed = false;
|
bool printed = false;
|
||||||
const size_t num_compile_units = GetNumCompileUnits();
|
const size_t num_compile_units = GetNumCompileUnits();
|
||||||
const bool clear_dies_if_already_not_parsed = true;
|
|
||||||
for (size_t idx = 0; idx < num_compile_units; ++idx)
|
for (size_t idx = 0; idx < num_compile_units; ++idx)
|
||||||
{
|
{
|
||||||
DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
|
DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
|
||||||
|
@ -94,7 +93,7 @@ DWARFDebugInfo::GetCompileUnitAranges ()
|
||||||
m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
|
m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
|
||||||
printed = true;
|
printed = true;
|
||||||
}
|
}
|
||||||
cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed);
|
cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1485,6 +1485,40 @@ DWARFDebugInfoEntry::GetAttributeAddressRange
|
||||||
hi_pc = fail_value;
|
hi_pc = fail_value;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF* dwarf2Data,
|
||||||
|
const DWARFCompileUnit* cu,
|
||||||
|
DWARFDebugRanges::RangeList &ranges,
|
||||||
|
bool check_hi_lo_pc) const
|
||||||
|
{
|
||||||
|
ranges.Clear();
|
||||||
|
|
||||||
|
dw_offset_t ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
|
||||||
|
if (ranges_offset != DW_INVALID_OFFSET)
|
||||||
|
{
|
||||||
|
dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
|
||||||
|
if (debug_ranges_offset != DW_INVALID_OFFSET)
|
||||||
|
{
|
||||||
|
DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
|
||||||
|
|
||||||
|
debug_ranges->FindRanges(debug_ranges_offset, ranges);
|
||||||
|
ranges.Slide (cu->GetBaseAddress());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (check_hi_lo_pc)
|
||||||
|
{
|
||||||
|
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
|
||||||
|
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
|
||||||
|
if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS))
|
||||||
|
{
|
||||||
|
if (lo_pc < hi_pc)
|
||||||
|
ranges.Append(DWARFDebugRanges::RangeList::Entry(lo_pc, hi_pc - lo_pc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ranges.GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// GetAttributeValueAsLocation
|
// GetAttributeValueAsLocation
|
||||||
//
|
//
|
||||||
|
|
|
@ -210,6 +210,12 @@ public:
|
||||||
dw_addr_t& hi_pc,
|
dw_addr_t& hi_pc,
|
||||||
uint64_t fail_value) const;
|
uint64_t fail_value) const;
|
||||||
|
|
||||||
|
size_t GetAttributeAddressRanges (
|
||||||
|
SymbolFileDWARF* dwarf2Data,
|
||||||
|
const DWARFCompileUnit* cu,
|
||||||
|
DWARFDebugRanges::RangeList &ranges,
|
||||||
|
bool check_hi_lo_pc) const;
|
||||||
|
|
||||||
dw_offset_t GetAttributeValueAsLocation(
|
dw_offset_t GetAttributeValueAsLocation(
|
||||||
SymbolFileDWARF* dwarf2Data,
|
SymbolFileDWARF* dwarf2Data,
|
||||||
const DWARFCompileUnit* cu,
|
const DWARFCompileUnit* cu,
|
||||||
|
|
Loading…
Reference in New Issue