Author: Adrian Prantl Date: 2024-01-04T09:04:05-08:00 New Revision: 917b404e2ccdcc31d2d64971ad094b80967a240b
URL: https://github.com/llvm/llvm-project/commit/917b404e2ccdcc31d2d64971ad094b80967a240b DIFF: https://github.com/llvm/llvm-project/commit/917b404e2ccdcc31d2d64971ad094b80967a240b.diff LOG: Add support for inline DWARF source files. (#75880) 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. rdar://110926168 Added: lldb/test/API/functionalities/inline-sourcefile/Makefile lldb/test/API/functionalities/inline-sourcefile/TestInlineSourceFiles.py lldb/test/API/functionalities/inline-sourcefile/inline.ll lldb/test/API/functionalities/inline-sourcefile/main.c Modified: lldb/include/lldb/Symbol/CompileUnit.h lldb/include/lldb/Symbol/SymbolFile.h lldb/include/lldb/Symbol/SymbolFileOnDemand.h lldb/include/lldb/Utility/FileSpecList.h lldb/source/API/SBCompileUnit.cpp lldb/source/Commands/CommandObjectSource.cpp lldb/source/Core/ModuleList.cpp lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h lldb/source/Plugins/SymbolFile/JSON/SymbolFileJSON.h lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h lldb/source/Symbol/CompileUnit.cpp lldb/source/Symbol/SymbolFileOnDemand.cpp lldb/source/Utility/FileSpecList.cpp lldb/unittests/Core/FileSpecListTest.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h index 93f191b4998584..89e853ab599d0f 100644 --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -112,10 +112,13 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>, /// the compile unit is optimized will be made when /// CompileUnit::GetIsOptimized() is called. /// + /// \param[in] support_files + /// An rvalue list of already parsed support files. /// \see lldb::LanguageType CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, - lldb::LanguageType language, lldb_private::LazyBool is_optimized); + lldb::LanguageType language, lldb_private::LazyBool is_optimized, + SupportFileList &&support_files = {}); /// Add a function to this compile unit. /// @@ -226,6 +229,9 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>, /// Return the primary source file associated with this compile unit. const FileSpec &GetPrimaryFile() const { return m_file_spec; } + /// Return the primary source file associated with this compile unit. + void SetPrimaryFile(const FileSpec &fs) { m_file_spec = fs; } + /// Get the line table for the compile unit. /// /// 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>, /// /// \return /// A support file list object. - const FileSpecList &GetSupportFiles(); + const SupportFileList &GetSupportFiles(); + + /// Used by plugins that parse the support file list. + SupportFileList &GetSupportFileList() { + m_flags.Set(flagsParsedSupportFiles); + return m_support_files; + } /// Get the compile unit's imported module list. /// @@ -331,8 +343,6 @@ 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 SetDebugMacros(const DebugMacrosSP &debug_macros); /// Set accessor for the variable list. @@ -410,9 +420,8 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>, std::vector<SourceModule> m_imported_modules; /// The primary file associated with this compile unit. FileSpec m_file_spec; - /// Files associated with this compile unit's line table and - /// declarations. - FileSpecList m_support_files; + /// Files associated with this compile unit's line table and declarations. + 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 77587aa917916b..8cccb194999917 100644 --- a/lldb/include/lldb/Utility/FileSpecList.h +++ b/lldb/include/lldb/Utility/FileSpecList.h @@ -17,6 +17,86 @@ namespace lldb_private { class Stream; +/// Wraps either a FileSpec that represents a local file or 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 +/// file yet. +class SupportFile { +protected: + FileSpec m_file_spec; + +public: + SupportFile(const FileSpec &spec) : m_file_spec(spec) {} + SupportFile(const SupportFile &other) = delete; + SupportFile(SupportFile &&other) = default; + virtual ~SupportFile() = default; + bool operator==(const SupportFile &other) { + return m_file_spec == other.m_file_spec; + } + /// Return the file name only. Useful for resolving breakpoints by file name. + const FileSpec &GetSpecOnly() const { return m_file_spec; }; + /// Materialize the file to disk and return the path to that temporary file. + virtual const FileSpec &Materialize() { return m_file_spec; } +}; + +/// A list of support files for a CompileUnit. +class SupportFileList { +public: + SupportFileList(){}; + SupportFileList(const SupportFileList &) = delete; + SupportFileList(SupportFileList &&other) = default; + + typedef std::vector<std::unique_ptr<SupportFile>> 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(std::make_unique<SupportFile>(file)); + } + void Append(std::unique_ptr<SupportFile> &&file) { + m_files.push_back(std::move(file)); + } + // FIXME: Only used by SymbolFilePDB. Replace with a DenseSet at call site. + bool AppendIfUnique(const FileSpec &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.push_back( + std::make_unique<SupportFile>(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. /// @@ -114,32 +194,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 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 aa89c93c8d0521..2180f29f369427 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -164,7 +164,7 @@ 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); if (status.Success()) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 68bdd96e8adb03..30bc81c9ed8c19 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -488,18 +488,18 @@ 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; 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 (const FileSpec &f : support_files) { - files.AppendIfUnique(f); + for (auto &f : support_files) { + files.AppendIfUnique(f->Materialize()); } } return false; @@ -508,7 +508,7 @@ 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()); } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp index 62443d1290dc72..f43a04488230f0 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, 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/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 505ea29ca4d4f5..447930ffe07b3f 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" @@ -209,17 +210,14 @@ GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx, return std::move(rel_path); } -static FileSpecList -ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, - const llvm::DWARFDebugLine::Prologue &prologue, - FileSpec::Style style, - llvm::StringRef compile_dir = {}) { - FileSpecList support_files; - +static void ParseSupportFilesFromPrologue( + SupportFileList &support_files, const lldb::ModuleSP &module, + const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style, + llvm::StringRef compile_dir = {}) { // Handle the case where there are no files first to avoid having to special // case this later. if (prologue.FileNames.empty()) - return support_files; + return; // Before DWARF v5, the line table indexes were one based. const bool is_one_based = prologue.getVersion() < 5; @@ -235,6 +233,53 @@ 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 LazyDWARFSourceFile : public SupportFile { + LazyDWARFSourceFile(const FileSpec &fs, llvm::StringRef source, + FileSpec::Style style) + : SupportFile(fs), source(source), style(style) {} + FileSpec tmp_file; + /// The file contents buffer. + llvm::StringRef source; + /// Deletes the temporary file at the end. + 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 orig_name = m_file_spec.GetFilename().GetStringRef(); + auto ec = llvm::sys::fs::createTemporaryFile( + "", llvm::sys::path::filename(orig_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(std::make_unique<LazyDWARFSourceFile>( + FileSpec(*file_path), *source, style)); + continue; + } + } if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path))) remapped_file = *remapped; else @@ -251,8 +296,6 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, // Unconditionally add an entry, so the indices match up. support_files.EmplaceBack(remapped_file, style, checksum); } - - return support_files; } void SymbolFileDWARF::Initialize() { @@ -744,12 +787,13 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { ModuleSP module_sp(m_objfile_sp->GetModule()); if (module_sp) { auto initialize_cu = [&](const FileSpec &file_spec, - LanguageType cu_language) { + LanguageType cu_language, + SupportFileList &&support_files = {}) { BuildCuTranslationTable(); cu_sp = std::make_shared<CompileUnit>( module_sp, &dwarf_cu, file_spec, *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language, - eLazyBoolCalculate); + eLazyBoolCalculate, std::move(support_files)); dwarf_cu.SetUserData(cu_sp.get()); @@ -775,15 +819,13 @@ 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) return false; - initialize_cu(support_files.GetFileSpecAtIndex(0), - eLanguageTypeUnknown); - cu_sp->SetSupportFiles(std::move(support_files)); + eLanguageTypeUnknown, std::move(support_files)); return true; }; @@ -1029,7 +1071,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) @@ -1038,13 +1080,12 @@ bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit, if (!ParseSupportFiles(*dwarf_cu, comp_unit.GetModule(), support_files)) return false; - comp_unit.SetSupportFiles(support_files); return true; } 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) @@ -1057,8 +1098,8 @@ bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu, return false; std::string comp_dir = dwarf_cu.GetCompilationDirectory().GetPath(); - support_files = ParseSupportFilesFromPrologue( - module, prologue, dwarf_cu.GetPathStyle(), comp_dir); + ParseSupportFilesFromPrologue(support_files, module, prologue, + dwarf_cu.GetPathStyle(), comp_dir); return true; } @@ -1070,24 +1111,27 @@ FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) { } auto &tu = llvm::cast<DWARFTypeUnit>(unit); - return GetTypeUnitSupportFiles(tu).GetFileSpecAtIndex(file_idx); + if (const SupportFileList *support_files = GetTypeUnitSupportFiles(tu)) + return support_files->GetFileSpecAtIndex(file_idx); + return {}; } -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 || offset == llvm::DenseMapInfo<dw_offset_t>::getEmptyKey() || offset == llvm::DenseMapInfo<dw_offset_t>::getTombstoneKey()) - return empty_list; + return nullptr; // 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; + std::unique_ptr<SupportFileList> &list = iter_bool.first->second; if (iter_bool.second) { + list = std::make_unique<SupportFileList>(); uint64_t line_table_offset = offset; llvm::DWARFDataExtractor data = m_context.getOrLoadLineData().GetAsLLVMDWARF(); @@ -1101,14 +1145,13 @@ SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) { }; ElapsedTime elapsed(m_parse_time); llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx); - if (error) { + if (error) report(std::move(error)); - } else { - list = ParseSupportFilesFromPrologue(GetObjectFile()->GetModule(), - prologue, tu.GetPathStyle()); - } + else + ParseSupportFilesFromPrologue(*list, GetObjectFile()->GetModule(), + prologue, tu.GetPathStyle()); } - return list; + return list.get(); } bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 78819edd0062bf..26a9502f90aa00 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,8 @@ 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, std::unique_ptr<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..a6b6c8e57eec01 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -28,10 +28,11 @@ CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, - lldb_private::LazyBool is_optimized) + lldb_private::LazyBool is_optimized, + SupportFileList &&support_files) : ModuleChild(module_sp), UserID(cu_sym_id), m_user_data(user_data), m_language(language), m_flags(0), m_file_spec(fspec), - m_is_optimized(is_optimized) { + m_support_files(std::move(support_files)), m_is_optimized(is_optimized) { if (language != eLanguageTypeUnknown) m_flags.Set(flagsParsedLanguage); assert(module_sp); @@ -178,10 +179,6 @@ void CompileUnit::SetLineTable(LineTable *line_table) { m_line_table_up.reset(line_table); } -void CompileUnit::SetSupportFiles(FileSpecList support_files) { - m_support_files = std::move(support_files); -} - DebugMacros *CompileUnit::GetDebugMacros() { if (m_debug_macros_sp.get() == nullptr) { if (m_flags.IsClear(flagsParsedDebugMacros)) { @@ -213,7 +210,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 +408,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 e3d8ea650c75dc..8d2cf81efe5b13 100644 --- a/lldb/source/Utility/FileSpecList.cpp +++ b/lldb/source/Utility/FileSpecList.cpp @@ -37,6 +37,19 @@ 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 FileSpec &file_spec) { + collection::iterator end = m_files.end(); + if (find_if(m_files.begin(), end, + [&](const std::unique_ptr<SupportFile> &support_file) { + return support_file->GetSpecOnly() == file_spec; + }) == end) { + Append(file_spec); + return true; + } + return false; +} + // Clears the file list. void FileSpecList::Clear() { m_files.clear(); } @@ -55,22 +68,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) { + const FileSpec &ith = get_ith(idx); if (compare_filename_only) { - if (ConstString::Equals( - m_files[idx].GetFilename(), file_spec.GetFilename(), - file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive())) + if (ConstString::Equals(ith.GetFilename(), file_spec.GetFilename(), + file_spec.IsCaseSensitive() || + ith.IsCaseSensitive())) return idx; } else { - if (FileSpec::Equal(m_files[idx], file_spec, full)) + if (FileSpec::Equal(ith, file_spec, full)) return idx; } } @@ -79,8 +92,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; @@ -92,7 +121,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)) @@ -140,6 +169,13 @@ const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const { 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; + return g_empty_file_spec; +} + // Return the size in bytes that this object takes in memory. This returns the // size in bytes of this object's member variables and any FileSpec objects its // member variables contain, the result doesn't not include the string values 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..20ed0ce00661f0 --- /dev/null +++ b/lldb/test/API/functionalities/inline-sourcefile/TestInlineSourceFiles.py @@ -0,0 +1,15 @@ +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() + lldbutil.run_to_name_breakpoint(self, 'f') + self.expect("list f", substrs=["This is inline source code"]) 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; +} 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); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits