Skip to content

Commit 9af00c3

Browse files
committed
Add support for inline DWARF source files.
LLVM supports DWARF 5 linetable extension to store source files inline in DWARF. This is particularly useful for compiler-generated source code. This implementation tries to materialize them as temporary files lazily, so SBAPI clients don't need to be aware of them. As an implementation detail, this patch separate SupportFileList from FileSpecList and makes SupportFileList uncopyable.
1 parent 7df28fd commit 9af00c3

31 files changed

+335
-123
lines changed

lldb/include/lldb/Symbol/CompileUnit.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,13 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
112112
/// the compile unit is optimized will be made when
113113
/// CompileUnit::GetIsOptimized() is called.
114114
///
115+
/// \param[in] support_files
116+
/// An rvalue list of already parsed support files.
115117
/// \see lldb::LanguageType
116118
CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
117119
const FileSpec &file_spec, lldb::user_id_t uid,
118-
lldb::LanguageType language, lldb_private::LazyBool is_optimized);
120+
lldb::LanguageType language, lldb_private::LazyBool is_optimized,
121+
SupportFileList &&support_files = {});
119122

120123
/// Add a function to this compile unit.
121124
///
@@ -226,6 +229,9 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
226229
/// Return the primary source file associated with this compile unit.
227230
const FileSpec &GetPrimaryFile() const { return m_file_spec; }
228231

232+
/// Return the primary source file associated with this compile unit.
233+
void SetPrimaryFile(const FileSpec &fs) { m_file_spec = fs; }
234+
229235
/// Get the line table for the compile unit.
230236
///
231237
/// Called by clients and the SymbolFile plug-in. The SymbolFile plug-ins
@@ -265,7 +271,13 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
265271
///
266272
/// \return
267273
/// A support file list object.
268-
const FileSpecList &GetSupportFiles();
274+
const SupportFileList &GetSupportFiles();
275+
276+
/// Used by plugins that parse the support file list.
277+
SupportFileList &GetSupportFileList() {
278+
m_flags.Set(flagsParsedSupportFiles);
279+
return m_support_files;
280+
}
269281

270282
/// Get the compile unit's imported module list.
271283
///
@@ -331,8 +343,6 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
331343
/// A line table object pointer that this object now owns.
332344
void SetLineTable(LineTable *line_table);
333345

334-
void SetSupportFiles(FileSpecList support_files);
335-
336346
void SetDebugMacros(const DebugMacrosSP &debug_macros);
337347

338348
/// Set accessor for the variable list.
@@ -410,9 +420,8 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
410420
std::vector<SourceModule> m_imported_modules;
411421
/// The primary file associated with this compile unit.
412422
FileSpec m_file_spec;
413-
/// Files associated with this compile unit's line table and
414-
/// declarations.
415-
FileSpecList m_support_files;
423+
/// Files associated with this compile unit's line table and declarations.
424+
SupportFileList m_support_files;
416425
/// Line table that will get parsed on demand.
417426
std::unique_ptr<LineTable> m_line_table_up;
418427
/// Debug macros that will get parsed on demand.

lldb/include/lldb/Symbol/SymbolFile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class SymbolFile : public PluginInterface {
197197
return false;
198198
}
199199
virtual bool ParseSupportFiles(CompileUnit &comp_unit,
200-
FileSpecList &support_files) = 0;
200+
SupportFileList &support_files) = 0;
201201
virtual size_t ParseTypes(CompileUnit &comp_unit) = 0;
202202
virtual bool ParseIsOptimized(CompileUnit &comp_unit) { return false; }
203203

lldb/include/lldb/Symbol/SymbolFileOnDemand.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class SymbolFileOnDemand : public lldb_private::SymbolFile {
8181
llvm::function_ref<bool(lldb_private::Module &)>) override;
8282

8383
bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
84-
lldb_private::FileSpecList &support_files) override;
84+
lldb_private::SupportFileList &support_files) override;
8585

8686
bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override;
8787

lldb/include/lldb/Utility/FileSpecList.h

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,86 @@
1717
namespace lldb_private {
1818
class Stream;
1919

20+
/// Wraps either a FileSpec that represents a local file or a source
21+
/// file whose contents is known (for example because it can be
22+
/// reconstructed from debug info), but that hasn't been written to a
23+
/// file yet.
24+
class SupportFile {
25+
protected:
26+
FileSpec m_file_spec;
27+
28+
public:
29+
SupportFile(const FileSpec &spec) : m_file_spec(spec) {}
30+
SupportFile(const SupportFile &other) = delete;
31+
SupportFile(SupportFile &&other) = default;
32+
virtual ~SupportFile() = default;
33+
bool operator==(const SupportFile &other) {
34+
return m_file_spec == other.m_file_spec;
35+
}
36+
/// Return the file name only. Useful for resolving breakpoints by file name.
37+
const FileSpec &GetSpecOnly() const { return m_file_spec; };
38+
/// Materialize the file to disk and return the path to that temporary file.
39+
virtual const FileSpec &Materialize() { return m_file_spec; }
40+
};
41+
42+
/// A list of support files for a CompileUnit.
43+
class SupportFileList {
44+
public:
45+
SupportFileList(){};
46+
SupportFileList(const SupportFileList &) = delete;
47+
SupportFileList(SupportFileList &&other) = default;
48+
49+
typedef std::vector<std::unique_ptr<SupportFile>> collection;
50+
typedef collection::const_iterator const_iterator;
51+
const_iterator begin() const { return m_files.begin(); }
52+
const_iterator end() const { return m_files.end(); }
53+
54+
void Append(const FileSpec &file) {
55+
return Append(std::make_unique<SupportFile>(file));
56+
}
57+
void Append(std::unique_ptr<SupportFile> &&file) {
58+
m_files.push_back(std::move(file));
59+
}
60+
// FIXME: Only used by SymbolFilePDB. Replace with a DenseSet at call site.
61+
bool AppendIfUnique(const FileSpec &file);
62+
size_t GetSize() const { return m_files.size(); }
63+
const FileSpec &GetFileSpecAtIndex(size_t idx) const;
64+
size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const;
65+
/// Find a compatible file index.
66+
///
67+
/// Find the index of a compatible file in the file spec list that matches \a
68+
/// file starting \a idx entries into the file spec list. A file is considered
69+
/// compatible if:
70+
/// - The file matches exactly (only filename if \a file has no directory)
71+
/// - If \a file is relative and any file in the list has this same suffix
72+
/// - If any file in the list is relative and the relative path is a suffix
73+
/// of \a file
74+
///
75+
/// This is used to implement better matching for setting breakpoints in
76+
/// source files where an IDE might specify a full path when setting the
77+
/// breakpoint and debug info contains relative paths, if a user specifies
78+
/// a relative path when setting a breakpoint.
79+
///
80+
/// \param[in] idx
81+
/// An index into the file list.
82+
///
83+
/// \param[in] file
84+
/// The file specification to search for.
85+
///
86+
/// \return
87+
/// The index of the file that matches \a file if it is found,
88+
/// else UINT32_MAX is returned.
89+
size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const;
90+
91+
template <class... Args> void EmplaceBack(Args &&...args) {
92+
m_files.push_back(
93+
std::make_unique<SupportFile>(FileSpec(std::forward<Args>(args)...)));
94+
}
95+
96+
protected:
97+
collection m_files; ///< A collection of FileSpec objects.
98+
};
99+
20100
/// \class FileSpecList FileSpecList.h "lldb/Utility/FileSpecList.h"
21101
/// A file collection class.
22102
///
@@ -114,32 +194,6 @@ class FileSpecList {
114194
/// else UINT32_MAX is returned.
115195
size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const;
116196

117-
/// Find a compatible file index.
118-
///
119-
/// Find the index of a compatible file in the file spec list that matches \a
120-
/// file starting \a idx entries into the file spec list. A file is considered
121-
/// compatible if:
122-
/// - The file matches exactly (only filename if \a file has no directory)
123-
/// - If \a file is relative and any file in the list has this same suffix
124-
/// - If any file in the list is relative and the relative path is a suffix
125-
/// of \a file
126-
///
127-
/// This is used to implement better matching for setting breakpoints in
128-
/// source files where an IDE might specify a full path when setting the
129-
/// breakpoint and debug info contains relative paths, if a user specifies
130-
/// a relative path when setting a breakpoint.
131-
///
132-
/// \param[in] idx
133-
/// An index into the file list.
134-
///
135-
/// \param[in] file
136-
/// The file specification to search for.
137-
///
138-
/// \return
139-
/// The index of the file that matches \a file if it is found,
140-
/// else UINT32_MAX is returned.
141-
size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const;
142-
143197
/// Get file at index.
144198
///
145199
/// Gets a file from the file list. If \a idx is not a valid index, an empty

lldb/source/API/SBCompileUnit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ uint32_t SBCompileUnit::FindSupportFileIndex(uint32_t start_idx,
171171
LLDB_INSTRUMENT_VA(this, start_idx, sb_file, full);
172172

173173
if (m_opaque_ptr) {
174-
const FileSpecList &support_files = m_opaque_ptr->GetSupportFiles();
174+
const SupportFileList &support_files = m_opaque_ptr->GetSupportFiles();
175175
return support_files.FindFileIndex(start_idx, sb_file.ref(), full);
176176
}
177177
return 0;

lldb/source/Commands/CommandObjectSource.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed {
204204
if (cu) {
205205
assert(file_spec.GetFilename().AsCString());
206206
bool has_path = (file_spec.GetDirectory().AsCString() != nullptr);
207-
const FileSpecList &cu_file_list = cu->GetSupportFiles();
207+
const SupportFileList &cu_file_list = cu->GetSupportFiles();
208208
size_t file_idx = cu_file_list.FindFileIndex(0, file_spec, has_path);
209209
if (file_idx != UINT32_MAX) {
210210
// Update the file to how it appears in the CU.

lldb/source/Core/ModuleList.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ void ModuleListProperties::UpdateSymlinkMappings() {
164164
llvm::sys::ScopedWriter lock(m_symlink_paths_mutex);
165165
const bool notify = false;
166166
m_symlink_paths.Clear(notify);
167-
for (FileSpec symlink : list) {
167+
for (auto symlink : list) {
168168
FileSpec resolved;
169169
Status status = FileSystem::Instance().Readlink(symlink, resolved);
170170
if (status.Success())

lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -488,18 +488,18 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
488488

489489
// Build a list of files we need to analyze to build the configuration.
490490
FileSpecList files;
491-
for (const FileSpec &f : sc.comp_unit->GetSupportFiles())
492-
files.AppendIfUnique(f);
491+
for (auto &f : sc.comp_unit->GetSupportFiles())
492+
files.AppendIfUnique(f->Materialize());
493493
// We also need to look at external modules in the case of -gmodules as they
494494
// contain the support files for libc++ and the C library.
495495
llvm::DenseSet<SymbolFile *> visited_symbol_files;
496496
sc.comp_unit->ForEachExternalModule(
497497
visited_symbol_files, [&files](Module &module) {
498498
for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {
499-
const FileSpecList &support_files =
499+
const SupportFileList &support_files =
500500
module.GetCompileUnitAtIndex(i)->GetSupportFiles();
501-
for (const FileSpec &f : support_files) {
502-
files.AppendIfUnique(f);
501+
for (auto &f : support_files) {
502+
files.AppendIfUnique(f->Materialize());
503503
}
504504
}
505505
return false;
@@ -508,7 +508,7 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
508508
LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
509509
files.GetSize());
510510
if (log && log->GetVerbose()) {
511-
for (const FileSpec &f : files)
511+
for (auto &f : files)
512512
LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}",
513513
f.GetPath());
514514
}

lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ bool CppModuleConfiguration::hasValidConfig() {
134134
CppModuleConfiguration::CppModuleConfiguration(
135135
const FileSpecList &support_files, const llvm::Triple &triple) {
136136
// Analyze all files we were given to build the configuration.
137-
bool error = !llvm::all_of(support_files,
138-
std::bind(&CppModuleConfiguration::analyzeFile,
139-
this, std::placeholders::_1, triple));
137+
bool error = !llvm::all_of(support_files, [&](auto &file) {
138+
return CppModuleConfiguration::analyzeFile(file, triple);
139+
});
140140
// If we have a valid configuration at this point, set the
141141
// include directories and module list that should be used.
142142
if (!error && hasValidConfig()) {

lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,13 +278,14 @@ bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) {
278278
}
279279

280280
bool SymbolFileBreakpad::ParseSupportFiles(CompileUnit &comp_unit,
281-
FileSpecList &support_files) {
281+
SupportFileList &support_files) {
282282
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
283283
CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data;
284284
if (!data.support_files)
285285
ParseLineTableAndSupportFiles(comp_unit, data);
286286

287-
support_files = std::move(*data.support_files);
287+
for (auto &fs : *data.support_files)
288+
support_files.Append(fs);
288289
return true;
289290
}
290291

lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class SymbolFileBreakpad : public SymbolFileCommon {
7373
bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; }
7474

7575
bool ParseSupportFiles(CompileUnit &comp_unit,
76-
FileSpecList &support_files) override;
76+
SupportFileList &support_files) override;
7777
size_t ParseTypes(CompileUnit &cu) override { return 0; }
7878

7979
bool ParseImportedModules(
@@ -195,7 +195,6 @@ class SymbolFileBreakpad : public SymbolFileCommon {
195195
Bookmark bookmark;
196196
std::optional<FileSpecList> support_files;
197197
std::unique_ptr<LineTable> line_table_up;
198-
199198
};
200199

201200
uint32_t CalculateNumCompileUnits() override;

lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon {
6666
bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; }
6767

6868
bool ParseSupportFiles(CompileUnit &comp_unit,
69-
FileSpecList &support_files) override {
69+
SupportFileList &support_files) override {
7070
return false;
7171
}
7272

0 commit comments

Comments
 (0)