forked from OSchip/llvm-project
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:
parent
2cc4e3e04e
commit
2540a553e5
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "decls.h"
|
||||
|
||||
void
|
||||
struct2::f()
|
||||
{
|
||||
struct2::~struct2() {
|
||||
int x = g(); // Break2
|
||||
}
|
||||
|
||||
void struct2::f() {}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue