llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) <details> <summary>Changes</summary> This fixes a data race between the main thread and the default event handler thread. The statusline format option value was protected by a mutex, but it was returned as a pointer, allowing one thread to access it while another was modifying it. Avoid the data race by returning format values by value instead of by pointer. --- Full diff: https://github.com/llvm/llvm-project/pull/142489.diff 9 Files Affected: - (modified) lldb/include/lldb/Core/Debugger.h (+6-6) - (modified) lldb/include/lldb/Interpreter/OptionValue.h (+3-3) - (modified) lldb/source/Core/Debugger.cpp (+19-21) - (modified) lldb/source/Core/Disassembler.cpp (+5-12) - (modified) lldb/source/Core/Statusline.cpp (+3-3) - (modified) lldb/source/Interpreter/OptionValue.cpp (+3-3) - (modified) lldb/source/Target/StackFrame.cpp (+2-2) - (modified) lldb/source/Target/Thread.cpp (+2-4) - (modified) lldb/source/Target/ThreadPlanTracer.cpp (+2-2) ``````````diff diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index c9e5310cded1a..d73aba1e3ce58 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -243,17 +243,17 @@ class Debugger : public std::enable_shared_from_this<Debugger>, bool GetAutoConfirm() const; - const FormatEntity::Entry *GetDisassemblyFormat() const; + FormatEntity::Entry GetDisassemblyFormat() const; - const FormatEntity::Entry *GetFrameFormat() const; + FormatEntity::Entry GetFrameFormat() const; - const FormatEntity::Entry *GetFrameFormatUnique() const; + FormatEntity::Entry GetFrameFormatUnique() const; uint64_t GetStopDisassemblyMaxSize() const; - const FormatEntity::Entry *GetThreadFormat() const; + FormatEntity::Entry GetThreadFormat() const; - const FormatEntity::Entry *GetThreadStopFormat() const; + FormatEntity::Entry GetThreadStopFormat() const; lldb::ScriptLanguage GetScriptLanguage() const; @@ -297,7 +297,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>, bool GetShowStatusline() const; - const FormatEntity::Entry *GetStatuslineFormat() const; + FormatEntity::Entry GetStatuslineFormat() const; bool SetStatuslineFormat(const FormatEntity::Entry &format); llvm::StringRef GetSeparator() const; diff --git a/lldb/include/lldb/Interpreter/OptionValue.h b/lldb/include/lldb/Interpreter/OptionValue.h index e3c139155b0ef..69f84419416c6 100644 --- a/lldb/include/lldb/Interpreter/OptionValue.h +++ b/lldb/include/lldb/Interpreter/OptionValue.h @@ -284,6 +284,8 @@ class OptionValue { return GetStringValue(); if constexpr (std::is_same_v<T, ArchSpec>) return GetArchSpecValue(); + if constexpr (std::is_same_v<T, FormatEntity::Entry>) + return GetFormatEntity(); if constexpr (std::is_enum_v<T>) if (std::optional<int64_t> value = GetEnumerationValue()) return static_cast<T>(*value); @@ -295,8 +297,6 @@ class OptionValue { typename std::remove_pointer<T>::type>::type, std::enable_if_t<std::is_pointer_v<T>, bool> = true> T GetValueAs() const { - if constexpr (std::is_same_v<U, FormatEntity::Entry>) - return GetFormatEntity(); if constexpr (std::is_same_v<U, RegularExpression>) return GetRegexValue(); return {}; @@ -382,7 +382,7 @@ class OptionValue { std::optional<UUID> GetUUIDValue() const; bool SetUUIDValue(const UUID &uuid); - const FormatEntity::Entry *GetFormatEntity() const; + FormatEntity::Entry GetFormatEntity() const; bool SetFormatEntityValue(const FormatEntity::Entry &entry); const RegularExpression *GetRegexValue() const; diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 519a2528ca7e0..112ef3572aa98 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -294,19 +294,19 @@ bool Debugger::GetAutoConfirm() const { idx, g_debugger_properties[idx].default_uint_value != 0); } -const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { +FormatEntity::Entry Debugger::GetDisassemblyFormat() const { constexpr uint32_t idx = ePropertyDisassemblyFormat; - return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); + return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {}); } -const FormatEntity::Entry *Debugger::GetFrameFormat() const { +FormatEntity::Entry Debugger::GetFrameFormat() const { constexpr uint32_t idx = ePropertyFrameFormat; - return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); + return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {}); } -const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { +FormatEntity::Entry Debugger::GetFrameFormatUnique() const { constexpr uint32_t idx = ePropertyFrameFormatUnique; - return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); + return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {}); } uint64_t Debugger::GetStopDisassemblyMaxSize() const { @@ -350,14 +350,14 @@ void Debugger::SetPrompt(llvm::StringRef p) { GetCommandInterpreter().UpdatePrompt(new_prompt); } -const FormatEntity::Entry *Debugger::GetThreadFormat() const { +FormatEntity::Entry Debugger::GetThreadFormat() const { constexpr uint32_t idx = ePropertyThreadFormat; - return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); + return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {}); } -const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { +FormatEntity::Entry Debugger::GetThreadStopFormat() const { constexpr uint32_t idx = ePropertyThreadStopFormat; - return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); + return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {}); } lldb::ScriptLanguage Debugger::GetScriptLanguage() const { @@ -492,9 +492,9 @@ bool Debugger::GetShowStatusline() const { idx, g_debugger_properties[idx].default_uint_value != 0); } -const FormatEntity::Entry *Debugger::GetStatuslineFormat() const { +FormatEntity::Entry Debugger::GetStatuslineFormat() const { constexpr uint32_t idx = ePropertyStatuslineFormat; - return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); + return GetPropertyAtIndexAs<FormatEntity::Entry>(idx, {}); } bool Debugger::SetStatuslineFormat(const FormatEntity::Entry &format) { @@ -1534,15 +1534,13 @@ bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, const ExecutionContext *exe_ctx, const Address *addr, Stream &s) { FormatEntity::Entry format_entry; + if (format) + format_entry = *format; + else if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) + format_entry = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + else + FormatEntity::Parse("${addr}: ", format_entry); - if (format == nullptr) { - if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) - format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); - if (format == nullptr) { - FormatEntity::Parse("${addr}: ", format_entry); - format = &format_entry; - } - } bool function_changed = false; bool initial_function = false; if (prev_sc && (prev_sc->function || prev_sc->symbol)) { @@ -1566,7 +1564,7 @@ bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) { initial_function = true; } - return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr, + return FormatEntity::Format(format_entry, s, sc, exe_ctx, addr, nullptr, function_changed, initial_function); } diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index dce3d59457c0e..7c1fc8fa1934d 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -307,14 +307,11 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = false; - const FormatEntity::Entry *disassembly_format = nullptr; FormatEntity::Entry format; if (exe_ctx.HasTargetScope()) { - disassembly_format = - exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); + format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); } else { FormatEntity::Parse("${addr}: ", format); - disassembly_format = &format; } // First pass: step through the list of instructions, find how long the @@ -342,8 +339,8 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); if (resolved_mask) { StreamString strmstr; - Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, - &exe_ctx, &addr, strmstr); + Debugger::FormatDisassemblerAddress(&format, &sc, nullptr, &exe_ctx, + &addr, strmstr); size_t cur_line = strmstr.GetSizeOfLastLine(); if (cur_line > address_text_size) address_text_size = cur_line; @@ -1034,14 +1031,11 @@ void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); collection::const_iterator pos, begin, end; - const FormatEntity::Entry *disassembly_format = nullptr; FormatEntity::Entry format; if (exe_ctx && exe_ctx->HasTargetScope()) { - disassembly_format = - exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); } else { FormatEntity::Parse("${addr}: ", format); - disassembly_format = &format; } for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; @@ -1049,8 +1043,7 @@ void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, if (pos != begin) s->EOL(); (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, - show_control_flow_kind, exe_ctx, nullptr, nullptr, - disassembly_format, 0); + show_control_flow_kind, exe_ctx, nullptr, nullptr, &format, 0); } } diff --git a/lldb/source/Core/Statusline.cpp b/lldb/source/Core/Statusline.cpp index 8b3c8d1ccfa80..4e6cc35033204 100644 --- a/lldb/source/Core/Statusline.cpp +++ b/lldb/source/Core/Statusline.cpp @@ -144,9 +144,9 @@ void Statusline::Redraw(bool update) { } StreamString stream; - if (auto *format = m_debugger.GetStatuslineFormat()) - FormatEntity::Format(*format, stream, &symbol_ctx, &exe_ctx, nullptr, - nullptr, false, false); + FormatEntity::Entry format = m_debugger.GetStatuslineFormat(); + FormatEntity::Format(format, stream, &symbol_ctx, &exe_ctx, nullptr, nullptr, + false, false); Draw(std::string(stream.GetString())); } diff --git a/lldb/source/Interpreter/OptionValue.cpp b/lldb/source/Interpreter/OptionValue.cpp index 28bc57a07ac71..245bc7c83e3f9 100644 --- a/lldb/source/Interpreter/OptionValue.cpp +++ b/lldb/source/Interpreter/OptionValue.cpp @@ -380,11 +380,11 @@ bool OptionValue::SetLanguageValue(lldb::LanguageType new_language) { return false; } -const FormatEntity::Entry *OptionValue::GetFormatEntity() const { +FormatEntity::Entry OptionValue::GetFormatEntity() const { std::lock_guard<std::mutex> lock(m_mutex); if (const OptionValueFormatEntity *option_value = GetAsFormatEntity()) - return &option_value->GetCurrentValue(); - return nullptr; + return option_value->GetCurrentValue(); + return {}; } const RegularExpression *OptionValue::GetRegexValue() const { diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index ab5cd0b27c789..fa041d11061ca 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1936,7 +1936,7 @@ void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, ExecutionContext exe_ctx(shared_from_this()); - const FormatEntity::Entry *frame_format = nullptr; + FormatEntity::Entry frame_format; Target *target = exe_ctx.GetTargetPtr(); if (target) { if (show_unique) { @@ -1945,7 +1945,7 @@ void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, frame_format = target->GetDebugger().GetFrameFormat(); } } - if (!DumpUsingFormat(*strm, frame_format, frame_marker)) { + if (!DumpUsingFormat(*strm, &frame_format, frame_marker)) { Dump(strm, true, false); strm->EOL(); } diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index b0e0f1e67c060..8840ba68e28e6 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -1667,15 +1667,13 @@ void Thread::DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, bool stop_format) { ExecutionContext exe_ctx(shared_from_this()); - const FormatEntity::Entry *thread_format; + FormatEntity::Entry thread_format; if (stop_format) thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadStopFormat(); else thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat(); - assert(thread_format); - - DumpUsingFormat(strm, frame_idx, thread_format); + DumpUsingFormat(strm, frame_idx, &thread_format); } void Thread::SettingsInitialize() {} diff --git a/lldb/source/Target/ThreadPlanTracer.cpp b/lldb/source/Target/ThreadPlanTracer.cpp index ab63cc7f6c223..c5a9c5b806c30 100644 --- a/lldb/source/Target/ThreadPlanTracer.cpp +++ b/lldb/source/Target/ThreadPlanTracer.cpp @@ -174,11 +174,11 @@ void ThreadPlanAssemblyTracer::Log() { const bool show_control_flow_kind = true; Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); - const FormatEntity::Entry *disassemble_format = + FormatEntity::Entry disassemble_format = m_process.GetTarget().GetDebugger().GetDisassemblyFormat(); instruction->Dump(stream_sp.get(), max_opcode_byte_size, show_address, show_bytes, show_control_flow_kind, nullptr, nullptr, - nullptr, disassemble_format, 0); + nullptr, &disassemble_format, 0); } } } `````````` </details> https://github.com/llvm/llvm-project/pull/142489 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits