Skip to content

Commit 8dfd6ca

Browse files
EricSLjankratochvil
authored andcommitted
[lldb] [DWARF-5] Be lazier about loading .dwo files
This change makes sure that DwarfUnit does not load a .dwo file until necessary. I also take advantage of DWARF 5's guarantee that the first support file is also the primary file to make it possible to create a compile unit without loading the .dwo file. Review By: jankratochvil, dblaikie Differential Revision: https://reviews.llvm.org/D100299
1 parent 7f97dda commit 8dfd6ca

File tree

10 files changed

+225
-97
lines changed

10 files changed

+225
-97
lines changed

lldb/include/lldb/Symbol/CompileUnit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
442442

443443
CompileUnit(const CompileUnit &) = delete;
444444
const CompileUnit &operator=(const CompileUnit &) = delete;
445+
const char *GetCachedLanguage() const;
445446
};
446447

447448
} // namespace lldb_private

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

Lines changed: 63 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
3535
DIERef::Section section, bool is_dwo)
3636
: UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs),
3737
m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo),
38-
m_dwo_id(header.GetDWOId()) {}
38+
m_has_parsed_non_skeleton_unit(false), m_dwo_id(header.GetDWOId()) {}
3939

4040
DWARFUnit::~DWARFUnit() = default;
4141

42-
// Parses first DIE of a compile unit.
43-
void DWARFUnit::ExtractUnitDIEIfNeeded() {
42+
// Parses first DIE of a compile unit, excluding DWO.
43+
void DWARFUnit::ExtractUnitDIENoDwoIfNeeded() {
4444
{
4545
llvm::sys::ScopedReader lock(m_first_die_mutex);
4646
if (m_first_die)
@@ -50,7 +50,8 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() {
5050
if (m_first_die)
5151
return; // Already parsed
5252

53-
LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", GetOffset());
53+
LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIENoDwoIfNeeded()",
54+
GetOffset());
5455

5556
// Set the offset to that of the first DIE and calculate the start of the
5657
// next compilation unit header.
@@ -66,6 +67,58 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() {
6667
}
6768
}
6869

70+
// Parses first DIE of a compile unit including DWO.
71+
void DWARFUnit::ExtractUnitDIEIfNeeded() {
72+
ExtractUnitDIENoDwoIfNeeded();
73+
74+
if (m_has_parsed_non_skeleton_unit)
75+
return;
76+
77+
m_has_parsed_non_skeleton_unit = true;
78+
79+
std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
80+
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, m_first_die);
81+
if (!dwo_symbol_file)
82+
return;
83+
84+
DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id);
85+
86+
if (!dwo_cu)
87+
return; // Can't fetch the compile unit from the dwo file.
88+
dwo_cu->SetUserData(this);
89+
90+
DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
91+
if (!dwo_cu_die.IsValid())
92+
return; // Can't fetch the compile unit DIE from the dwo file.
93+
94+
// Here for DWO CU we want to use the address base set in the skeleton unit
95+
// (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
96+
// otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
97+
// attributes which were applicable to the DWO units. The corresponding
98+
// DW_AT_* attributes standardized in DWARF v5 are also applicable to the
99+
// main unit in contrast.
100+
if (m_addr_base)
101+
dwo_cu->SetAddrBase(*m_addr_base);
102+
else if (m_gnu_addr_base)
103+
dwo_cu->SetAddrBase(*m_gnu_addr_base);
104+
105+
if (GetVersion() <= 4 && m_gnu_ranges_base)
106+
dwo_cu->SetRangesBase(*m_gnu_ranges_base);
107+
else if (dwo_symbol_file->GetDWARFContext()
108+
.getOrLoadRngListsData()
109+
.GetByteSize() > 0)
110+
dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
111+
112+
if (GetVersion() >= 5 &&
113+
dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() >
114+
0)
115+
dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
116+
117+
dwo_cu->SetBaseAddress(GetBaseAddress());
118+
119+
m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
120+
}
121+
69122
// Parses a compile unit and indexes its DIEs if it hasn't already been done.
70123
// It will leave this compile unit extracted forever.
71124
void DWARFUnit::ExtractDIEsIfNeeded() {
@@ -291,14 +344,12 @@ void DWARFUnit::SetDwoStrOffsetsBase() {
291344
}
292345

293346
uint64_t DWARFUnit::GetDWOId() {
294-
ExtractUnitDIEIfNeeded();
347+
ExtractUnitDIENoDwoIfNeeded();
295348
return m_dwo_id;
296349
}
297350

298351
// m_die_array_mutex must be already held as read/write.
299352
void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
300-
llvm::Optional<uint64_t> addr_base, gnu_addr_base, gnu_ranges_base;
301-
302353
DWARFAttributes attributes;
303354
size_t num_attributes = cu_die.GetAttributes(this, attributes);
304355

@@ -308,8 +359,7 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
308359
continue;
309360
DWARFFormValue form_value;
310361
if (attributes.ExtractFormValueAtIndex(i, form_value)) {
311-
addr_base = form_value.Unsigned();
312-
SetAddrBase(*addr_base);
362+
SetAddrBase(form_value.Unsigned());
313363
break;
314364
}
315365
}
@@ -341,10 +391,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
341391
m_line_table_offset = form_value.Unsigned();
342392
break;
343393
case DW_AT_GNU_addr_base:
344-
gnu_addr_base = form_value.Unsigned();
394+
m_gnu_addr_base = form_value.Unsigned();
345395
break;
346396
case DW_AT_GNU_ranges_base:
347-
gnu_ranges_base = form_value.Unsigned();
397+
m_gnu_ranges_base = form_value.Unsigned();
348398
break;
349399
case DW_AT_GNU_dwo_id:
350400
m_dwo_id = form_value.Unsigned();
@@ -353,50 +403,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
353403
}
354404

355405
if (m_is_dwo) {
406+
m_has_parsed_non_skeleton_unit = true;
356407
SetDwoStrOffsetsBase();
357408
return;
358409
}
359-
360-
std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
361-
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
362-
if (!dwo_symbol_file)
363-
return;
364-
365-
DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id);
366-
367-
if (!dwo_cu)
368-
return; // Can't fetch the compile unit from the dwo file.
369-
dwo_cu->SetUserData(this);
370-
371-
DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
372-
if (!dwo_cu_die.IsValid())
373-
return; // Can't fetch the compile unit DIE from the dwo file.
374-
375-
// Here for DWO CU we want to use the address base set in the skeleton unit
376-
// (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
377-
// otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
378-
// attributes which were applicable to the DWO units. The corresponding
379-
// DW_AT_* attributes standardized in DWARF v5 are also applicable to the main
380-
// unit in contrast.
381-
if (addr_base)
382-
dwo_cu->SetAddrBase(*addr_base);
383-
else if (gnu_addr_base)
384-
dwo_cu->SetAddrBase(*gnu_addr_base);
385-
386-
if (GetVersion() <= 4 && gnu_ranges_base)
387-
dwo_cu->SetRangesBase(*gnu_ranges_base);
388-
else if (dwo_symbol_file->GetDWARFContext()
389-
.getOrLoadRngListsData()
390-
.GetByteSize() > 0)
391-
dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
392-
393-
if (GetVersion() >= 5 &&
394-
dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() >
395-
0)
396-
dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
397-
dwo_cu->SetBaseAddress(GetBaseAddress());
398-
399-
m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
400410
}
401411

402412
size_t DWARFUnit::GetDebugInfoSize() const {
@@ -412,7 +422,7 @@ dw_offset_t DWARFUnit::GetAbbrevOffset() const {
412422
}
413423

414424
dw_offset_t DWARFUnit::GetLineTableOffset() {
415-
ExtractUnitDIEIfNeeded();
425+
ExtractUnitDIENoDwoIfNeeded();
416426
return m_line_table_offset;
417427
}
418428

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ class DWARFUnit : public lldb_private::UserID {
9292
uint64_t GetDWOId();
9393

9494
void ExtractUnitDIEIfNeeded();
95+
void ExtractUnitDIENoDwoIfNeeded();
9596
void ExtractDIEsIfNeeded();
9697

9798
class ScopedExtractDIEs {
@@ -151,7 +152,7 @@ class DWARFUnit : public lldb_private::UserID {
151152
const DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
152153
dw_offset_t GetAbbrevOffset() const;
153154
uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); }
154-
dw_addr_t GetAddrBase() const { return m_addr_base; }
155+
dw_addr_t GetAddrBase() const { return m_addr_base ? *m_addr_base : 0; }
155156
dw_addr_t GetBaseAddress() const { return m_base_addr; }
156157
dw_offset_t GetLineTableOffset();
157158
dw_addr_t GetRangesBase() const { return m_ranges_base; }
@@ -268,7 +269,7 @@ class DWARFUnit : public lldb_private::UserID {
268269
// Get the DWARF unit DWARF debug information entry. Parse the single DIE
269270
// if needed.
270271
const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
271-
ExtractUnitDIEIfNeeded();
272+
ExtractUnitDIENoDwoIfNeeded();
272273
// m_first_die_mutex is not required as m_first_die is never cleared.
273274
if (!m_first_die)
274275
return NULL;
@@ -315,9 +316,11 @@ class DWARFUnit : public lldb_private::UserID {
315316
lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
316317
llvm::Optional<lldb_private::FileSpec> m_comp_dir;
317318
llvm::Optional<lldb_private::FileSpec> m_file_spec;
318-
dw_addr_t m_addr_base = 0; ///< Value of DW_AT_addr_base.
319-
dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
320-
dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base.
319+
llvm::Optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base.
320+
dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
321+
dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base.
322+
llvm::Optional<uint64_t> m_gnu_addr_base;
323+
llvm::Optional<uint64_t> m_gnu_ranges_base;
321324

322325
/// Value of DW_AT_stmt_list.
323326
dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
@@ -330,6 +333,7 @@ class DWARFUnit : public lldb_private::UserID {
330333

331334
const DIERef::Section m_section;
332335
bool m_is_dwo;
336+
bool m_has_parsed_non_skeleton_unit;
333337
/// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5).
334338
uint64_t m_dwo_id;
335339

0 commit comments

Comments
 (0)