Skip to content

Commit 3243964

Browse files
committed
DWARF: Don't compute address ranges for type units
Summary: Type units don't describe any code, so they should never be the result of any address lookup queries. Previously, we would compute the address ranges for the type units for via the line tables they reference because the type units looked a lot like line-tables-only compile units. However, this is not correct, as the line tables are only referenced from type units so that other declarations can use the file names contained in them. In this patch I make the BuildAddressRangeTable function virtual, and implement it only for compile units. Testing this was a bit tricky, because the behavior depends on the order in which we add things to the address range map. This rarely caused a problem with DWARF v4 type units, as they are always added after all CUs. It happened more frequently with DWARF v5, as there clang emits the type units first. However, this is still not something that it is required to do, so for testing I've created an assembly file where I've deliberately sandwiched a compile unit between two type units, which should isolate us from both changes in how the compiler emits the units and changes in the order we process them. Reviewers: clayborg, aprantl, JDevlieghere Subscribers: jdoerfert, lldb-commits Differential Revision: https://reviews.llvm.org/D62178 llvm-svn: 361465
1 parent eee5d42 commit 3243964

File tree

8 files changed

+456
-116
lines changed

8 files changed

+456
-116
lines changed

lldb/lit/SymbolFile/DWARF/debug-types-address-ranges.s

Lines changed: 338 additions & 0 deletions
Large diffs are not rendered by default.

lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "DWARFCompileUnit.h"
10+
#include "DWARFDebugAranges.h"
11+
#include "SymbolFileDWARFDebugMap.h"
1012

13+
#include "lldb/Symbol/CompileUnit.h"
14+
#include "lldb/Symbol/LineTable.h"
1115
#include "lldb/Utility/Stream.h"
1216

1317
using namespace lldb;
@@ -20,3 +24,92 @@ void DWARFCompileUnit::Dump(Stream *s) const {
2024
GetOffset(), GetLength(), GetVersion(), GetAbbrevOffset(),
2125
GetAddressByteSize(), GetNextUnitOffset());
2226
}
27+
28+
void DWARFCompileUnit::BuildAddressRangeTable(
29+
DWARFDebugAranges *debug_aranges) {
30+
// This function is usually called if there in no .debug_aranges section in
31+
// order to produce a compile unit level set of address ranges that is
32+
// accurate.
33+
34+
size_t num_debug_aranges = debug_aranges->GetNumRanges();
35+
36+
// First get the compile unit DIE only and check if it has a DW_AT_ranges
37+
const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
38+
39+
const dw_offset_t cu_offset = GetOffset();
40+
if (die) {
41+
DWARFRangeList ranges;
42+
const size_t num_ranges =
43+
die->GetAttributeAddressRanges(this, ranges, false);
44+
if (num_ranges > 0) {
45+
// This compile unit has DW_AT_ranges, assume this is correct if it is
46+
// present since clang no longer makes .debug_aranges by default and it
47+
// emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with
48+
// recent GCC builds.
49+
for (size_t i = 0; i < num_ranges; ++i) {
50+
const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
51+
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
52+
range.GetRangeEnd());
53+
}
54+
55+
return; // We got all of our ranges from the DW_AT_ranges attribute
56+
}
57+
}
58+
// We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
59+
60+
// If the DIEs weren't parsed, then we don't want all dies for all compile
61+
// units to stay loaded when they weren't needed. So we can end up parsing
62+
// the DWARF and then throwing them all away to keep memory usage down.
63+
ScopedExtractDIEs clear_dies(ExtractDIEsScoped());
64+
65+
die = DIEPtr();
66+
if (die)
67+
die->BuildAddressRangeTable(this, debug_aranges);
68+
69+
if (debug_aranges->GetNumRanges() == num_debug_aranges) {
70+
// We got nothing from the functions, maybe we have a line tables only
71+
// situation. Check the line tables and build the arange table from this.
72+
SymbolContext sc;
73+
sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this);
74+
if (sc.comp_unit) {
75+
SymbolFileDWARFDebugMap *debug_map_sym_file =
76+
m_dwarf->GetDebugMapSymfile();
77+
if (debug_map_sym_file == nullptr) {
78+
if (LineTable *line_table = sc.comp_unit->GetLineTable()) {
79+
LineTable::FileAddressRanges file_ranges;
80+
const bool append = true;
81+
const size_t num_ranges =
82+
line_table->GetContiguousFileAddressRanges(file_ranges, append);
83+
for (uint32_t idx = 0; idx < num_ranges; ++idx) {
84+
const LineTable::FileAddressRanges::Entry &range =
85+
file_ranges.GetEntryRef(idx);
86+
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
87+
range.GetRangeEnd());
88+
}
89+
}
90+
} else
91+
debug_map_sym_file->AddOSOARanges(m_dwarf, debug_aranges);
92+
}
93+
}
94+
95+
if (debug_aranges->GetNumRanges() == num_debug_aranges) {
96+
// We got nothing from the functions, maybe we have a line tables only
97+
// situation. Check the line tables and build the arange table from this.
98+
SymbolContext sc;
99+
sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this);
100+
if (sc.comp_unit) {
101+
if (LineTable *line_table = sc.comp_unit->GetLineTable()) {
102+
LineTable::FileAddressRanges file_ranges;
103+
const bool append = true;
104+
const size_t num_ranges =
105+
line_table->GetContiguousFileAddressRanges(file_ranges, append);
106+
for (uint32_t idx = 0; idx < num_ranges; ++idx) {
107+
const LineTable::FileAddressRanges::Entry &range =
108+
file_ranges.GetEntryRef(idx);
109+
debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(),
110+
range.GetRangeEnd());
111+
}
112+
}
113+
}
114+
}
115+
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
class DWARFCompileUnit : public DWARFUnit {
1616
public:
17+
void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override;
18+
1719
void Dump(lldb_private::Stream *s) const override;
1820

1921
private:

lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
class DWARFTypeUnit : public DWARFUnit {
1616
public:
17+
void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) override {}
18+
1719
void Dump(lldb_private::Stream *s) const override;
1820

1921
private:

lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
#include "lldb/Core/Module.h"
1212
#include "lldb/Host/StringConvert.h"
13-
#include "lldb/Symbol/CompileUnit.h"
14-
#include "lldb/Symbol/LineTable.h"
1513
#include "lldb/Symbol/ObjectFile.h"
1614
#include "lldb/Utility/LLDBAssert.h"
1715
#include "lldb/Utility/StreamString.h"
@@ -23,7 +21,6 @@
2321
#include "DWARFDebugInfo.h"
2422
#include "DWARFTypeUnit.h"
2523
#include "LogChannelDWARF.h"
26-
#include "SymbolFileDWARFDebugMap.h"
2724
#include "SymbolFileDWARFDwo.h"
2825

2926
using namespace lldb;
@@ -407,98 +404,6 @@ void DWARFUnit::ClearDIEsRWLocked() {
407404
m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked();
408405
}
409406

410-
void DWARFUnit::BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) {
411-
// This function is usually called if there in no .debug_aranges section in
412-
// order to produce a compile unit level set of address ranges that is
413-
// accurate.
414-
415-
size_t num_debug_aranges = debug_aranges->GetNumRanges();
416-
417-
// First get the compile unit DIE only and check if it has a DW_AT_ranges
418-
const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
419-
420-
const dw_offset_t cu_offset = GetOffset();
421-
if (die) {
422-
DWARFRangeList ranges;
423-
const size_t num_ranges =
424-
die->GetAttributeAddressRanges(this, ranges, false);
425-
if (num_ranges > 0) {
426-
// This compile unit has DW_AT_ranges, assume this is correct if it is
427-
// present since clang no longer makes .debug_aranges by default and it
428-
// emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with
429-
// recent GCC builds.
430-
for (size_t i = 0; i < num_ranges; ++i) {
431-
const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
432-
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
433-
range.GetRangeEnd());
434-
}
435-
436-
return; // We got all of our ranges from the DW_AT_ranges attribute
437-
}
438-
}
439-
// We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
440-
441-
// If the DIEs weren't parsed, then we don't want all dies for all compile
442-
// units to stay loaded when they weren't needed. So we can end up parsing
443-
// the DWARF and then throwing them all away to keep memory usage down.
444-
ScopedExtractDIEs clear_dies(ExtractDIEsScoped());
445-
446-
die = DIEPtr();
447-
if (die)
448-
die->BuildAddressRangeTable(this, debug_aranges);
449-
450-
if (debug_aranges->GetNumRanges() == num_debug_aranges) {
451-
// We got nothing from the functions, maybe we have a line tables only
452-
// situation. Check the line tables and build the arange table from this.
453-
SymbolContext sc;
454-
sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this);
455-
if (sc.comp_unit) {
456-
SymbolFileDWARFDebugMap *debug_map_sym_file =
457-
m_dwarf->GetDebugMapSymfile();
458-
if (debug_map_sym_file == NULL) {
459-
LineTable *line_table = sc.comp_unit->GetLineTable();
460-
461-
if (line_table) {
462-
LineTable::FileAddressRanges file_ranges;
463-
const bool append = true;
464-
const size_t num_ranges =
465-
line_table->GetContiguousFileAddressRanges(file_ranges, append);
466-
for (uint32_t idx = 0; idx < num_ranges; ++idx) {
467-
const LineTable::FileAddressRanges::Entry &range =
468-
file_ranges.GetEntryRef(idx);
469-
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
470-
range.GetRangeEnd());
471-
}
472-
}
473-
} else
474-
debug_map_sym_file->AddOSOARanges(m_dwarf, debug_aranges);
475-
}
476-
}
477-
478-
if (debug_aranges->GetNumRanges() == num_debug_aranges) {
479-
// We got nothing from the functions, maybe we have a line tables only
480-
// situation. Check the line tables and build the arange table from this.
481-
SymbolContext sc;
482-
sc.comp_unit = m_dwarf->GetCompUnitForDWARFCompUnit(this);
483-
if (sc.comp_unit) {
484-
LineTable *line_table = sc.comp_unit->GetLineTable();
485-
486-
if (line_table) {
487-
LineTable::FileAddressRanges file_ranges;
488-
const bool append = true;
489-
const size_t num_ranges =
490-
line_table->GetContiguousFileAddressRanges(file_ranges, append);
491-
for (uint32_t idx = 0; idx < num_ranges; ++idx) {
492-
const LineTable::FileAddressRanges::Entry &range =
493-
file_ranges.GetEntryRef(idx);
494-
debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(),
495-
range.GetRangeEnd());
496-
}
497-
}
498-
}
499-
}
500-
}
501-
502407
lldb::ByteOrder DWARFUnit::GetByteOrder() const {
503408
return m_dwarf->GetObjectFile()->GetByteOrder();
504409
}

lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class DWARFUnit : public lldb_private::UserID {
143143
void SetRangesBase(dw_addr_t ranges_base);
144144
void SetBaseObjOffset(dw_offset_t base_obj_offset);
145145
void SetStrOffsetsBase(dw_offset_t str_offsets_base);
146-
void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges);
146+
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;
147147

148148
lldb::ByteOrder GetByteOrder() const;
149149

@@ -215,6 +215,24 @@ class DWARFUnit : public lldb_private::UserID {
215215
const lldb_private::DWARFDataExtractor &data,
216216
lldb::offset_t *offset_ptr);
217217

218+
// Get the DWARF unit DWARF debug information entry. Parse the single DIE
219+
// if needed.
220+
const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
221+
ExtractUnitDIEIfNeeded();
222+
// m_first_die_mutex is not required as m_first_die is never cleared.
223+
if (!m_first_die)
224+
return NULL;
225+
return &m_first_die;
226+
}
227+
228+
// Get all DWARF debug informration entries. Parse all DIEs if needed.
229+
const DWARFDebugInfoEntry *DIEPtr() {
230+
ExtractDIEsIfNeeded();
231+
if (m_die_array.empty())
232+
return NULL;
233+
return &m_die_array[0];
234+
}
235+
218236
SymbolFileDWARF *m_dwarf = nullptr;
219237
std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
220238
DWARFUnitHeader m_header;
@@ -257,24 +275,6 @@ class DWARFUnit : public lldb_private::UserID {
257275
void ExtractDIEsRWLocked();
258276
void ClearDIEsRWLocked();
259277

260-
// Get the DWARF unit DWARF debug informration entry. Parse the single DIE
261-
// if needed.
262-
const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
263-
ExtractUnitDIEIfNeeded();
264-
// m_first_die_mutex is not required as m_first_die is never cleared.
265-
if (!m_first_die)
266-
return NULL;
267-
return &m_first_die;
268-
}
269-
270-
// Get all DWARF debug informration entries. Parse all DIEs if needed.
271-
const DWARFDebugInfoEntry *DIEPtr() {
272-
ExtractDIEsIfNeeded();
273-
if (m_die_array.empty())
274-
return NULL;
275-
return &m_die_array[0];
276-
}
277-
278278
void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
279279

280280
void ComputeCompDirAndGuessPathStyle();

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class SymbolFileDWARF : public lldb_private::SymbolFile,
6262
friend class SymbolFileDWARFDwo;
6363
friend class DebugMapModule;
6464
friend struct DIERef;
65-
friend class DWARFUnit;
65+
friend class DWARFCompileUnit;
6666
friend class DWARFDIE;
6767
friend class DWARFASTParserClang;
6868

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile {
135135
friend class DebugMapModule;
136136
friend struct DIERef;
137137
friend class DWARFASTParserClang;
138-
friend class DWARFUnit;
138+
friend class DWARFCompileUnit;
139139
friend class SymbolFileDWARF;
140140
struct OSOInfo {
141141
lldb::ModuleSP module_sp;

0 commit comments

Comments
 (0)