From c5fd298463905670018c68383a5e305cf7b918e6 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 20 Nov 2025 16:45:11 -0800 Subject: [PATCH] [lldb] Eliminate SupportFileSP nullptr derefs (#168624) This patch fixes and eliminates the possibility of SupportFileSP ever being nullptr. The support file was originally treated like a value type, but became a polymorphic type and therefore has to be stored and passed around as a pointer. To avoid having all the callers check the validity of the pointer, I introduced the invariant that SupportFileSP is never null and always default constructed. However, without enforcement at the type level, that's fragile and indeed, we already identified two crashes where someone accidentally broke that invariant. This PR introduces a NonNullSharedPtr to prevent that. NonNullSharedPtr is a smart pointer wrapper around std::shared_ptr that guarantees the pointer is never null. If default-constructed, it creates a default-constructed instance of the contained type. Note that I'm using private inheritance because you shouldn't inherit from standard library classes due to the lack of virtual destructor. So while the new abstraction looks like a `std::shared_ptr`, it is in fact **not** a shared pointer. Given that our destructor is trivial, we could use public inheritance, but currently there's no need for it. rdar://164989579 (cherry picked from commit 06eac9feb92cba1d24e8a674c643aae1200d2bc8) --- lldb/include/lldb/Core/SourceManager.h | 40 ++++----- lldb/include/lldb/Symbol/CompileUnit.h | 12 +-- lldb/include/lldb/Symbol/Function.h | 4 +- lldb/include/lldb/Symbol/LineEntry.h | 4 +- lldb/include/lldb/Utility/FileSpecList.h | 2 +- lldb/include/lldb/Utility/NonNullSharedPtr.h | 80 ++++++++++++++++++ lldb/include/lldb/Utility/SupportFile.h | 3 + lldb/include/lldb/lldb-forward.h | 1 - .../Breakpoint/BreakpointResolverFileLine.cpp | 2 +- .../Commands/CommandObjectBreakpoint.cpp | 2 +- lldb/source/Commands/CommandObjectSource.cpp | 4 +- lldb/source/Core/Disassembler.cpp | 5 +- lldb/source/Core/SourceManager.cpp | 81 +++++++++---------- lldb/source/Expression/REPL.cpp | 2 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 4 +- lldb/source/Symbol/CompileUnit.cpp | 4 +- lldb/source/Symbol/Function.cpp | 6 +- lldb/source/Symbol/LineTable.cpp | 2 +- lldb/source/Target/StackFrame.cpp | 2 +- lldb/source/Target/ThreadPlanStepRange.cpp | 4 +- lldb/source/Utility/FileSpecList.cpp | 12 ++- lldb/unittests/Symbol/LineTableTest.cpp | 10 ++- 22 files changed, 184 insertions(+), 102 deletions(-) create mode 100644 lldb/include/lldb/Utility/NonNullSharedPtr.h diff --git a/lldb/include/lldb/Core/SourceManager.h b/lldb/include/lldb/Core/SourceManager.h index 83dc74768733d..5a7b51528eb97 100644 --- a/lldb/include/lldb/Core/SourceManager.h +++ b/lldb/include/lldb/Core/SourceManager.h @@ -11,6 +11,7 @@ #include "lldb/Utility/Checksum.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/SupportFile.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-forward.h" @@ -38,8 +39,8 @@ class SourceManager { const SourceManager::File &rhs); public: - File(lldb::SupportFileSP support_file_sp, lldb::TargetSP target_sp); - File(lldb::SupportFileSP support_file_sp, lldb::DebuggerSP debugger_sp); + File(SupportFileNSP support_file_nsp, lldb::TargetSP target_sp); + File(SupportFileNSP support_file_nsp, lldb::DebuggerSP debugger_sp); bool ModificationTimeIsStale() const; bool PathRemappingIsStale() const; @@ -57,9 +58,9 @@ class SourceManager { bool LineIsValid(uint32_t line); - lldb::SupportFileSP GetSupportFile() const { - assert(m_support_file_sp && "SupportFileSP must always be valid"); - return m_support_file_sp; + SupportFileNSP GetSupportFile() const { + assert(m_support_file_nsp && "SupportFileNSP must always be valid"); + return m_support_file_nsp; } uint32_t GetSourceMapModificationID() const { return m_source_map_mod_id; } @@ -80,13 +81,13 @@ class SourceManager { protected: /// Set file and update modification time. - void SetSupportFile(lldb::SupportFileSP support_file_sp); + void SetSupportFile(SupportFileNSP support_file_nsp); bool CalculateLineOffsets(uint32_t line = UINT32_MAX); /// The support file. If the target has source mappings, this might be /// different from the original support file passed to the constructor. - lldb::SupportFileSP m_support_file_sp; + SupportFileNSP m_support_file_nsp; /// Keep track of the on-disk checksum. Checksum m_checksum; @@ -107,9 +108,9 @@ class SourceManager { lldb::TargetWP m_target_wp; private: - void CommonInitializer(lldb::SupportFileSP support_file_sp, + void CommonInitializer(SupportFileNSP support_file_nsp, lldb::TargetSP target_sp); - void CommonInitializerImpl(lldb::SupportFileSP support_file_sp, + void CommonInitializerImpl(SupportFileNSP support_file_nsp, lldb::TargetSP target_sp); }; @@ -156,13 +157,13 @@ class SourceManager { ~SourceManager(); - FileSP GetLastFile() { return GetFile(m_last_support_file_sp); } + FileSP GetLastFile() { return GetFile(m_last_support_file_nsp); } bool AtLastLine(bool reverse) { return m_last_line == UINT32_MAX || (reverse && m_last_line == 1); } size_t DisplaySourceLinesWithLineNumbers( - lldb::SupportFileSP support_file_sp, uint32_t line, uint32_t column, + SupportFileNSP support_file_nsp, uint32_t line, uint32_t column, uint32_t context_before, uint32_t context_after, const char *current_line_cstr, Stream *s, const SymbolContextList *bp_locs = nullptr); @@ -176,31 +177,30 @@ class SourceManager { size_t DisplayMoreWithLineNumbers(Stream *s, uint32_t count, bool reverse, const SymbolContextList *bp_locs = nullptr); - bool SetDefaultFileAndLine(lldb::SupportFileSP support_file_sp, - uint32_t line); + bool SetDefaultFileAndLine(SupportFileNSP support_file_nsp, uint32_t line); struct SupportFileAndLine { - lldb::SupportFileSP support_file_sp; + SupportFileNSP support_file_nsp; uint32_t line; - SupportFileAndLine(lldb::SupportFileSP support_file_sp, uint32_t line) - : support_file_sp(support_file_sp), line(line) {} + SupportFileAndLine(SupportFileNSP support_file_nsp, uint32_t line) + : support_file_nsp(support_file_nsp), line(line) {} }; std::optional GetDefaultFileAndLine(); bool DefaultFileAndLineSet() { - return (GetFile(m_last_support_file_sp).get() != nullptr); + return (GetFile(m_last_support_file_nsp).get() != nullptr); } - void FindLinesMatchingRegex(lldb::SupportFileSP support_file_sp, + void FindLinesMatchingRegex(SupportFileNSP support_file_nsp, RegularExpression ®ex, uint32_t start_line, uint32_t end_line, std::vector &match_lines); - FileSP GetFile(lldb::SupportFileSP support_file_sp); + FileSP GetFile(SupportFileNSP support_file_nsp); protected: - lldb::SupportFileSP m_last_support_file_sp; + SupportFileNSP m_last_support_file_nsp; uint32_t m_last_line; uint32_t m_last_count; bool m_default_set; diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h index c5bb080d21184..bb9594699df33 100644 --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -93,7 +93,7 @@ class CompileUnit : public std::enable_shared_from_this, /// \param[in] user_data /// User data where the SymbolFile parser can store data. /// - /// \param[in] support_file_sp + /// \param[in] support_file_nsp /// The file specification for the source file of this compile /// unit. /// @@ -118,7 +118,7 @@ class CompileUnit : public std::enable_shared_from_this, /// An rvalue list of already parsed support files. /// \see lldb::LanguageType CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, - lldb::SupportFileSP support_file_sp, lldb::user_id_t uid, + SupportFileNSP support_file_nsp, lldb::user_id_t uid, lldb::LanguageType language, lldb_private::LazyBool is_optimized, SupportFileList &&support_files = {}); @@ -230,12 +230,12 @@ class CompileUnit : public std::enable_shared_from_this, /// Return the primary source spec associated with this compile unit. const FileSpec &GetPrimaryFile() const { - return m_primary_support_file_sp->GetSpecOnly(); + return m_primary_support_file_nsp->GetSpecOnly(); } /// Return the primary source file associated with this compile unit. - lldb::SupportFileSP GetPrimarySupportFile() const { - return m_primary_support_file_sp; + SupportFileNSP GetPrimarySupportFile() const { + return m_primary_support_file_nsp; } /// Get the line table for the compile unit. @@ -430,7 +430,7 @@ class CompileUnit : public std::enable_shared_from_this, /// compile unit. std::vector m_imported_modules; /// The primary file associated with this compile unit. - lldb::SupportFileSP m_primary_support_file_sp; + SupportFileNSP m_primary_support_file_nsp; /// Files associated with this compile unit's line table and declarations. SupportFileList m_support_files; /// Line table that will get parsed on demand. diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h index 3d3fc038cdbdd..9ddfe4b3340cb 100644 --- a/lldb/include/lldb/Symbol/Function.h +++ b/lldb/include/lldb/Symbol/Function.h @@ -473,12 +473,12 @@ class Function : public UserID, public SymbolContextScope { /// /// \param[out] line_no /// The line number. - void GetStartLineSourceInfo(lldb::SupportFileSP &source_file_sp, + void GetStartLineSourceInfo(SupportFileNSP &source_file_sp, uint32_t &line_no); using SourceRange = Range; /// Find the file and line number range of the function. - llvm::Expected> GetSourceInfo(); + llvm::Expected> GetSourceInfo(); /// Get the outgoing call edges from this function, sorted by their return /// PC addresses (in increasing order). diff --git a/lldb/include/lldb/Symbol/LineEntry.h b/lldb/include/lldb/Symbol/LineEntry.h index 8da59cf0bd24a..a61b72f253dd7 100644 --- a/lldb/include/lldb/Symbol/LineEntry.h +++ b/lldb/include/lldb/Symbol/LineEntry.h @@ -137,10 +137,10 @@ struct LineEntry { AddressRange range; /// The source file, possibly mapped by the target.source-map setting. - lldb::SupportFileSP file_sp; + SupportFileNSP file_sp; /// The original source file, from debug info. - lldb::SupportFileSP original_file_sp; + SupportFileNSP original_file_sp; /// The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line /// number information. diff --git a/lldb/include/lldb/Utility/FileSpecList.h b/lldb/include/lldb/Utility/FileSpecList.h index d091a9246e082..b565c2ab7f762 100644 --- a/lldb/include/lldb/Utility/FileSpecList.h +++ b/lldb/include/lldb/Utility/FileSpecList.h @@ -41,7 +41,7 @@ class SupportFileList { bool AppendIfUnique(const FileSpec &file); size_t GetSize() const { return m_files.size(); } const FileSpec &GetFileSpecAtIndex(size_t idx) const; - lldb::SupportFileSP GetSupportFileAtIndex(size_t idx) const; + SupportFileNSP GetSupportFileAtIndex(size_t idx) const; size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const; /// Find a compatible file index. /// diff --git a/lldb/include/lldb/Utility/NonNullSharedPtr.h b/lldb/include/lldb/Utility/NonNullSharedPtr.h new file mode 100644 index 0000000000000..7e12ce72c6238 --- /dev/null +++ b/lldb/include/lldb/Utility/NonNullSharedPtr.h @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_NONNULLSHAREDPTR_H +#define LLDB_UTILITY_NONNULLSHAREDPTR_H + +#include +#include + +namespace lldb_private { + +/// A non-nullable shared pointer that always holds a valid object. +/// +/// NonNullSharedPtr is a smart pointer wrapper around std::shared_ptr that +/// guarantees the pointer is never null. +/// +/// This class is used for enforcing invariants at the type level and +/// eliminating entire classes of null pointer bugs. +/// +/// @tparam T The type of object to manage. Must be default-constructible. +template class NonNullSharedPtr : private std::shared_ptr { + using Base = std::shared_ptr; + +public: + NonNullSharedPtr(const std::shared_ptr &t) + : Base(t ? t : std::make_shared()) { + assert(t && "NonNullSharedPtr initialized from NULL shared_ptr"); + } + + NonNullSharedPtr(std::shared_ptr &&t) + : Base(t ? std::move(t) : std::make_shared()) { + // Can't assert on t as it's been moved-from. + } + + NonNullSharedPtr(const NonNullSharedPtr &other) : Base(other) {} + + NonNullSharedPtr(NonNullSharedPtr &&other) : Base(std::move(other)) {} + + NonNullSharedPtr &operator=(const NonNullSharedPtr &other) { + Base::operator=(other); + return *this; + } + + NonNullSharedPtr &operator=(NonNullSharedPtr &&other) { + Base::operator=(std::move(other)); + return *this; + } + + using Base::operator*; + using Base::operator->; + using Base::get; + using Base::unique; + using Base::use_count; + using Base::operator bool; + + void swap(NonNullSharedPtr &other) { Base::swap(other); } + + /// Explicitly deleted operations that could introduce nullptr. + /// @{ + void reset() = delete; + void reset(T *ptr) = delete; + /// @} +}; + +} // namespace lldb_private + +/// Specialized swap function for NonNullSharedPtr to enable argument-dependent +/// lookup (ADL) and efficient swapping. +template +void swap(lldb_private::NonNullSharedPtr &lhs, + lldb_private::NonNullSharedPtr &rhs) { + lhs.swap(rhs); +} + +#endif diff --git a/lldb/include/lldb/Utility/SupportFile.h b/lldb/include/lldb/Utility/SupportFile.h index c389edf0e9f12..edc327dfd9010 100644 --- a/lldb/include/lldb/Utility/SupportFile.h +++ b/lldb/include/lldb/Utility/SupportFile.h @@ -11,6 +11,7 @@ #include "lldb/Utility/Checksum.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/NonNullSharedPtr.h" namespace lldb_private { @@ -76,6 +77,8 @@ class SupportFile { const Checksum m_checksum; }; +typedef NonNullSharedPtr SupportFileNSP; + } // namespace lldb_private #endif // LLDB_UTILITY_SUPPORTFILE_H diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index af5656b3dcad1..cea75d71c23e8 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -487,7 +487,6 @@ typedef std::shared_ptr TypeSummaryImplSP; typedef std::shared_ptr TypeSummaryOptionsSP; typedef std::shared_ptr ScriptedSyntheticChildrenSP; -typedef std::shared_ptr SupportFileSP; typedef std::shared_ptr UnixSignalsSP; typedef std::weak_ptr UnixSignalsWP; typedef std::shared_ptr UnwindAssemblySP; diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp index a94e9e23163d3..cef1ef1b08fe0 100644 --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -139,7 +139,7 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) { if (!sc.block) continue; - SupportFileSP file_sp; + SupportFileNSP file_sp = std::make_shared(); uint32_t line; const Block *inline_block = sc.block->GetContainingInlinedBlock(); if (inline_block) { diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index c3ba36696a867..5461a2bb720b8 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -800,7 +800,7 @@ class CommandObjectBreakpointSet : public CommandObjectParsed { // frame's file. if (auto maybe_file_and_line = target.GetSourceManager().GetDefaultFileAndLine()) { - file = maybe_file_and_line->support_file_sp->GetSpecOnly(); + file = maybe_file_and_line->support_file_nsp->GetSpecOnly(); return true; } diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index 7e7d3f065b622..e7bbe2541ffbe 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -777,7 +777,7 @@ class CommandObjectSourceList : public CommandObjectParsed { if (sc.function) { Target &target = GetTarget(); - SupportFileSP start_file = std::make_shared(); + SupportFileNSP start_file = std::make_shared(); uint32_t start_line; uint32_t end_line; FileSpec end_file; @@ -1194,7 +1194,7 @@ class CommandObjectSourceList : public CommandObjectParsed { // file(s) will be found and assigned to // sc.comp_unit->GetPrimarySupportFile, which is NOT what we want to // print. Instead, we want to print the one from the line entry. - lldb::SupportFileSP found_file_sp = sc.line_entry.file_sp; + SupportFileNSP found_file_sp = sc.line_entry.file_sp; target.GetSourceManager().DisplaySourceLinesWithLineNumbers( found_file_sp, m_options.start_line, column, 0, diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index e0a7d69345706..1c2bad0e60b8d 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -202,7 +202,7 @@ Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { return {}; LineEntry prologue_end_line = sc.line_entry; - SupportFileSP func_decl_file_sp; + SupportFileNSP func_decl_file_sp = std::make_shared(); uint32_t func_decl_line; sc.function->GetStartLineSourceInfo(func_decl_file_sp, func_decl_line); @@ -411,7 +411,8 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, LineEntry prologue_end_line = sc.line_entry; if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, prologue_end_line)) { - SupportFileSP func_decl_file_sp; + SupportFileNSP func_decl_file_sp = + std::make_shared(); uint32_t func_decl_line; sc.function->GetStartLineSourceInfo(func_decl_file_sp, func_decl_line); diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp index ca9eb040c4e4c..a4e77b43e5626 100644 --- a/lldb/source/Core/SourceManager.cpp +++ b/lldb/source/Core/SourceManager.cpp @@ -30,6 +30,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include "lldb/Utility/SupportFile.h" #include "lldb/lldb-enumerations.h" #include "llvm/ADT/Twine.h" @@ -69,22 +70,20 @@ static std::string toString(const Checksum &checksum) { // SourceManager constructor SourceManager::SourceManager(const TargetSP &target_sp) - : m_last_support_file_sp(std::make_shared()), m_last_line(0), + : m_last_support_file_nsp(std::make_shared()), m_last_line(0), m_last_count(0), m_default_set(false), m_target_wp(target_sp), m_debugger_wp(target_sp->GetDebugger().shared_from_this()) {} SourceManager::SourceManager(const DebuggerSP &debugger_sp) - : m_last_support_file_sp(std::make_shared()), m_last_line(0), + : m_last_support_file_nsp(std::make_shared()), m_last_line(0), m_last_count(0), m_default_set(false), m_target_wp(), m_debugger_wp(debugger_sp) {} // Destructor SourceManager::~SourceManager() = default; -SourceManager::FileSP SourceManager::GetFile(SupportFileSP support_file_sp) { - assert(support_file_sp && "SupportFileSP must be valid"); - - FileSpec file_spec = support_file_sp->GetSpecOnly(); +SourceManager::FileSP SourceManager::GetFile(SupportFileNSP support_file_nsp) { + FileSpec file_spec = support_file_nsp->GetSpecOnly(); if (!file_spec) return {}; @@ -97,8 +96,8 @@ SourceManager::FileSP SourceManager::GetFile(SupportFileSP support_file_sp) { LLDB_LOG(log, "Source file caching disabled: creating new source file: {0}", file_spec); if (target_sp) - return std::make_shared(support_file_sp, target_sp); - return std::make_shared(support_file_sp, debugger_sp); + return std::make_shared(support_file_nsp, target_sp); + return std::make_shared(support_file_nsp, debugger_sp); } ProcessSP process_sp = target_sp ? target_sp->GetProcessSP() : ProcessSP(); @@ -159,9 +158,9 @@ SourceManager::FileSP SourceManager::GetFile(SupportFileSP support_file_sp) { // (Re)create the file. if (target_sp) - file_sp = std::make_shared(support_file_sp, target_sp); + file_sp = std::make_shared(support_file_nsp, target_sp); else - file_sp = std::make_shared(support_file_sp, debugger_sp); + file_sp = std::make_shared(support_file_nsp, debugger_sp); // Add the file to the debugger and process cache. If the file was // invalidated, this will overwrite it. @@ -325,12 +324,12 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile( } size_t SourceManager::DisplaySourceLinesWithLineNumbers( - lldb::SupportFileSP support_file_sp, uint32_t line, uint32_t column, + SupportFileNSP support_file_nsp, uint32_t line, uint32_t column, uint32_t context_before, uint32_t context_after, const char *current_line_cstr, Stream *s, const SymbolContextList *bp_locs) { - assert(support_file_sp && "SupportFile must be valid"); - FileSP file_sp(GetFile(support_file_sp)); + assert(support_file_nsp && "SupportFile must be valid"); + FileSP file_sp(GetFile(support_file_nsp)); uint32_t start_line; uint32_t count = context_before + context_after + 1; @@ -343,7 +342,7 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbers( if (last_file_sp.get() != file_sp.get()) { if (line == 0) m_last_line = 0; - m_last_support_file_sp = support_file_sp; + m_last_support_file_nsp = support_file_nsp; } return DisplaySourceLinesWithLineNumbersUsingLastFile( @@ -389,15 +388,15 @@ size_t SourceManager::DisplayMoreWithLineNumbers( return 0; } -bool SourceManager::SetDefaultFileAndLine(lldb::SupportFileSP support_file_sp, +bool SourceManager::SetDefaultFileAndLine(SupportFileNSP support_file_nsp, uint32_t line) { - assert(support_file_sp && "SupportFile must be valid"); + assert(support_file_nsp && "SupportFile must be valid"); m_default_set = true; - if (FileSP file_sp = GetFile(support_file_sp)) { + if (FileSP file_sp = GetFile(support_file_nsp)) { m_last_line = line; - m_last_support_file_sp = support_file_sp; + m_last_support_file_nsp = support_file_nsp; return true; } @@ -461,7 +460,7 @@ static lldb_private::LineEntry FindEntryPoint(Module *exe_module) { std::optional SourceManager::GetDefaultFileAndLine() { if (FileSP last_file_sp = GetLastFile()) - return SupportFileAndLine(m_last_support_file_sp, m_last_line); + return SupportFileAndLine(m_last_support_file_nsp, m_last_line); if (!m_default_set) { TargetSP target_sp(m_target_wp.lock()); @@ -510,36 +509,36 @@ SourceManager::GetDefaultFileAndLine() { return std::nullopt; } -void SourceManager::FindLinesMatchingRegex(SupportFileSP support_file_sp, +void SourceManager::FindLinesMatchingRegex(SupportFileNSP support_file_nsp, RegularExpression ®ex, uint32_t start_line, uint32_t end_line, std::vector &match_lines) { match_lines.clear(); - FileSP file_sp = GetFile(support_file_sp); + FileSP file_sp = GetFile(support_file_nsp); if (!file_sp) return; return file_sp->FindLinesMatchingRegex(regex, start_line, end_line, match_lines); } -SourceManager::File::File(SupportFileSP support_file_sp, +SourceManager::File::File(SupportFileNSP support_file_nsp, lldb::DebuggerSP debugger_sp) - : m_support_file_sp(std::make_shared()), m_checksum(), + : m_support_file_nsp(std::make_shared()), m_checksum(), m_mod_time(), m_debugger_wp(debugger_sp), m_target_wp(TargetSP()) { - CommonInitializer(support_file_sp, {}); + CommonInitializer(support_file_nsp, {}); } -SourceManager::File::File(SupportFileSP support_file_sp, TargetSP target_sp) - : m_support_file_sp(std::make_shared()), m_checksum(), +SourceManager::File::File(SupportFileNSP support_file_nsp, TargetSP target_sp) + : m_support_file_nsp(std::make_shared()), m_checksum(), m_mod_time(), m_debugger_wp(target_sp ? target_sp->GetDebugger().shared_from_this() : DebuggerSP()), m_target_wp(target_sp) { - CommonInitializer(support_file_sp, target_sp); + CommonInitializer(support_file_nsp, target_sp); } -void SourceManager::File::CommonInitializer(SupportFileSP support_file_sp, +void SourceManager::File::CommonInitializer(SupportFileNSP support_file_nsp, TargetSP target_sp) { // It might take a while to read a source file, for example because it's // coming from a virtual file system that's fetching the data on demand. When @@ -548,23 +547,23 @@ void SourceManager::File::CommonInitializer(SupportFileSP support_file_sp, static constexpr auto g_progress_delay = std::chrono::milliseconds(500); std::future future = std::async(std::launch::async, [=]() { - CommonInitializerImpl(support_file_sp, target_sp); + CommonInitializerImpl(support_file_nsp, target_sp); }); std::optional progress; if (future.wait_for(g_progress_delay) == std::future_status::timeout) { Debugger *debugger = target_sp ? &target_sp->GetDebugger() : nullptr; progress.emplace("Loading source file", - support_file_sp->GetSpecOnly().GetFilename().GetString(), + support_file_nsp->GetSpecOnly().GetFilename().GetString(), 1, debugger); } future.wait(); } -void SourceManager::File::CommonInitializerImpl(SupportFileSP support_file_sp, +void SourceManager::File::CommonInitializerImpl(SupportFileNSP support_file_nsp, TargetSP target_sp) { // Set the file and update the modification time. - SetSupportFile(support_file_sp); + SetSupportFile(support_file_nsp); // Always update the source map modification ID if we have a target. if (target_sp) @@ -575,7 +574,7 @@ void SourceManager::File::CommonInitializerImpl(SupportFileSP support_file_sp, if (target_sp) { // If this is just a file name, try finding it in the target. { - FileSpec file_spec = support_file_sp->GetSpecOnly(); + FileSpec file_spec = support_file_nsp->GetSpecOnly(); if (!file_spec.GetDirectory() && file_spec.GetFilename()) { bool check_inlines = false; SymbolContextList sc_list; @@ -612,7 +611,7 @@ void SourceManager::File::CommonInitializerImpl(SupportFileSP support_file_sp, // Try remapping the file if it doesn't exist. { - FileSpec file_spec = support_file_sp->GetSpecOnly(); + FileSpec file_spec = support_file_nsp->GetSpecOnly(); if (!FileSystem::Instance().Exists(file_spec)) { // Check target specific source remappings (i.e., the // target.source-map setting), then fall back to the module @@ -625,7 +624,7 @@ void SourceManager::File::CommonInitializerImpl(SupportFileSP support_file_sp, } if (remapped) SetSupportFile(std::make_shared( - *remapped, support_file_sp->GetChecksum())); + *remapped, support_file_nsp->GetChecksum())); } } } @@ -634,16 +633,16 @@ void SourceManager::File::CommonInitializerImpl(SupportFileSP support_file_sp, // If the file exists, read in the data. if (m_mod_time != llvm::sys::TimePoint<>()) { m_data_sp = FileSystem::Instance().CreateDataBuffer( - m_support_file_sp->GetSpecOnly()); + m_support_file_nsp->GetSpecOnly()); m_checksum = llvm::MD5::hash(m_data_sp->GetData()); } } -void SourceManager::File::SetSupportFile(lldb::SupportFileSP support_file_sp) { - FileSpec file_spec = support_file_sp->GetSpecOnly(); +void SourceManager::File::SetSupportFile(SupportFileNSP support_file_nsp) { + FileSpec file_spec = support_file_nsp->GetSpecOnly(); resolve_tilde(file_spec); - m_support_file_sp = - std::make_shared(file_spec, support_file_sp->GetChecksum()); + m_support_file_nsp = + std::make_shared(file_spec, support_file_nsp->GetChecksum()); m_mod_time = FileSystem::Instance().GetModificationTime(file_spec); } @@ -718,7 +717,7 @@ bool SourceManager::File::ModificationTimeIsStale() const { // source cache and only update when we determine a file has been updated. // For now we check each time we want to display info for the file. auto curr_mod_time = FileSystem::Instance().GetModificationTime( - m_support_file_sp->GetSpecOnly()); + m_support_file_nsp->GetSpecOnly()); return curr_mod_time != llvm::sys::TimePoint<>() && m_mod_time != curr_mod_time; } diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp index 8d918f415ac16..bf75f29ad5046 100644 --- a/lldb/source/Expression/REPL.cpp +++ b/lldb/source/Expression/REPL.cpp @@ -654,6 +654,6 @@ Status REPL::RunLoop() { // Restore the default file and line if (default_file_line) m_target.GetSourceManager().SetDefaultFileAndLine( - default_file_line->support_file_sp, default_file_line->line); + default_file_line->support_file_nsp, default_file_line->line); return error; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 011aa1d8b593c..adf8bd00b776b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -795,12 +795,12 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { } else { ModuleSP module_sp(m_objfile_sp->GetModule()); if (module_sp) { - auto initialize_cu = [&](lldb::SupportFileSP support_file_sp, + auto initialize_cu = [&](SupportFileNSP support_file_nsp, LanguageType cu_language, SupportFileList &&support_files = {}) { BuildCuTranslationTable(); cu_sp = std::make_shared( - module_sp, &dwarf_cu, support_file_sp, + module_sp, &dwarf_cu, support_file_nsp, *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language, eLazyBoolCalculate, std::move(support_files)); diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index 166f111ef6220..703ef131ad6bf 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -27,14 +27,14 @@ CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, language, is_optimized) {} CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, - lldb::SupportFileSP support_file_sp, + SupportFileNSP support_file_nsp, const lldb::user_id_t cu_sym_id, lldb::LanguageType language, 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_primary_support_file_sp(support_file_sp), + m_primary_support_file_nsp(support_file_nsp), m_support_files(std::move(support_files)), m_is_optimized(is_optimized) { if (language != eLanguageTypeUnknown) m_flags.Set(flagsParsedLanguage); diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 368f370a1d90d..81792fb37d224 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -277,7 +277,7 @@ Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, Function::~Function() = default; -void Function::GetStartLineSourceInfo(SupportFileSP &source_file_sp, +void Function::GetStartLineSourceInfo(SupportFileNSP &source_file_sp, uint32_t &line_no) { line_no = 0; source_file_sp = std::make_shared(); @@ -305,9 +305,9 @@ void Function::GetStartLineSourceInfo(SupportFileSP &source_file_sp, } } -llvm::Expected> +llvm::Expected> Function::GetSourceInfo() { - SupportFileSP source_file_sp; + SupportFileNSP source_file_sp = std::make_shared(); uint32_t start_line; GetStartLineSourceInfo(source_file_sp, start_line); LineTable *line_table = m_comp_unit->GetLineTable(); diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index ca3accd6894a7..ae2abf5befb48 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -327,7 +327,7 @@ void LineTable::Dump(Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges) { const size_t count = m_entries.size(); LineEntry line_entry; - SupportFileSP prev_file; + SupportFileNSP prev_file = std::make_shared(); for (size_t idx = 0; idx < count; ++idx) { ConvertEntryAtIndexToLineEntry(idx, line_entry); line_entry.Dump(s, target, !prev_file->Equal(*line_entry.original_file_sp), diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 5b328dd97baa0..0707ce804b2fb 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -2111,7 +2111,7 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, if (m_sc.comp_unit && m_sc.line_entry.IsValid()) { have_debuginfo = true; if (source_lines_before > 0 || source_lines_after > 0) { - SupportFileSP source_file_sp = m_sc.line_entry.file_sp; + SupportFileNSP source_file_sp = m_sc.line_entry.file_sp; uint32_t start_line = m_sc.line_entry.line; if (!start_line && m_sc.function) { m_sc.function->GetStartLineSourceInfo(source_file_sp, start_line); diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 2c074a6300819..f64c17778a4ab 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -431,10 +431,10 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() { top_most_line_entry.original_file_sp.reset( new SupportFile(call_site_file_spec)); top_most_line_entry.range = range; - top_most_line_entry.file_sp.reset(); + top_most_line_entry.file_sp = std::make_shared(); top_most_line_entry.ApplyFileMappings( GetThread().CalculateTarget()); - if (!top_most_line_entry.file_sp) + if (!top_most_line_entry.file_sp->GetSpecOnly()) top_most_line_entry.file_sp = top_most_line_entry.original_file_sp; } diff --git a/lldb/source/Utility/FileSpecList.cpp b/lldb/source/Utility/FileSpecList.cpp index 5852367f77827..8aa0820bd78d0 100644 --- a/lldb/source/Utility/FileSpecList.cpp +++ b/lldb/source/Utility/FileSpecList.cpp @@ -45,10 +45,9 @@ bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) { // 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::shared_ptr &support_file) { - return support_file->GetSpecOnly() == file_spec; - }) == end) { + if (find_if(m_files.begin(), end, [&](const SupportFileNSP &support_file) { + return support_file->GetSpecOnly() == file_spec; + }) == end) { Append(file_spec); return true; } @@ -214,11 +213,10 @@ const FileSpec &SupportFileList::GetFileSpecAtIndex(size_t idx) const { return g_empty_file_spec; } -std::shared_ptr -SupportFileList::GetSupportFileAtIndex(size_t idx) const { +SupportFileNSP SupportFileList::GetSupportFileAtIndex(size_t idx) const { if (idx < m_files.size()) return m_files[idx]; - return {}; + return std::make_shared(); } // Return the size in bytes that this object takes in memory. This returns the diff --git a/lldb/unittests/Symbol/LineTableTest.cpp b/lldb/unittests/Symbol/LineTableTest.cpp index eadab40a37fac..ca63c6ff51dad 100644 --- a/lldb/unittests/Symbol/LineTableTest.cpp +++ b/lldb/unittests/Symbol/LineTableTest.cpp @@ -176,10 +176,12 @@ CreateFakeModule(std::vector line_sequences) { if (!text_sp) return createStringError("No .text"); - auto cu_up = std::make_unique(module_sp, /*user_data=*/nullptr, - /*support_file_sp=*/nullptr, - /*uid=*/0, eLanguageTypeC, - /*is_optimized=*/eLazyBoolNo); + auto cu_up = std::make_unique( + module_sp, + /*user_data=*/nullptr, + /*support_file_nsp=*/std::make_shared(), + /*uid=*/0, eLanguageTypeC, + /*is_optimized=*/eLazyBoolNo); LineTable *line_table = new LineTable(cu_up.get(), std::move(line_sequences)); cu_up->SetLineTable(line_table); cast(module_sp->GetSymbolFile())