Skip to content

Commit f44bee7

Browse files
authored
[lldb] Fix the DWARF index cache when index is partial. (llvm#118390)
The ManualDWARFIndex class can create a index cache if the LLDB index cache is enabled. This used to save the index to the same file, regardless of wether the cache was a full index (no .debug_names) or a partial index (have .debug_names, but not all .o files were had .debug_names). So we could end up saving an index cache that was partial, and then later load that partial index as if it were a full index if the user set the 'settings set plugin.symbol-file.dwarf.ignore-file-indexes true'. This would cause us to ignore the .debug_names section, and if the index cache was enabled, we could end up loading the partial index as if it were a full DWARF index. This patch detects when the ManualDWARFIndex is being used with .debug_names, and saves out a cache file with a suffix of "-full" or "-partial" to avoid this issue.
1 parent ce416a0 commit f44bee7

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

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

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,16 +706,38 @@ bool ManualDWARFIndex::Encode(DataEncoder &encoder) const {
706706
return true;
707707
}
708708

709+
bool ManualDWARFIndex::IsPartial() const {
710+
// If we have units or type units to skip, then this index is partial.
711+
return !m_units_to_avoid.empty() || !m_type_sigs_to_avoid.empty();
712+
}
713+
709714
std::string ManualDWARFIndex::GetCacheKey() {
710715
std::string key;
711716
llvm::raw_string_ostream strm(key);
712717
// DWARF Index can come from different object files for the same module. A
713718
// module can have one object file as the main executable and might have
714719
// another object file in a separate symbol file, or we might have a .dwo file
715720
// that claims its module is the main executable.
721+
722+
// This class can be used to index all of the DWARF, or part of the DWARF
723+
// when there is a .debug_names index where some compile or type units were
724+
// built without .debug_names. So we need to know when we have a full manual
725+
// DWARF index or a partial manual DWARF index and save them to different
726+
// cache files. Before this fix we might end up debugging a binary with
727+
// .debug_names where some of the compile or type units weren't indexed, and
728+
// find an issue with the .debug_names tables (bugs or being incomplete), and
729+
// then we disable loading the .debug_names by setting a setting in LLDB by
730+
// running "settings set plugin.symbol-file.dwarf.ignore-file-indexes 0" in
731+
// another LLDB instance. The problem arose when there was an index cache from
732+
// a previous run where .debug_names was enabled and it had saved a cache file
733+
// that only covered the missing compile and type units from the .debug_names,
734+
// and with the setting that disables the loading of the cache files we would
735+
// load partial cache index cache. So we need to pick a unique cache suffix
736+
// name that indicates if the cache is partial or full to avoid this problem.
737+
llvm::StringRef dwarf_index_suffix(IsPartial() ? "partial-" : "full-");
716738
ObjectFile *objfile = m_dwarf->GetObjectFile();
717739
strm << objfile->GetModule()->GetCacheKey() << "-dwarf-index-"
718-
<< llvm::format_hex(objfile->GetCacheHash(), 10);
740+
<< dwarf_index_suffix << llvm::format_hex(objfile->GetCacheHash(), 10);
719741
return key;
720742
}
721743

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,16 @@ class ManualDWARFIndex : public DWARFIndex {
168168
const lldb::LanguageType cu_language,
169169
IndexSet &set);
170170

171+
/// Return true if this manual DWARF index is covering only part of the DWARF.
172+
///
173+
/// An instance of this class will be used to index all of the DWARF, but also
174+
/// when we have .debug_names we will use one to index any compile or type
175+
/// units that are not covered by the .debug_names table.
176+
///
177+
/// \return
178+
/// True if this index is a partial index, false otherwise.
179+
bool IsPartial() const;
180+
171181
/// The DWARF file which we are indexing.
172182
SymbolFileDWARF *m_dwarf;
173183
/// Which dwarf units should we skip while building the index.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// REQUIRES: lld
2+
3+
// Test if we build a mixed binary where one .o file has a .debug_names and
4+
// another doesn't have one, that we save a full or partial index cache.
5+
// Previous versions of LLDB would have ManualDWARFIndex.cpp that would save out
6+
// an index cache to the same file regardless of wether the index cache was a
7+
// full DWARF manual index, or just the CUs and TUs that were missing from any
8+
// .debug_names tables. If the user had a .debug_names table and debugged once
9+
// with index caching enabled, then debugged again but set the setting to ignore
10+
// .debug_names ('settings set plugin.symbol-file.dwarf.ignore-file-indexes 1')
11+
// this could cause LLDB to load the index cache from the previous run which
12+
// was incomplete and it only contained the manually indexed DWARF from the run
13+
// where we used .debug_names, but it would now load it as if it were the
14+
// complete DWARF index.
15+
16+
// Test that if we don't have .debug_names, that we save a full DWARF index.
17+
// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -DMAIN=1 -c %s -o %t.main.o
18+
// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -DMAIN=0 -c %s -o %t.foo.o
19+
// RUN: ld.lld %t.main.o %t.foo.o -o %t.nonames
20+
// RUN: llvm-dwp %t.main.dwo %t.foo.dwo -o %t.nonames.dwp
21+
// RUN: rm %t.main.dwo %t.foo.dwo
22+
// Run one time with the index cache enabled to populate the index cache. When
23+
// we populate the index cache we have to parse all of the DWARF debug info
24+
// and it is always available.
25+
// RUN: rm -rf %t.lldb-index-cache
26+
// RUN: %lldb \
27+
// RUN: -O 'settings set symbols.enable-lldb-index-cache true' \
28+
// RUN: -O 'settings set symbols.lldb-index-cache-path %t.lldb-index-cache' \
29+
// RUN: -O 'settings set target.preload-symbols true' \
30+
// RUN: %t.nonames -b
31+
32+
// Make sure there is a file with "dwarf-index-full" in its filename
33+
// RUN: ls %t.lldb-index-cache | FileCheck %s -check-prefix=FULL
34+
// FULL: {{dwp-index-cache.cpp.tmp.nonames.*-dwarf-index-full-}}
35+
36+
// Test that if we have one .o file with .debug_names and one without, that we
37+
// save a partial DWARF index.
38+
// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -DMAIN=1 -c %s -o %t.main.o -gpubnames
39+
// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -DMAIN=0 -c %s -o %t.foo.o
40+
// RUN: ld.lld %t.main.o %t.foo.o -o %t.somenames
41+
// RUN: llvm-dwp %t.main.dwo %t.foo.dwo -o %t.somenames.dwp
42+
// RUN: rm %t.main.dwo %t.foo.dwo
43+
// Run one time with the index cache enabled to populate the index cache. When
44+
// we populate the index cache we have to parse all of the DWARF debug info
45+
// and it is always available.
46+
// RUN: rm -rf %t.lldb-index-cache
47+
// RUN: %lldb \
48+
// RUN: -O 'settings set symbols.enable-lldb-index-cache true' \
49+
// RUN: -O 'settings set symbols.lldb-index-cache-path %t.lldb-index-cache' \
50+
// RUN: -O 'settings set target.preload-symbols true' \
51+
// RUN: %t.somenames -b
52+
53+
// Make sure there is a file with "dwarf-index-full" in its filename
54+
// RUN: ls %t.lldb-index-cache | FileCheck %s -check-prefix=PARTIAL
55+
// PARTIAL: {{dwp-index-cache.cpp.tmp.somenames.*-dwarf-index-partial-}}
56+
57+
#if MAIN
58+
extern int foo();
59+
int main() { return foo(); }
60+
#else
61+
int foo() { return 0; }
62+
#endif

0 commit comments

Comments
 (0)