Add support for DW_AT_ranges_base attribute

It is a new attribute emitted by clang as a GNU extension and will
be part of Dwarf5. The purpose of the attribute is to specify a compile
unit level base value for all DW_AT_ranges to reduce the number of
relocations have to be done by the linker.

Fixes (at least partially): https://llvm.org/pr28826

Differential revision: https://reviews.llvm.org/D24514

llvm-svn: 281595
This commit is contained in:
Tamas Berghammer 2016-09-15 08:53:33 +00:00
parent 2cc4e3e04e
commit 2540a553e5
10 changed files with 95 additions and 33 deletions

View File

@ -38,3 +38,46 @@ class SymbolContextTwoFilesTestCase(TestBase):
symbol_address, lldb.eSymbolContextFunction)
self.assertEqual(symbol_name,
sc_by_address.GetFunction().GetName())
@add_test_categories(['pyapi'])
def test_ranges_in_multiple_compile_unit(self):
"""This test verifies that we correctly handle the case when multiple
compile unit contains DW_AT_ranges and DW_AT_ranges_base attributes."""
self.build()
exe = os.path.join(os.getcwd(), "a.out")
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
source1 = "file1.cpp"
line1 = line_number(source1, '// Break1')
breakpoint1 = target.BreakpointCreateByLocation(source1, line1)
self.assertIsNotNone(breakpoint1)
self.assertTrue(breakpoint1.IsValid())
source2 = "file2.cpp"
line2 = line_number(source2, '// Break2')
breakpoint2 = target.BreakpointCreateByLocation(source2, line2)
self.assertIsNotNone(breakpoint2)
self.assertTrue(breakpoint2.IsValid())
process = target.LaunchSimple(None, None, os.getcwd())
self.assertIsNotNone(process, PROCESS_IS_VALID)
threads = lldbutil.get_threads_stopped_at_breakpoint(
process, breakpoint2)
self.assertEqual(len(threads), 1)
frame = threads[0].GetFrameAtIndex(0)
value = frame.FindVariable("x")
self.assertTrue(value.IsValid())
process.Continue()
threads = lldbutil.get_threads_stopped_at_breakpoint(
process, breakpoint1)
self.assertEqual(len(threads), 1)
frame = threads[0].GetFrameAtIndex(0)
value = frame.FindVariable("x")
self.assertTrue(value.IsValid())
process.Continue()

View File

@ -1,11 +1,11 @@
struct struct1
{
static void
f();
struct struct1 {
~struct1();
static void f();
};
struct struct2
{
static void
f();
struct struct2 {
~struct2();
static void f();
};
int g();

View File

@ -1,13 +1,21 @@
#include "decls.h"
void
struct1::f()
{
int g() {
return 1;
}
int main()
{
struct1::f();
struct2::f();
return 0;
struct1::~struct1() {
int x = g(); // Break1
}
void struct1::f() {}
int main() {
struct1::f();
struct2::f();
struct1 s1;
struct2 s2;
return 0;
}

View File

@ -1,6 +1,7 @@
#include "decls.h"
void
struct2::f()
{
struct2::~struct2() {
int x = g(); // Break2
}
void struct2::f() {}

View File

@ -46,7 +46,7 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data)
m_producer_version_minor(0), m_producer_version_update(0),
m_language_type(eLanguageTypeUnknown), m_is_dwarf64(false),
m_is_optimized(eLazyBoolCalculate), m_addr_base(0),
m_base_obj_offset(DW_INVALID_OFFSET) {}
m_ranges_base(0), m_base_obj_offset(DW_INVALID_OFFSET) {}
DWARFCompileUnit::~DWARFCompileUnit() {}
@ -307,7 +307,9 @@ void DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry &die) {
dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(
m_dwarf2Data, this, DW_AT_GNU_addr_base, 0);
dwo_cu->SetAddrBase(addr_base, m_offset);
dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
m_dwarf2Data, this, DW_AT_GNU_ranges_base, 0);
dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset);
}
dw_offset_t DWARFCompileUnit::GetAbbrevOffset() const {
@ -1114,8 +1116,10 @@ void DWARFCompileUnit::SetUserData(void *d) {
}
void DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base,
dw_addr_t ranges_base,
dw_offset_t base_obj_offset) {
m_addr_base = addr_base;
m_ranges_base = ranges_base;
m_base_obj_offset = base_obj_offset;
}

View File

@ -70,7 +70,8 @@ public:
uint8_t GetAddressByteSize() const { return m_addr_size; }
dw_addr_t GetBaseAddress() const { return m_base_addr; }
dw_addr_t GetAddrBase() const { return m_addr_base; }
void SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset);
dw_addr_t GetRangesBase() const { return m_ranges_base; }
void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base, dw_offset_t base_obj_offset);
void ClearDIEs(bool keep_compile_unit_die);
void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
DWARFDebugAranges *debug_aranges);
@ -185,10 +186,11 @@ protected:
lldb::LanguageType m_language_type;
bool m_is_dwarf64;
lldb_private::LazyBool m_is_optimized;
dw_addr_t m_addr_base; // Value of DW_AT_addr_base
dw_offset_t
m_base_obj_offset; // If this is a dwo compile unit this is the offset of
// the base compile unit in the main object file
dw_addr_t m_addr_base; // Value of DW_AT_addr_base
dw_addr_t m_ranges_base; // Value of DW_AT_ranges_base
dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the
// offset of the base compile unit in the main
// object file
void ParseProducerInfo();

View File

@ -450,7 +450,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
case DW_AT_ranges: {
const DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
if (debug_ranges) {
debug_ranges->FindRanges(form_value.Unsigned(), ranges);
debug_ranges->FindRanges(cu->GetRangesBase(), form_value.Unsigned(), ranges);
// All DW_AT_ranges are relative to the base address of the
// compile unit. We add the compile unit base address to make
// sure all the addresses are properly fixed up.
@ -1108,7 +1108,7 @@ size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
if (debug_ranges_offset != DW_INVALID_OFFSET) {
DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
debug_ranges->FindRanges(debug_ranges_offset, ranges);
debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
ranges.Slide(cu->GetBaseAddress());
} else if (check_hi_lo_pc) {
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
@ -1772,7 +1772,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
if (debug_ranges_offset != DW_INVALID_OFFSET) {
DWARFRangeList ranges;
DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
debug_ranges->FindRanges(debug_ranges_offset, ranges);
debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
// All DW_AT_ranges are relative to the base address of the
// compile unit. We add the compile unit base address to make
// sure all the addresses are properly fixed up.

View File

@ -118,9 +118,11 @@ void DWARFDebugRanges::Dump(Stream &s,
}
}
bool DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset,
bool DWARFDebugRanges::FindRanges(dw_addr_t debug_ranges_base,
dw_offset_t debug_ranges_offset,
DWARFRangeList &range_list) const {
range_map_const_iterator pos = m_range_map.find(debug_ranges_offset);
dw_addr_t debug_ranges_address = debug_ranges_base + debug_ranges_offset;
range_map_const_iterator pos = m_range_map.find(debug_ranges_address);
if (pos != m_range_map.end()) {
range_list = pos->second;
return true;

View File

@ -23,7 +23,8 @@ public:
static void Dump(lldb_private::Stream &s,
const lldb_private::DWARFDataExtractor &debug_ranges_data,
lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
bool FindRanges(dw_offset_t debug_ranges_offset,
bool FindRanges(dw_addr_t debug_ranges_base,
dw_offset_t debug_ranges_offset,
DWARFRangeList &range_list) const;
protected:

View File

@ -3810,7 +3810,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
if (form_value.Form() == DW_FORM_sec_offset) {
DWARFRangeList dwarf_scope_ranges;
const DWARFDebugRanges *debug_ranges = DebugRanges();
debug_ranges->FindRanges(form_value.Unsigned(),
debug_ranges->FindRanges(die.GetCU()->GetRangesBase(),
form_value.Unsigned(),
dwarf_scope_ranges);
// All DW_AT_start_scope are relative to the base address of the