https://github.com/adrian-prantl updated https://github.com/llvm/llvm-project/pull/75880
>From e089e1d67c01a42da16b7544abf8c4935cde4aed Mon Sep 17 00:00:00 2001 From: Adrian Prantl <apra...@apple.com> Date: Mon, 18 Dec 2023 15:59:00 -0800 Subject: [PATCH 1/2] 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. --- lldb/include/lldb/Utility/FileSpecList.h | 45 +++++++++++++++--- lldb/source/Core/ModuleList.cpp | 8 ++-- .../Clang/ClangUserExpression.cpp | 12 ++--- .../Clang/CppModuleConfiguration.cpp | 6 +-- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 47 +++++++++++++++++++ lldb/source/Utility/FileSpecList.cpp | 21 +++++---- .../inline-sourcefile/Makefile | 11 +++++ .../TestInlineSourceFiles.py | 17 +++++++ .../inline-sourcefile/inline.ll | 39 +++++++++++++++ .../functionalities/inline-sourcefile/main.c | 7 +++ 10 files changed, 186 insertions(+), 27 deletions(-) create mode 100644 lldb/test/API/functionalities/inline-sourcefile/Makefile create mode 100644 lldb/test/API/functionalities/inline-sourcefile/TestInlineSourceFiles.py create mode 100644 lldb/test/API/functionalities/inline-sourcefile/inline.ll create mode 100644 lldb/test/API/functionalities/inline-sourcefile/main.c diff --git a/lldb/include/lldb/Utility/FileSpecList.h b/lldb/include/lldb/Utility/FileSpecList.h index 77587aa917916b..8eda721b607fd6 100644 --- a/lldb/include/lldb/Utility/FileSpecList.h +++ b/lldb/include/lldb/Utility/FileSpecList.h @@ -17,13 +17,41 @@ namespace lldb_private { class Stream; +/// Represents a source file whose contents is known (for example +/// because it can be reconstructed from debug info), but that +/// hasn't been written to a local disk yet. +struct LazyFileSpec { + virtual ~LazyFileSpec() {} + virtual const FileSpec &Materialize() = 0; +}; + +/// Wraps either a FileSpec that represents a local file or a +/// LazyFileSpec that could be materialized into a local file. +class FileSpecHolder { + FileSpec m_file_spec; + std::shared_ptr<LazyFileSpec> m_lazy; + +public: + FileSpecHolder(const FileSpec &spec, std::shared_ptr<LazyFileSpec> lazy = {}) + : m_file_spec(spec), m_lazy(lazy) {} + FileSpecHolder(const FileSpecHolder &other) = default; + FileSpecHolder(FileSpecHolder &&other) = default; + FileSpecHolder &operator=(const FileSpecHolder &other) = default; + const FileSpec &GetSpecOnly() const { return m_file_spec; }; + const FileSpec &Materialize() const { + if (m_lazy) + return m_lazy->Materialize(); + return m_file_spec; + } +}; + /// \class FileSpecList FileSpecList.h "lldb/Utility/FileSpecList.h" /// A file collection class. /// /// A class that contains a mutable list of FileSpec objects. class FileSpecList { public: - typedef std::vector<FileSpec> collection; + typedef std::vector<FileSpecHolder> collection; typedef collection::const_iterator const_iterator; /// Default constructor. @@ -38,7 +66,10 @@ class FileSpecList { FileSpecList(FileSpecList &&rhs) = default; /// Initialize this object from a vector of FileSpecs - FileSpecList(std::vector<FileSpec> &&rhs) : m_files(std::move(rhs)) {} + FileSpecList(std::vector<FileSpec> &&rhs) { + for (auto &fs : rhs) + m_files.emplace_back(fs); + } /// Destructor. ~FileSpecList(); @@ -83,9 +114,11 @@ class FileSpecList { /// \param[in] args /// Arguments to create the FileSpec template <class... Args> void EmplaceBack(Args &&...args) { - m_files.emplace_back(std::forward<Args>(args)...); + m_files.emplace_back(FileSpec(std::forward<Args>(args)...)); } + void Append(FileSpecHolder &&fsh) { m_files.push_back(std::move(fsh)); } + /// Clears the file list. void Clear(); @@ -175,10 +208,10 @@ class FileSpecList { bool Insert(size_t idx, const FileSpec &file) { if (idx < m_files.size()) { - m_files.insert(m_files.begin() + idx, file); + m_files.insert(m_files.begin() + idx, FileSpecHolder(file)); return true; } else if (idx == m_files.size()) { - m_files.push_back(file); + m_files.push_back(FileSpecHolder(file)); return true; } return false; @@ -186,7 +219,7 @@ class FileSpecList { bool Replace(size_t idx, const FileSpec &file) { if (idx < m_files.size()) { - m_files[idx] = file; + m_files[idx] = FileSpecHolder(file); return true; } return false; diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index aa89c93c8d0521..3b6c3ea899caf7 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -164,11 +164,13 @@ void ModuleListProperties::UpdateSymlinkMappings() { llvm::sys::ScopedWriter lock(m_symlink_paths_mutex); const bool notify = false; m_symlink_paths.Clear(notify); - for (FileSpec symlink : list) { + for (auto symlink : list) { FileSpec resolved; - Status status = FileSystem::Instance().Readlink(symlink, resolved); + Status status = + FileSystem::Instance().Readlink(symlink.Materialize(), resolved); if (status.Success()) - m_symlink_paths.Append(symlink.GetPath(), resolved.GetPath(), notify); + m_symlink_paths.Append(symlink.Materialize().GetPath(), + resolved.GetPath(), notify); } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 68bdd96e8adb03..ec03a38752c2fe 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -488,8 +488,8 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, // Build a list of files we need to analyze to build the configuration. FileSpecList files; - for (const FileSpec &f : sc.comp_unit->GetSupportFiles()) - files.AppendIfUnique(f); + for (auto &f : sc.comp_unit->GetSupportFiles()) + files.AppendIfUnique(f.Materialize()); // We also need to look at external modules in the case of -gmodules as they // contain the support files for libc++ and the C library. llvm::DenseSet<SymbolFile *> visited_symbol_files; @@ -498,8 +498,8 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) { const FileSpecList &support_files = module.GetCompileUnitAtIndex(i)->GetSupportFiles(); - for (const FileSpec &f : support_files) { - files.AppendIfUnique(f); + for (auto &f : support_files) { + files.AppendIfUnique(f.Materialize()); } } return false; @@ -508,9 +508,9 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze", files.GetSize()); if (log && log->GetVerbose()) { - for (const FileSpec &f : files) + for (auto &f : files) LLDB_LOGV(log, "[C++ module config] Analyzing support file: {0}", - f.GetPath()); + f.Materialize().GetPath()); } // Try to create a configuration from the files. If there is no valid diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp index 62443d1290dc72..0cd52db97521a1 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -134,9 +134,9 @@ bool CppModuleConfiguration::hasValidConfig() { CppModuleConfiguration::CppModuleConfiguration( const FileSpecList &support_files, const llvm::Triple &triple) { // Analyze all files we were given to build the configuration. - bool error = !llvm::all_of(support_files, - std::bind(&CppModuleConfiguration::analyzeFile, - this, std::placeholders::_1, triple)); + bool error = !llvm::all_of(support_files, [&](auto &file) { + return CppModuleConfiguration::analyzeFile(file.Materialize(), triple); + }); // If we have a valid configuration at this point, set the // include directories and module list that should be used. if (!error && hasValidConfig()) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 505ea29ca4d4f5..52caa5885baac2 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/FileUtilities.h" #include "llvm/Support/Format.h" #include "llvm/Support/Threading.h" @@ -235,6 +236,52 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, for (size_t idx = first_file_idx; idx <= last_file_idx; ++idx) { std::string remapped_file; if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) { + auto entry = prologue.getFileNameEntry(idx); + auto source = entry.Source.getAsCString(); + if (!source) + consumeError(source.takeError()); + else { + llvm::StringRef source_ref(*source); + if (!source_ref.empty()) { + /// Wrap a path for an in-DWARF source file. Lazily write it + /// to disk when Materialize() is called. + struct LazyDWARFFile : public LazyFileSpec { + LazyDWARFFile(std::string file_name, llvm::StringRef source, + FileSpec::Style style) + : file_name(file_name), source(source), style(style) {} + std::string file_name; + FileSpec tmp_file; + llvm::StringRef source; + std::unique_ptr<llvm::FileRemover> remover; + FileSpec::Style style; + + /// Write the file contents to a temporary file. + const FileSpec &Materialize() override { + if (tmp_file) + return tmp_file; + llvm::SmallString<0> name; + int fd; + auto ec = llvm::sys::fs::createTemporaryFile( + "", llvm::sys::path::filename(file_name, style), fd, name); + if (ec || fd <= 0) { + LLDB_LOG(GetLog(DWARFLog::DebugInfo), + "Could not create temporary file"); + return tmp_file; + } + remover = std::make_unique<llvm::FileRemover>(name); + NativeFile file(fd, File::eOpenOptionWriteOnly, true); + size_t num_bytes = source.size(); + file.Write(source.data(), num_bytes); + tmp_file.SetPath(name); + return tmp_file; + } + }; + support_files.Append(FileSpecHolder( + FileSpec(*file_path), + std::make_shared<LazyDWARFFile>(*file_path, *source, style))); + continue; + } + } if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path))) remapped_file = *remapped; else diff --git a/lldb/source/Utility/FileSpecList.cpp b/lldb/source/Utility/FileSpecList.cpp index e3d8ea650c75dc..c2ebbfd5ec854f 100644 --- a/lldb/source/Utility/FileSpecList.cpp +++ b/lldb/source/Utility/FileSpecList.cpp @@ -30,7 +30,9 @@ void FileSpecList::Append(const FileSpec &file_spec) { // a copy of "file_spec". bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) { collection::iterator end = m_files.end(); - if (find(m_files.begin(), end, file_spec) == end) { + if (find_if(m_files.begin(), end, [&](auto &holder) { + return holder.GetSpecOnly() == file_spec; + }) == end) { m_files.push_back(file_spec); return true; } @@ -44,7 +46,7 @@ void FileSpecList::Clear() { m_files.clear(); } void FileSpecList::Dump(Stream *s, const char *separator_cstr) const { collection::const_iterator pos, end = m_files.end(); for (pos = m_files.begin(); pos != end; ++pos) { - pos->Dump(s->AsRawOstream()); + pos->GetSpecOnly().Dump(s->AsRawOstream()); if (separator_cstr && ((pos + 1) != end)) s->PutCString(separator_cstr); } @@ -64,13 +66,14 @@ size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec, bool compare_filename_only = file_spec.GetDirectory().IsEmpty(); for (size_t idx = start_idx; idx < num_files; ++idx) { + auto f = m_files[idx].GetSpecOnly(); if (compare_filename_only) { - if (ConstString::Equals( - m_files[idx].GetFilename(), file_spec.GetFilename(), - file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive())) + if (ConstString::Equals(f.GetFilename(), file_spec.GetFilename(), + file_spec.IsCaseSensitive() || + f.IsCaseSensitive())) return idx; } else { - if (FileSpec::Equal(m_files[idx], file_spec, full)) + if (FileSpec::Equal(f, file_spec, full)) return idx; } } @@ -92,7 +95,7 @@ size_t FileSpecList::FindCompatibleIndex(size_t start_idx, const bool full = !file_spec.GetDirectory().IsEmpty(); for (size_t idx = start_idx; idx < num_files; ++idx) { - const FileSpec &curr_file = m_files[idx]; + const FileSpec &curr_file = m_files[idx].GetSpecOnly(); // Always start by matching the filename first if (!curr_file.FileEquals(file_spec)) @@ -135,7 +138,7 @@ size_t FileSpecList::FindCompatibleIndex(size_t start_idx, // an empty FileSpec object will be returned. const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const { if (idx < m_files.size()) - return m_files[idx]; + return m_files[idx].Materialize(); static FileSpec g_empty_file_spec; return g_empty_file_spec; } @@ -148,7 +151,7 @@ size_t FileSpecList::MemorySize() const { size_t mem_size = sizeof(FileSpecList); collection::const_iterator pos, end = m_files.end(); for (pos = m_files.begin(); pos != end; ++pos) { - mem_size += pos->MemorySize(); + mem_size += pos->GetSpecOnly().MemorySize(); } return mem_size; diff --git a/lldb/test/API/functionalities/inline-sourcefile/Makefile b/lldb/test/API/functionalities/inline-sourcefile/Makefile new file mode 100644 index 00000000000000..adb29d3a88e26c --- /dev/null +++ b/lldb/test/API/functionalities/inline-sourcefile/Makefile @@ -0,0 +1,11 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -gdwarf-5 + +include Makefile.rules + +OBJECTS += inline.o + +$(EXE): main.c inline.o + +%.o: %.ll + $(CC) $< -c -o $@ diff --git a/lldb/test/API/functionalities/inline-sourcefile/TestInlineSourceFiles.py b/lldb/test/API/functionalities/inline-sourcefile/TestInlineSourceFiles.py new file mode 100644 index 00000000000000..6daf970b895b0f --- /dev/null +++ b/lldb/test/API/functionalities/inline-sourcefile/TestInlineSourceFiles.py @@ -0,0 +1,17 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil + + +class InlineSourceFilesTestCase(TestBase): + @skipIf(compiler="gcc") + @skipIf(compiler="clang", compiler_version=["<", "18.0"]) + def test(self): + """Test DWARF inline source files.""" + self.build() + #target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + # self, 'break here', lldb.SBFileSpec('inlined.c')) + target, process, thread, bkpt = lldbutil.run_to_name_breakpoint( + self, 'f') diff --git a/lldb/test/API/functionalities/inline-sourcefile/inline.ll b/lldb/test/API/functionalities/inline-sourcefile/inline.ll new file mode 100644 index 00000000000000..56194e45b81387 --- /dev/null +++ b/lldb/test/API/functionalities/inline-sourcefile/inline.ll @@ -0,0 +1,39 @@ +; ModuleID = '/tmp/t.c' +source_filename = "/tmp/t.c" +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +; Function Attrs: noinline nounwind optnone ssp uwtable(sync) +define void @f() #0 !dbg !9 { +entry: + call void @stop(), !dbg !13 + ret void, !dbg !14 +} + +declare void @stop(...) #1 + +attributes #0 = { noinline nounwind optnone ssp uwtable(sync) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 18.0.0git (g...@github.com:llvm/llvm-project.git 29ee66f4a0967e43a035f147c960743c7b640f2f)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/") +!1 = !DIFile(filename: "/INLINE/inlined.c", directory: "/Volumes/Data/llvm-project", checksumkind: CSK_MD5, checksum: "3183154a5cb31debe9a8e27ca500bc3c") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"uwtable", i32 1} +!7 = !{i32 7, !"frame-pointer", i32 1} +!8 = !{!"clang version 18.0.0git (g...@github.com:llvm/llvm-project.git 29ee66f4a0967e43a035f147c960743c7b640f2f)"} +!9 = distinct !DISubprogram(name: "f", scope: !10, file: !10, line: 2, type: !11, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0) +!10 = !DIFile(filename: "/INLINE/inlined.c", directory: "", source: "void stop(); +void f() { + // This is inline source code. + stop(); // break here +} +") +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !DILocation(line: 4, column: 3, scope: !9) +!14 = !DILocation(line: 5, column: 1, scope: !9) diff --git a/lldb/test/API/functionalities/inline-sourcefile/main.c b/lldb/test/API/functionalities/inline-sourcefile/main.c new file mode 100644 index 00000000000000..c030d7773fa70a --- /dev/null +++ b/lldb/test/API/functionalities/inline-sourcefile/main.c @@ -0,0 +1,7 @@ +void f(); +void stop() {} + +int main(int argc, char const *argv[]) { + f(); + return 0; +} >From f66f34faac71c87aa1692c24f835a46fb8e1f023 Mon Sep 17 00:00:00 2001 From: Adrian Prantl <apra...@apple.com> Date: Tue, 19 Dec 2023 17:47:06 -0800 Subject: [PATCH 2/2] Separate FileSpecList from SupportFileList --- lldb/include/lldb/Symbol/CompileUnit.h | 6 +- lldb/include/lldb/Symbol/SymbolFile.h | 2 +- lldb/include/lldb/Symbol/SymbolFileOnDemand.h | 2 +- lldb/include/lldb/Utility/FileSpecList.h | 94 +++++++++++-------- lldb/source/API/SBCompileUnit.cpp | 2 +- lldb/source/Commands/CommandObjectSource.cpp | 2 +- lldb/source/Core/ModuleList.cpp | 6 +- .../Clang/ClangUserExpression.cpp | 8 +- .../Clang/CppModuleConfiguration.cpp | 2 +- .../Clang/CppModuleConfiguration.h | 2 +- .../Breakpad/SymbolFileBreakpad.cpp | 5 +- .../SymbolFile/Breakpad/SymbolFileBreakpad.h | 3 +- .../Plugins/SymbolFile/CTF/SymbolFileCTF.h | 2 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 16 ++-- .../SymbolFile/DWARF/SymbolFileDWARF.h | 8 +- .../DWARF/SymbolFileDWARFDebugMap.cpp | 4 +- .../DWARF/SymbolFileDWARFDebugMap.h | 2 +- .../Plugins/SymbolFile/JSON/SymbolFileJSON.h | 2 +- .../NativePDB/SymbolFileNativePDB.cpp | 4 +- .../NativePDB/SymbolFileNativePDB.h | 2 +- .../Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 2 +- .../Plugins/SymbolFile/PDB/SymbolFilePDB.h | 2 +- .../SymbolFile/Symtab/SymbolFileSymtab.cpp | 2 +- .../SymbolFile/Symtab/SymbolFileSymtab.h | 2 +- lldb/source/Symbol/CompileUnit.cpp | 6 +- lldb/source/Symbol/SymbolFileOnDemand.cpp | 2 +- lldb/source/Utility/FileSpecList.cpp | 68 +++++++++++--- lldb/unittests/Core/FileSpecListTest.cpp | 8 +- .../Expression/CppModuleConfigurationTest.cpp | 4 +- 29 files changed, 165 insertions(+), 105 deletions(-) diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h index 93f191b4998584..4b7119c6c5cdcf 100644 --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -265,7 +265,7 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>, /// /// \return /// A support file list object. - const FileSpecList &GetSupportFiles(); + const SupportFileList &GetSupportFiles(); /// Get the compile unit's imported module list. /// @@ -331,7 +331,7 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>, /// A line table object pointer that this object now owns. void SetLineTable(LineTable *line_table); - void SetSupportFiles(FileSpecList support_files); + void SetSupportFiles(SupportFileList support_files); void SetDebugMacros(const DebugMacrosSP &debug_macros); @@ -412,7 +412,7 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>, FileSpec m_file_spec; /// Files associated with this compile unit's line table and /// declarations. - FileSpecList m_support_files; + SupportFileList m_support_files; /// Line table that will get parsed on demand. std::unique_ptr<LineTable> m_line_table_up; /// Debug macros that will get parsed on demand. diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index c9a2a647a039dc..f356f7b789fa38 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -197,7 +197,7 @@ class SymbolFile : public PluginInterface { return false; } virtual bool ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) = 0; + SupportFileList &support_files) = 0; virtual size_t ParseTypes(CompileUnit &comp_unit) = 0; virtual bool ParseIsOptimized(CompileUnit &comp_unit) { return false; } diff --git a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h index cde9f3c3b8ce1f..4e3009941aa7d6 100644 --- a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h +++ b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h @@ -81,7 +81,7 @@ class SymbolFileOnDemand : public lldb_private::SymbolFile { llvm::function_ref<bool(lldb_private::Module &)>) override; bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, - lldb_private::FileSpecList &support_files) override; + lldb_private::SupportFileList &support_files) override; bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override; diff --git a/lldb/include/lldb/Utility/FileSpecList.h b/lldb/include/lldb/Utility/FileSpecList.h index 8eda721b607fd6..80ab3294e1395d 100644 --- a/lldb/include/lldb/Utility/FileSpecList.h +++ b/lldb/include/lldb/Utility/FileSpecList.h @@ -37,6 +37,9 @@ class FileSpecHolder { FileSpecHolder(const FileSpecHolder &other) = default; FileSpecHolder(FileSpecHolder &&other) = default; FileSpecHolder &operator=(const FileSpecHolder &other) = default; + bool operator==(const FileSpecHolder &other) { + return m_file_spec == other.m_file_spec; + } const FileSpec &GetSpecOnly() const { return m_file_spec; }; const FileSpec &Materialize() const { if (m_lazy) @@ -45,13 +48,61 @@ class FileSpecHolder { } }; +class SupportFileList { +public: + typedef std::vector<FileSpecHolder> collection; + typedef collection::const_iterator const_iterator; + const_iterator begin() const { return m_files.begin(); } + const_iterator end() const { return m_files.end(); } + + void Append(const FileSpec &file) { return Append(FileSpecHolder(file)); } + void Append(const FileSpecHolder &file) { m_files.push_back(file); } + bool AppendIfUnique(const FileSpec &file); + bool AppendIfUnique(const FileSpecHolder &file); + size_t GetSize() const { return m_files.size(); } + const FileSpec &GetFileSpecAtIndex(size_t idx) const; + size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const; + /// Find a compatible file index. + /// + /// Find the index of a compatible file in the file spec list that matches \a + /// file starting \a idx entries into the file spec list. A file is considered + /// compatible if: + /// - The file matches exactly (only filename if \a file has no directory) + /// - If \a file is relative and any file in the list has this same suffix + /// - If any file in the list is relative and the relative path is a suffix + /// of \a file + /// + /// This is used to implement better matching for setting breakpoints in + /// source files where an IDE might specify a full path when setting the + /// breakpoint and debug info contains relative paths, if a user specifies + /// a relative path when setting a breakpoint. + /// + /// \param[in] idx + /// An index into the file list. + /// + /// \param[in] file + /// The file specification to search for. + /// + /// \return + /// The index of the file that matches \a file if it is found, + /// else UINT32_MAX is returned. + size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const; + + template <class... Args> void EmplaceBack(Args &&...args) { + m_files.emplace_back(FileSpec(std::forward<Args>(args)...)); + } + +protected: + collection m_files; ///< A collection of FileSpec objects. +}; + /// \class FileSpecList FileSpecList.h "lldb/Utility/FileSpecList.h" /// A file collection class. /// /// A class that contains a mutable list of FileSpec objects. class FileSpecList { public: - typedef std::vector<FileSpecHolder> collection; + typedef std::vector<FileSpec> collection; typedef collection::const_iterator const_iterator; /// Default constructor. @@ -66,10 +117,7 @@ class FileSpecList { FileSpecList(FileSpecList &&rhs) = default; /// Initialize this object from a vector of FileSpecs - FileSpecList(std::vector<FileSpec> &&rhs) { - for (auto &fs : rhs) - m_files.emplace_back(fs); - } + FileSpecList(std::vector<FileSpec> &&rhs) : m_files(std::move(rhs)) {} /// Destructor. ~FileSpecList(); @@ -114,11 +162,9 @@ class FileSpecList { /// \param[in] args /// Arguments to create the FileSpec template <class... Args> void EmplaceBack(Args &&...args) { - m_files.emplace_back(FileSpec(std::forward<Args>(args)...)); + m_files.emplace_back(std::forward<Args>(args)...); } - void Append(FileSpecHolder &&fsh) { m_files.push_back(std::move(fsh)); } - /// Clears the file list. void Clear(); @@ -147,32 +193,6 @@ class FileSpecList { /// else UINT32_MAX is returned. size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const; - /// Find a compatible file index. - /// - /// Find the index of a compatible file in the file spec list that matches \a - /// file starting \a idx entries into the file spec list. A file is considered - /// compatible if: - /// - The file matches exactly (only filename if \a file has no directory) - /// - If \a file is relative and any file in the list has this same suffix - /// - If any file in the list is relative and the relative path is a suffix - /// of \a file - /// - /// This is used to implement better matching for setting breakpoints in - /// source files where an IDE might specify a full path when setting the - /// breakpoint and debug info contains relative paths, if a user specifies - /// a relative path when setting a breakpoint. - /// - /// \param[in] idx - /// An index into the file list. - /// - /// \param[in] file - /// The file specification to search for. - /// - /// \return - /// The index of the file that matches \a file if it is found, - /// else UINT32_MAX is returned. - size_t FindCompatibleIndex(size_t idx, const FileSpec &file) const; - /// Get file at index. /// /// Gets a file from the file list. If \a idx is not a valid index, an empty @@ -208,10 +228,10 @@ class FileSpecList { bool Insert(size_t idx, const FileSpec &file) { if (idx < m_files.size()) { - m_files.insert(m_files.begin() + idx, FileSpecHolder(file)); + m_files.insert(m_files.begin() + idx, file); return true; } else if (idx == m_files.size()) { - m_files.push_back(FileSpecHolder(file)); + m_files.push_back(file); return true; } return false; @@ -219,7 +239,7 @@ class FileSpecList { bool Replace(size_t idx, const FileSpec &file) { if (idx < m_files.size()) { - m_files[idx] = FileSpecHolder(file); + m_files[idx] = file; return true; } return false; diff --git a/lldb/source/API/SBCompileUnit.cpp b/lldb/source/API/SBCompileUnit.cpp index 3aa65e225d7aba..65fdb11032b9c0 100644 --- a/lldb/source/API/SBCompileUnit.cpp +++ b/lldb/source/API/SBCompileUnit.cpp @@ -171,7 +171,7 @@ uint32_t SBCompileUnit::FindSupportFileIndex(uint32_t start_idx, LLDB_INSTRUMENT_VA(this, start_idx, sb_file, full); if (m_opaque_ptr) { - const FileSpecList &support_files = m_opaque_ptr->GetSupportFiles(); + const SupportFileList &support_files = m_opaque_ptr->GetSupportFiles(); return support_files.FindFileIndex(start_idx, sb_file.ref(), full); } return 0; diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index db158a7f526305..cabf6f0436f176 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -204,7 +204,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed { if (cu) { assert(file_spec.GetFilename().AsCString()); bool has_path = (file_spec.GetDirectory().AsCString() != nullptr); - const FileSpecList &cu_file_list = cu->GetSupportFiles(); + const SupportFileList &cu_file_list = cu->GetSupportFiles(); size_t file_idx = cu_file_list.FindFileIndex(0, file_spec, has_path); if (file_idx != UINT32_MAX) { // Update the file to how it appears in the CU. diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 3b6c3ea899caf7..2180f29f369427 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -166,11 +166,9 @@ void ModuleListProperties::UpdateSymlinkMappings() { m_symlink_paths.Clear(notify); for (auto symlink : list) { FileSpec resolved; - Status status = - FileSystem::Instance().Readlink(symlink.Materialize(), resolved); + Status status = FileSystem::Instance().Readlink(symlink, resolved); if (status.Success()) - m_symlink_paths.Append(symlink.Materialize().GetPath(), - resolved.GetPath(), notify); + m_symlink_paths.Append(symlink.GetPath(), resolved.GetPath(), notify); } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index ec03a38752c2fe..619f70f565a364 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -487,19 +487,19 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, return LogConfigError("Couldn't calculate symbol context"); // Build a list of files we need to analyze to build the configuration. - FileSpecList files; + SupportFileList files; for (auto &f : sc.comp_unit->GetSupportFiles()) - files.AppendIfUnique(f.Materialize()); + files.AppendIfUnique(f); // We also need to look at external modules in the case of -gmodules as they // contain the support files for libc++ and the C library. llvm::DenseSet<SymbolFile *> visited_symbol_files; sc.comp_unit->ForEachExternalModule( visited_symbol_files, [&files](Module &module) { for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) { - const FileSpecList &support_files = + const SupportFileList &support_files = module.GetCompileUnitAtIndex(i)->GetSupportFiles(); for (auto &f : support_files) { - files.AppendIfUnique(f.Materialize()); + files.AppendIfUnique(f); } } return false; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp index 0cd52db97521a1..ff9abd05d30a8e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -132,7 +132,7 @@ bool CppModuleConfiguration::hasValidConfig() { } CppModuleConfiguration::CppModuleConfiguration( - const FileSpecList &support_files, const llvm::Triple &triple) { + const SupportFileList &support_files, const llvm::Triple &triple) { // Analyze all files we were given to build the configuration. bool error = !llvm::all_of(support_files, [&](auto &file) { return CppModuleConfiguration::analyzeFile(file.Materialize(), triple); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h index 7be0ce6c7ae579..0e3408bae06ba2 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -65,7 +65,7 @@ class CppModuleConfiguration { public: /// Creates a configuration by analyzing the given list of used source files. /// The triple (if valid) is used to search for target-specific include paths. - explicit CppModuleConfiguration(const FileSpecList &support_files, + explicit CppModuleConfiguration(const SupportFileList &support_files, const llvm::Triple &triple); /// Creates an empty and invalid configuration. CppModuleConfiguration() = default; diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index 729d6af02402d8..47c8074adc5b7c 100644 --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -278,13 +278,14 @@ bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) { } bool SymbolFileBreakpad::ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) { + SupportFileList &support_files) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); CompUnitData &data = m_cu_data->GetEntryRef(comp_unit.GetID()).data; if (!data.support_files) ParseLineTableAndSupportFiles(comp_unit, data); - support_files = std::move(*data.support_files); + for (auto &fs : *data.support_files) + support_files.Append(fs); return true; } diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 214fbdd3ff3aa0..41e4e3b258014c 100644 --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -73,7 +73,7 @@ class SymbolFileBreakpad : public SymbolFileCommon { bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; } bool ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) override; + SupportFileList &support_files) override; size_t ParseTypes(CompileUnit &cu) override { return 0; } bool ParseImportedModules( @@ -195,7 +195,6 @@ class SymbolFileBreakpad : public SymbolFileCommon { Bookmark bookmark; std::optional<FileSpecList> support_files; std::unique_ptr<LineTable> line_table_up; - }; uint32_t CalculateNumCompileUnits() override; diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index f111937dbd6ef0..3a80138fffbc37 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -66,7 +66,7 @@ class SymbolFileCTF : public lldb_private::SymbolFileCommon { bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; } bool ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) override { + SupportFileList &support_files) override { return false; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 52caa5885baac2..1b1b3cdbe557be 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -210,12 +210,12 @@ GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx, return std::move(rel_path); } -static FileSpecList +static SupportFileList ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style, llvm::StringRef compile_dir = {}) { - FileSpecList support_files; + SupportFileList support_files; // Handle the case where there are no files first to avoid having to special // case this later. @@ -822,7 +822,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { // file is also the name of the compile unit. This // allows us to avoid loading the non-skeleton unit, // which may be in a separate DWO file. - FileSpecList support_files; + SupportFileList support_files; if (!ParseSupportFiles(dwarf_cu, module_sp, support_files)) return false; if (support_files.GetSize() == 0) @@ -1076,7 +1076,7 @@ bool SymbolFileDWARF::ForEachExternalModule( } bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) { + SupportFileList &support_files) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit); if (!dwarf_cu) @@ -1091,7 +1091,7 @@ bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu, const ModuleSP &module, - FileSpecList &support_files) { + SupportFileList &support_files) { dw_offset_t offset = dwarf_cu.GetLineTableOffset(); if (offset == DW_INVALID_OFFSET) @@ -1120,9 +1120,9 @@ FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { return GetTypeUnitSupportFiles(tu).GetFileSpecAtIndex(file_idx); } -const FileSpecList & +const SupportFileList & SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { - static FileSpecList empty_list; + static SupportFileList empty_list; dw_offset_t offset = tu.GetLineTableOffset(); if (offset == DW_INVALID_OFFSET || @@ -1133,7 +1133,7 @@ SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { // Many type units can share a line table, so parse the support file list // once, and cache it based on the offset field. auto iter_bool = m_type_unit_support_files.try_emplace(offset); - FileSpecList &list = iter_bool.first->second; + SupportFileList &list = iter_bool.first->second; if (iter_bool.second) { uint64_t line_table_offset = offset; llvm::DWARFDataExtractor data = diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 78819edd0062bf..f4de005af59fb1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -123,7 +123,7 @@ class SymbolFileDWARF : public SymbolFileCommon { llvm::function_ref<bool(Module &)>) override; bool ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) override; + SupportFileList &support_files) override; bool ParseIsOptimized(CompileUnit &comp_unit) override; @@ -396,7 +396,7 @@ class SymbolFileDWARF : public SymbolFileCommon { bool *type_is_new); bool ParseSupportFiles(DWARFUnit &dwarf_cu, const lldb::ModuleSP &module, - FileSpecList &support_files); + SupportFileList &support_files); lldb::VariableSP ParseVariableDIE(const SymbolContext &sc, const DWARFDIE &die, @@ -489,7 +489,7 @@ class SymbolFileDWARF : public SymbolFileCommon { void FindDwpSymbolFile(); - const FileSpecList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); + const SupportFileList &GetTypeUnitSupportFiles(DWARFTypeUnit &tu); void InitializeFirstCodeAddressRecursive(const SectionList §ion_list); @@ -529,7 +529,7 @@ class SymbolFileDWARF : public SymbolFileCommon { DIEToVariableSP m_die_to_variable_sp; DIEToCompilerType m_forward_decl_die_to_compiler_type; CompilerTypeToDIE m_forward_decl_compiler_type_to_die; - llvm::DenseMap<dw_offset_t, FileSpecList> m_type_unit_support_files; + llvm::DenseMap<dw_offset_t, SupportFileList> m_type_unit_support_files; std::vector<uint32_t> m_lldb_cu_to_dwarf_unit; /// DWARF does not provide a good way for traditional (concatenating) linkers /// to invalidate debug info describing dead-stripped code. These linkers will diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index e5b59460cb85d5..9094a5e21e690c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -725,8 +725,8 @@ bool SymbolFileDWARFDebugMap::ForEachExternalModule( return false; } -bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) { +bool SymbolFileDWARFDebugMap::ParseSupportFiles( + CompileUnit &comp_unit, SupportFileList &support_files) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit); if (oso_dwarf) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index cd0a4bb6e41c2f..d639ee500080d5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -74,7 +74,7 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon { llvm::function_ref<bool(Module &)>) override; bool ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) override; + SupportFileList &support_files) override; bool ParseIsOptimized(CompileUnit &comp_unit) override; diff --git a/lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h b/lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h index 4dd0d65da46583..3dd33b3dc82fba 100644 --- a/lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h +++ b/lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h @@ -59,7 +59,7 @@ class SymbolFileJSON : public lldb_private::SymbolFileCommon { bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; } bool ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) override { + SupportFileList &support_files) override { return false; } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index ad08013399369e..8375010ae3dedd 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1369,7 +1369,7 @@ SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii, } bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) { + SupportFileList &support_files) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid cu_id(comp_unit.GetID()); lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); @@ -1416,7 +1416,7 @@ void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, return; InlineeSourceLine inlinee_line = iter->second; - const FileSpecList &files = comp_unit->GetSupportFiles(); + const SupportFileList &files = comp_unit->GetSupportFiles(); FileSpec decl_file; llvm::Expected<uint32_t> file_index_or_err = GetFileIndex(*cii, inlinee_line.Header->FileID); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 9d0458cf7ebfeb..82577771f355c8 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -94,7 +94,7 @@ class SymbolFileNativePDB : public SymbolFileCommon { bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, - FileSpecList &support_files) override; + SupportFileList &support_files) override; size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; bool ParseImportedModules( diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 9e1cd836066021..b26beecc6d1263 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -365,7 +365,7 @@ bool SymbolFilePDB::ParseDebugMacros(CompileUnit &comp_unit) { } bool SymbolFilePDB::ParseSupportFiles( - CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) { + CompileUnit &comp_unit, lldb_private::SupportFileList &support_files) { // In theory this is unnecessary work for us, because all of this information // is easily (and quickly) accessible from DebugInfoPDB, so caching it a diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 01851f1418f3a8..ea495c575f1f1a 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -70,7 +70,7 @@ class SymbolFilePDB : public lldb_private::SymbolFileCommon { bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, - lldb_private::FileSpecList &support_files) override; + lldb_private::SupportFileList &support_files) override; size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 6e4c6439974e95..8c17017442b1f8 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -211,7 +211,7 @@ bool SymbolFileSymtab::ParseDebugMacros(CompileUnit &comp_unit) { } bool SymbolFileSymtab::ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) { + SupportFileList &support_files) { return false; } diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index 1bbc4de9c9425b..a36311525334e4 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -57,7 +57,7 @@ class SymbolFileSymtab : public lldb_private::SymbolFileCommon { bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override; bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit, - lldb_private::FileSpecList &support_files) override; + lldb_private::SupportFileList &support_files) override; size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override; diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index c9796973940a24..6ba3e0d7bd909c 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -178,7 +178,7 @@ void CompileUnit::SetLineTable(LineTable *line_table) { m_line_table_up.reset(line_table); } -void CompileUnit::SetSupportFiles(FileSpecList support_files) { +void CompileUnit::SetSupportFiles(SupportFileList support_files) { m_support_files = std::move(support_files); } @@ -213,7 +213,7 @@ VariableListSP CompileUnit::GetVariableList(bool can_create) { return m_variables; } -std::vector<uint32_t> FindFileIndexes(const FileSpecList &files, +std::vector<uint32_t> FindFileIndexes(const SupportFileList &files, const FileSpec &file) { std::vector<uint32_t> result; uint32_t idx = -1; @@ -411,7 +411,7 @@ bool CompileUnit::ForEachExternalModule( return false; } -const FileSpecList &CompileUnit::GetSupportFiles() { +const SupportFileList &CompileUnit::GetSupportFiles() { if (m_support_files.GetSize() == 0) { if (m_flags.IsClear(flagsParsedSupportFiles)) { m_flags.Set(flagsParsedSupportFiles); diff --git a/lldb/source/Symbol/SymbolFileOnDemand.cpp b/lldb/source/Symbol/SymbolFileOnDemand.cpp index 33995252bfe2c9..bdb1951d51259d 100644 --- a/lldb/source/Symbol/SymbolFileOnDemand.cpp +++ b/lldb/source/Symbol/SymbolFileOnDemand.cpp @@ -115,7 +115,7 @@ bool SymbolFileOnDemand::ForEachExternalModule( } bool SymbolFileOnDemand::ParseSupportFiles(CompileUnit &comp_unit, - FileSpecList &support_files) { + SupportFileList &support_files) { LLDB_LOG(GetLog(), "[{0}] {1} is not skipped: explicitly allowed to support breakpoint", GetSymbolFileName(), __FUNCTION__); diff --git a/lldb/source/Utility/FileSpecList.cpp b/lldb/source/Utility/FileSpecList.cpp index c2ebbfd5ec854f..3c1d41bc846d9a 100644 --- a/lldb/source/Utility/FileSpecList.cpp +++ b/lldb/source/Utility/FileSpecList.cpp @@ -30,7 +30,17 @@ void FileSpecList::Append(const FileSpec &file_spec) { // a copy of "file_spec". bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) { collection::iterator end = m_files.end(); - if (find_if(m_files.begin(), end, [&](auto &holder) { + if (find(m_files.begin(), end, file_spec) == end) { + m_files.push_back(file_spec); + return true; + } + return false; +} + +// FIXME: Replace this with a DenseSet at the call site. It is inefficient. +bool SupportFileList::AppendIfUnique(const FileSpec &file_spec) { + collection::iterator end = m_files.end(); + if (find_if(m_files.begin(), end, [&](const FileSpecHolder &holder) { return holder.GetSpecOnly() == file_spec; }) == end) { m_files.push_back(file_spec); @@ -39,6 +49,16 @@ bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) { return false; } +// FIXME: Replace this with a DenseSet at the call site. It is inefficient. +bool SupportFileList::AppendIfUnique(const FileSpecHolder &holder) { + collection::iterator end = m_files.end(); + if (find(m_files.begin(), end, holder) == end) { + m_files.push_back(holder); + return true; + } + return false; +} + // Clears the file list. void FileSpecList::Clear() { m_files.clear(); } @@ -46,7 +66,7 @@ void FileSpecList::Clear() { m_files.clear(); } void FileSpecList::Dump(Stream *s, const char *separator_cstr) const { collection::const_iterator pos, end = m_files.end(); for (pos = m_files.begin(); pos != end; ++pos) { - pos->GetSpecOnly().Dump(s->AsRawOstream()); + pos->Dump(s->AsRawOstream()); if (separator_cstr && ((pos + 1) != end)) s->PutCString(separator_cstr); } @@ -57,23 +77,22 @@ void FileSpecList::Dump(Stream *s, const char *separator_cstr) const { // // Returns the valid index of the file that matches "file_spec" if it is found, // else std::numeric_limits<uint32_t>::max() is returned. -size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec, - bool full) const { - const size_t num_files = m_files.size(); - +static size_t FindFileIndex(size_t start_idx, const FileSpec &file_spec, + bool full, size_t num_files, + std::function<const FileSpec &(size_t)> get_ith) { // When looking for files, we will compare only the filename if the FILE_SPEC // argument is empty bool compare_filename_only = file_spec.GetDirectory().IsEmpty(); for (size_t idx = start_idx; idx < num_files; ++idx) { - auto f = m_files[idx].GetSpecOnly(); + const FileSpec &ith = get_ith(idx); if (compare_filename_only) { - if (ConstString::Equals(f.GetFilename(), file_spec.GetFilename(), + if (ConstString::Equals(ith.GetFilename(), file_spec.GetFilename(), file_spec.IsCaseSensitive() || - f.IsCaseSensitive())) + ith.IsCaseSensitive())) return idx; } else { - if (FileSpec::Equal(f, file_spec, full)) + if (FileSpec::Equal(ith, file_spec, full)) return idx; } } @@ -82,8 +101,24 @@ size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec, return UINT32_MAX; } -size_t FileSpecList::FindCompatibleIndex(size_t start_idx, - const FileSpec &file_spec) const { +size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec, + bool full) const { + return ::FindFileIndex( + start_idx, file_spec, full, m_files.size(), + [&](size_t idx) -> const FileSpec & { return m_files[idx]; }); +} + +size_t SupportFileList::FindFileIndex(size_t start_idx, + const FileSpec &file_spec, + bool full) const { + return ::FindFileIndex(start_idx, file_spec, full, m_files.size(), + [&](size_t idx) -> const FileSpec & { + return m_files[idx].GetSpecOnly(); + }); +} + +size_t SupportFileList::FindCompatibleIndex(size_t start_idx, + const FileSpec &file_spec) const { const size_t num_files = m_files.size(); if (start_idx >= num_files) return UINT32_MAX; @@ -137,6 +172,13 @@ size_t FileSpecList::FindCompatibleIndex(size_t start_idx, // Returns the FileSpec object at index "idx". If "idx" is out of range, then // an empty FileSpec object will be returned. const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const { + if (idx < m_files.size()) + return m_files[idx]; + static FileSpec g_empty_file_spec; + return g_empty_file_spec; +} + +const FileSpec &SupportFileList::GetFileSpecAtIndex(size_t idx) const { if (idx < m_files.size()) return m_files[idx].Materialize(); static FileSpec g_empty_file_spec; @@ -151,7 +193,7 @@ size_t FileSpecList::MemorySize() const { size_t mem_size = sizeof(FileSpecList); collection::const_iterator pos, end = m_files.end(); for (pos = m_files.begin(); pos != end; ++pos) { - mem_size += pos->GetSpecOnly().MemorySize(); + mem_size += pos->MemorySize(); } return mem_size; diff --git a/lldb/unittests/Core/FileSpecListTest.cpp b/lldb/unittests/Core/FileSpecListTest.cpp index d65e7cd2d0586b..e63f4a00bc3a94 100644 --- a/lldb/unittests/Core/FileSpecListTest.cpp +++ b/lldb/unittests/Core/FileSpecListTest.cpp @@ -20,7 +20,7 @@ static FileSpec WindowsSpec(llvm::StringRef path) { return FileSpec(path, FileSpec::Style::windows); } -TEST(FileSpecListTest, RelativePathMatchesPosix) { +TEST(SupportFileListTest, RelativePathMatchesPosix) { const FileSpec fullpath = PosixSpec("/build/src/main.cpp"); const FileSpec relative = PosixSpec("./src/main.cpp"); @@ -32,7 +32,7 @@ TEST(FileSpecListTest, RelativePathMatchesPosix) { const FileSpec rel2_wrong = PosixSpec("asrc/main.cpp"); const FileSpec rel3_wrong = PosixSpec("rc/main.cpp"); - FileSpecList files; + SupportFileList files; files.Append(fullpath); files.Append(relative); files.Append(basename); @@ -72,7 +72,7 @@ TEST(FileSpecListTest, RelativePathMatchesPosix) { EXPECT_EQ((size_t)6, files.FindCompatibleIndex(3, rel3_wrong)); } -TEST(FileSpecListTest, RelativePathMatchesWindows) { +TEST(SupportFileListTest, RelativePathMatchesWindows) { const FileSpec fullpath = WindowsSpec(R"(C:\build\src\main.cpp)"); const FileSpec relative = WindowsSpec(R"(.\src\main.cpp)"); @@ -84,7 +84,7 @@ TEST(FileSpecListTest, RelativePathMatchesWindows) { const FileSpec rel2_wrong = WindowsSpec(R"(asrc\main.cpp)"); const FileSpec rel3_wrong = WindowsSpec(R"("rc\main.cpp)"); - FileSpecList files; + SupportFileList files; files.Append(fullpath); files.Append(relative); files.Append(basename); diff --git a/lldb/unittests/Expression/CppModuleConfigurationTest.cpp b/lldb/unittests/Expression/CppModuleConfigurationTest.cpp index 017a0748c2243c..3c395938f1af86 100644 --- a/lldb/unittests/Expression/CppModuleConfigurationTest.cpp +++ b/lldb/unittests/Expression/CppModuleConfigurationTest.cpp @@ -37,8 +37,8 @@ struct CppModuleConfigurationTest : public testing::Test { } /// Utility function turning a list of paths into a FileSpecList. - FileSpecList makeFiles(llvm::ArrayRef<std::string> paths) { - FileSpecList result; + SupportFileList makeFiles(llvm::ArrayRef<std::string> paths) { + SupportFileList result; for (const std::string &path : paths) { result.Append(FileSpec(path, FileSpec::Style::posix)); if (!m_fs->addFileNoOwn(path, static_cast<time_t>(0), m_empty_buffer)) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits