[Lldb-commits] [lldb] [lldb] Synchronize the debugger's stdout and stderr streams (PR #126630)
JDevlieghere wrote: > That's okay. I thought it might not work out. Thanks for giving it a shot. > > I feel bad about bringing this up after you did all the work, but there is > one more thing going through my head. I now have a very awkward feeling about > this because it seems like this is solving mostly the same problem that > StreamAsynchronousIO (and Debugger::PrintAsync) was trying to solve. You > mentioned that in the first version of the patch and said that it doesn't > work in some cases, but it's not quite clear why is that the case. If the > motivation is status line, then it sounds like it _might_ be possible to > plumb the updates through the async streams. The async streams buffer until they're flushed (or more commonly destroyed) and they delegate to the IOHandler instead of writing directly to the debugger's output or error stream. The problem is that while the IOHandler can protect the write, as is the case for `IOHandlerEditline` using the output mutex, nothing prevents anyone else from writing directly to the output stream, not using the asynchronous handler. If everyone uses the asynchronous streams, and every IOHandler would protect the write using the same mutex, then we could achieve the same. But that really files like working around the issue rather than addressing it (i.e. protecting the underlying streams), which is what this patch does. > I can imagine that it might not work for some reason, but then I think it's > important to know why, and come up with some sort of an story for which of > the two systems should be used for a particular use case. Or, (I am dreaming, > I know) actually deprecate/remove the async IO system. Yes, with this patch protecting the underlying streams, I don't think we _need_ the asynchronous streams and most uses could be converted to lock the stream. That said, there are still uses cases that benefit from the buffering, like running the expressions. As you pointed out, we don't want to lock the streams for the duration of running the expression. But maybe we should rename them to "BufferedOutputStream" but still remove the `PrintAsync` stuff that delegates to the IO handlers. https://github.com/llvm/llvm-project/pull/126630 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
jimingham wrote: This looks fine. The one thing that we might want to also test is that if we step through the thunk, and then stop in some code that we don't want to stop in (i.e. the target of the thunk doesn't have debug information) we step back out correctly. This should work by composition, but thunks can be funny and harder to trace out of... I don't remember whether we had tests for this on the swift side, but it shouldn't be too hard to have the target of the thunk in a separate .cpp file, and strip that one. Then make sure we don't leave the user stranded there. https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/127206 >From 759f0569807d00a059a78aeb3bd1eddeffcbdf36 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 14 Feb 2025 11:43:20 + Subject: [PATCH 01/10] Init --- lldb/include/lldb/Symbol/CompilerType.h | 3 +- lldb/source/API/SBType.cpp| 8 +++- .../Language/CPlusPlus/GenericBitset.cpp | 2 +- .../Plugins/Language/CPlusPlus/LibCxxSpan.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 33 ++--- .../TypeSystem/Clang/TypeSystemClang.cpp | 47 +-- .../TestCppTemplateArguments.py | 31 ++-- .../API/lang/cpp/template-arguments/main.cpp | 6 +++ lldb/unittests/Symbol/TestTypeSystemClang.cpp | 42 - 9 files changed, 143 insertions(+), 31 deletions(-) diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 096a8f1ab68e8..f7e3e552f3e45 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -15,6 +15,7 @@ #include #include "lldb/lldb-private.h" +#include "clang/AST/APValue.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/Casting.h" @@ -544,7 +545,7 @@ bool operator==(const CompilerType &lhs, const CompilerType &rhs); bool operator!=(const CompilerType &lhs, const CompilerType &rhs); struct CompilerType::IntegralTemplateArgument { - llvm::APSInt value; + clang::APValue value; CompilerType type; }; diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index 6401d32c85795..72f590947dff6 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -697,6 +697,7 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, std::optional arg; const bool expand_pack = true; switch (GetTemplateArgumentKind(idx)) { + case eTemplateArgumentKindStructuralValue: case eTemplateArgumentKindIntegral: arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument( idx, expand_pack); @@ -708,7 +709,12 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, if (!arg) return {}; - Scalar value{arg->value}; + Scalar value; + if (arg->value.isFloat()) +value = arg->value.getFloat(); + else +value = arg->value.getInt(); + DataExtractor data; value.GetData(data); diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index 33955dccb6ccc..99ff975825c71 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -91,7 +91,7 @@ lldb::ChildCacheState GenericBitsetFrontEnd::Update() { size_t size = 0; if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) -size = arg->value.getLimitedValue(); +size = arg->value.getInt().getLimitedValue(); m_elements.assign(size, ValueObjectSP()); m_first = diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp index 15040295efe6d..687ef1739ad11 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp @@ -119,7 +119,7 @@ lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { } else if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { - m_num_elements = arg->value.getLimitedValue(); + m_num_elements = arg->value.getInt().getLimitedValue(); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ec0004c70c6da..70af283ab7443 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1973,6 +1973,27 @@ class DWARFASTParserClang::DelayedAddObjCClassProperty { ClangASTMetadata m_metadata; }; +static clang::APValue MakeAPValue(CompilerType clang_type, uint64_t bit_width, + uint64_t value) { + bool is_signed = false; + const bool is_integral = clang_type.IsIntegerOrEnumerationType(is_signed); + + llvm::APSInt apint(bit_width, !is_signed); + apint = value; + + if (is_integral) +return clang::APValue(apint); + + uint32_t count; + bool is_complex; + assert(clang_type.IsFloatingPointType(count, is_complex)); + + if (bit_width == 32) +return clang::APValue(llvm::APFloat(apint.bitsToFloat())); + + return clang::APValue(llvm::APFloat(apint.bitsToDouble())); +} + bool DWARFASTParserClang::ParseTemplateDIE( const DWARFDIE &die, TypeSystemClang::TemplateParameterInfos &template_param_infos) { @@ -2050,9 +2071,6 @@ bool DWARFASTParserClang::ParseTemplateDIE( clang_type = m_ast.GetBasicType(eBasicTypeVoid); if (!is_templ
[Lldb-commits] [lldb] [lldb][NFC] remove AdaptedConstIterator and AdaptedIterable (PR #127507)
https://github.com/JDevlieghere approved this pull request. I suspect the LLDB classes preceded their LLVM counterparts, but the latter are much more complete and there's definitely no point having both. LGTM. https://github.com/llvm/llvm-project/pull/127507 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][Mach-O] Read dyld_all_image_infos addr from `main bin spec` LC_NOTE (PR #127156)
@@ -5669,6 +5673,10 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo(addr_t &value, type = eBinaryTypeStandalone; typestr = "standalone"; break; + case 4: +type = eBinaryTypeUserAllImageInfos; +typestr = "userland dyld_all_image_infos"; +break; bulbazord wrote: If you do, it might be useful to add a log. If that situation were to happen, you'd see it in the logs immediately and know that either the core file looks unexpected or LLDB has a bug in core file handling. https://github.com/llvm/llvm-project/pull/127156 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] remove AdaptedConstIterator and AdaptedIterable (PR #127507)
https://github.com/dlav-sc updated https://github.com/llvm/llvm-project/pull/127507 >From 9ac7f03648a41e1ffbd17e11485fa7f717708c50 Mon Sep 17 00:00:00 2001 From: Daniil Avdeev Date: Wed, 5 Feb 2025 13:20:24 + Subject: [PATCH] [lldb][NFC] remove AdaptedConstIterator and AdaptedIterable AdaptedConstIterator currently doesn't have iterator traits, so I can't use STL algorithms with containers like WatchpointList. This patch replaces AdaptedConstIterator and AdaptedIterable with llvm::iterator_adaped_base and llvm::iterator_range respectively. --- lldb/include/lldb/Breakpoint/BreakpointList.h | 3 +- .../Breakpoint/BreakpointLocationCollection.h | 3 +- .../lldb/Breakpoint/BreakpointLocationList.h | 3 +- lldb/include/lldb/Breakpoint/WatchpointList.h | 3 +- .../lldb/Breakpoint/WatchpointResource.h | 3 +- lldb/include/lldb/Core/ModuleList.h | 5 +- lldb/include/lldb/Core/ModuleSpec.h | 3 +- .../lldb/Host/common/NativeProcessProtocol.h | 10 +- lldb/include/lldb/Symbol/SymbolContext.h | 2 +- lldb/include/lldb/Symbol/TypeList.h | 3 +- lldb/include/lldb/Symbol/TypeMap.h| 3 +- lldb/include/lldb/Target/QueueList.h | 4 +- lldb/include/lldb/Target/TargetList.h | 3 +- lldb/include/lldb/Target/ThreadCollection.h | 3 +- lldb/include/lldb/Utility/Iterable.h | 175 ++ 15 files changed, 38 insertions(+), 188 deletions(-) diff --git a/lldb/include/lldb/Breakpoint/BreakpointList.h b/lldb/include/lldb/Breakpoint/BreakpointList.h index a7399d385f6f0..4a921fadfc066 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointList.h @@ -163,8 +163,7 @@ class BreakpointList { bool m_is_internal; public: - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable BreakpointIterable; BreakpointIterable Breakpoints() { return BreakpointIterable(m_breakpoints, GetMutex()); diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h index 34bd309864871..3aef1d658c0e5 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h @@ -165,8 +165,7 @@ class BreakpointLocationCollection { mutable std::mutex m_collection_mutex; public: - typedef AdaptedIterable + typedef llvm::iterator_range BreakpointLocationCollectionIterable; BreakpointLocationCollectionIterable BreakpointLocations() { return BreakpointLocationCollectionIterable(m_break_loc_collection); diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h index f76a8fcfdd7e7..17dc0bfe03148 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h @@ -204,8 +204,7 @@ class BreakpointLocationList { BreakpointLocationCollection *m_new_location_recorder; public: - typedef AdaptedIterable + typedef llvm::iterator_range BreakpointLocationIterable; BreakpointLocationIterable BreakpointLocations() { diff --git a/lldb/include/lldb/Breakpoint/WatchpointList.h b/lldb/include/lldb/Breakpoint/WatchpointList.h index bf87495d79dba..d037d36e64290 100644 --- a/lldb/include/lldb/Breakpoint/WatchpointList.h +++ b/lldb/include/lldb/Breakpoint/WatchpointList.h @@ -39,8 +39,7 @@ class WatchpointList { ~WatchpointList(); typedef std::list wp_collection; - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable WatchpointIterable; /// Add a Watchpoint to the list. diff --git a/lldb/include/lldb/Breakpoint/WatchpointResource.h b/lldb/include/lldb/Breakpoint/WatchpointResource.h index 070d84cff8f26..c1a81fc486eb6 100644 --- a/lldb/include/lldb/Breakpoint/WatchpointResource.h +++ b/lldb/include/lldb/Breakpoint/WatchpointResource.h @@ -39,8 +39,7 @@ class WatchpointResource void SetType(bool read, bool write); typedef std::vector WatchpointCollection; - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable WatchpointIterable; /// Iterate over the watchpoint constituents for this resource diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 43d931a844740..29b87de88520d 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -521,14 +521,13 @@ class ModuleList { Notifier *m_notifier = nullptr; public: - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable ModuleIterable; ModuleIterable Modules() const { return ModuleIterable(m_modules, GetMutex()); } - typedef AdaptedIterable + typedef llvm::iterator_range ModuleIterableNoLocking; ModuleIterableNoLocking ModulesNoLocking() const { return ModuleIterableNoLocking(m_modules); diff --git a/lldb/include/lldb/Core/ModuleSpec.h b/lldb
[Lldb-commits] [lldb] [lldb] fix software breakpoint removing in multithreaded process while stepping (PR #127506)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: None (dlav-sc) Changes I have encountered with the issue that sometimes lldb-server can't remove internal software breakpoints in a multithread process and as a result the process freezes. The source of the issue was that lldb-server tried to read/write memory of the process using a tid of the exited thread and received 'No such process' error from ptrace. This patch sets an existing thread as the current one for this process before software breakpoints removing. --- Full diff: https://github.com/llvm/llvm-project/pull/127506.diff 1 Files Affected: - (modified) lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp (+1-1) ``diff diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 7f2aba0e4eb2c..fe16ec73c0404 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1959,6 +1959,7 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() { // Clear any temporary breakpoints we used to implement software single // stepping. + SetCurrentThreadID(m_pending_notification_tid); for (const auto &thread_info : m_threads_stepping_with_breakpoint) { Status error = RemoveBreakpoint(thread_info.second); if (error.Fail()) @@ -1968,7 +1969,6 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() { m_threads_stepping_with_breakpoint.clear(); // Notify the delegate about the stop - SetCurrentThreadID(m_pending_notification_tid); SetState(StateType::eStateStopped, true); m_pending_notification_tid = LLDB_INVALID_THREAD_ID; } `` https://github.com/llvm/llvm-project/pull/127506 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] fix LR/SC handling in lldb-server (PR #127505)
https://github.com/dlav-sc created https://github.com/llvm/llvm-project/pull/127505 lldb-server didn't consider that LR instruction may be followed not only by BNE instruction (takes 4 bytes), but by BNEZ too, which is a compressed instruction (takes 2 bytes). As a result, after BNEZ lldb-server reseived an incorrect PC value and couldn't parse the next instruction opcode. >From 2ab6cea7391b00ec865e6b7838452511320a2eee Mon Sep 17 00:00:00 2001 From: Daniil Avdeev Date: Tue, 11 Feb 2025 16:38:53 + Subject: [PATCH] [lldb] fix LR/SC handling in lldb-server lldb-server didn't consider that LR instruction may be followed not only by BNE instruction (takes 4 bytes), but by BNEZ too, which is a compressed instruction (takes 2 bytes). As a result, after BNEZ lldb-server reseived an incorrect PC value and couldn't parse the next instruction opcode. --- .../RISCV/EmulateInstructionRISCV.cpp | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp index badc7ba36f011..e4de28d97d1ff 100644 --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -349,9 +349,10 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The second instruction should be BNE to exit address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The second instruction should be BNE or C.BNEZ to exit address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_exit = std::get(inst->decoded); @@ -359,15 +360,18 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; // save the exit address to check later const auto exit_pc = current_pc + SextW(bne_exit.imm); + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; // The third instruction should be SC.W or SC.D - inst = emulator.ReadInstructionAt(current_pc += 4); + inst = emulator.ReadInstructionAt(current_pc); if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The fourth instruction should be BNE to entry address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The fourth instruction should be BNE or C.BNEZ to entry address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_start = std::get(inst->decoded); @@ -375,8 +379,9 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; if (entry_pc != current_pc + SextW(bne_start.imm)) return false; + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; - current_pc += 4; // check the exit address and jump to it return exit_pc == current_pc && emulator.WritePC(current_pc); } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] fix software breakpoint removing in multithreaded process while stepping (PR #127506)
https://github.com/dlav-sc created https://github.com/llvm/llvm-project/pull/127506 I have encountered with the issue that sometimes lldb-server can't remove internal software breakpoints in a multithread process and as a result the process freezes. The source of the issue was that lldb-server tried to read/write memory of the process using a tid of the exited thread and received 'No such process' error from ptrace. This patch sets an existing thread as the current one for this process before software breakpoints removing. >From 8beff49a1b0af7b5f2298a73b9bb1a17670f673b Mon Sep 17 00:00:00 2001 From: Daniil Avdeev Date: Wed, 12 Feb 2025 13:15:53 + Subject: [PATCH] [lldb] fix software breakpoint removing in multithreaded process while stepping I have encountered with the issue that sometimes lldb-server can't remove internal software breakpoints in a multithread process and as a result the process freezes. The source of the issue was that lldb-server tried to read/write memory of the process using a tid of the exited thread and received 'No such process' error from ptrace. This patch sets an existing thread as the current one for this process before software breakpoints removing. --- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 7f2aba0e4eb2c..fe16ec73c0404 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1959,6 +1959,7 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() { // Clear any temporary breakpoints we used to implement software single // stepping. + SetCurrentThreadID(m_pending_notification_tid); for (const auto &thread_info : m_threads_stepping_with_breakpoint) { Status error = RemoveBreakpoint(thread_info.second); if (error.Fail()) @@ -1968,7 +1969,6 @@ void NativeProcessLinux::SignalIfAllThreadsStopped() { m_threads_stepping_with_breakpoint.clear(); // Notify the delegate about the stop - SetCurrentThreadID(m_pending_notification_tid); SetState(StateType::eStateStopped, true); m_pending_notification_tid = LLDB_INVALID_THREAD_ID; } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] remove AdaptedConstIterator and AdaptedIterable (PR #127507)
https://github.com/dlav-sc created https://github.com/llvm/llvm-project/pull/127507 AdaptedConstIterator currently doesn't have iterator traits, so I can't use STL algorithms with containers like WatchpointList. This patch replaces AdaptedConstIterator and AdaptedIterable with llvm::iterator_adaped_base and llvm::iterator_range respectively. >From 5b41afe5a368a9243442d6ad93f78f4d1cef5405 Mon Sep 17 00:00:00 2001 From: Daniil Avdeev Date: Wed, 5 Feb 2025 13:20:24 + Subject: [PATCH] [lldb] remove AdaptedConstIterator and AdaptedIterable AdaptedConstIterator currently doesn't have iterator traits, so I can't use STL algorithms with containers like WatchpointList. This patch replaces AdaptedConstIterator and AdaptedIterable with llvm::iterator_adaped_base and llvm::iterator_range respectively. --- lldb/include/lldb/Breakpoint/BreakpointList.h | 3 +- .../Breakpoint/BreakpointLocationCollection.h | 3 +- .../lldb/Breakpoint/BreakpointLocationList.h | 3 +- lldb/include/lldb/Breakpoint/WatchpointList.h | 3 +- .../lldb/Breakpoint/WatchpointResource.h | 3 +- lldb/include/lldb/Core/ModuleList.h | 5 +- lldb/include/lldb/Core/ModuleSpec.h | 3 +- .../lldb/Host/common/NativeProcessProtocol.h | 10 +- lldb/include/lldb/Symbol/SymbolContext.h | 2 +- lldb/include/lldb/Symbol/TypeList.h | 3 +- lldb/include/lldb/Symbol/TypeMap.h| 3 +- lldb/include/lldb/Target/QueueList.h | 4 +- lldb/include/lldb/Target/TargetList.h | 3 +- lldb/include/lldb/Target/ThreadCollection.h | 3 +- lldb/include/lldb/Utility/Iterable.h | 175 ++ 15 files changed, 38 insertions(+), 188 deletions(-) diff --git a/lldb/include/lldb/Breakpoint/BreakpointList.h b/lldb/include/lldb/Breakpoint/BreakpointList.h index a7399d385f6f0..4a921fadfc066 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointList.h @@ -163,8 +163,7 @@ class BreakpointList { bool m_is_internal; public: - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable BreakpointIterable; BreakpointIterable Breakpoints() { return BreakpointIterable(m_breakpoints, GetMutex()); diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h index 34bd309864871..3aef1d658c0e5 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h @@ -165,8 +165,7 @@ class BreakpointLocationCollection { mutable std::mutex m_collection_mutex; public: - typedef AdaptedIterable + typedef llvm::iterator_range BreakpointLocationCollectionIterable; BreakpointLocationCollectionIterable BreakpointLocations() { return BreakpointLocationCollectionIterable(m_break_loc_collection); diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h index f76a8fcfdd7e7..17dc0bfe03148 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h @@ -204,8 +204,7 @@ class BreakpointLocationList { BreakpointLocationCollection *m_new_location_recorder; public: - typedef AdaptedIterable + typedef llvm::iterator_range BreakpointLocationIterable; BreakpointLocationIterable BreakpointLocations() { diff --git a/lldb/include/lldb/Breakpoint/WatchpointList.h b/lldb/include/lldb/Breakpoint/WatchpointList.h index bf87495d79dba..d037d36e64290 100644 --- a/lldb/include/lldb/Breakpoint/WatchpointList.h +++ b/lldb/include/lldb/Breakpoint/WatchpointList.h @@ -39,8 +39,7 @@ class WatchpointList { ~WatchpointList(); typedef std::list wp_collection; - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable WatchpointIterable; /// Add a Watchpoint to the list. diff --git a/lldb/include/lldb/Breakpoint/WatchpointResource.h b/lldb/include/lldb/Breakpoint/WatchpointResource.h index 070d84cff8f26..c1a81fc486eb6 100644 --- a/lldb/include/lldb/Breakpoint/WatchpointResource.h +++ b/lldb/include/lldb/Breakpoint/WatchpointResource.h @@ -39,8 +39,7 @@ class WatchpointResource void SetType(bool read, bool write); typedef std::vector WatchpointCollection; - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable WatchpointIterable; /// Iterate over the watchpoint constituents for this resource diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 43d931a844740..29b87de88520d 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -521,14 +521,13 @@ class ModuleList { Notifier *m_notifier = nullptr; public: - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable ModuleIterable; ModuleIterable Modules() const { return ModuleIterable(m_modules, GetMutex()
[Lldb-commits] [lldb] [lldb] remove AdaptedConstIterator and AdaptedIterable (PR #127507)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: None (dlav-sc) Changes AdaptedConstIterator currently doesn't have iterator traits, so I can't use STL algorithms with containers like WatchpointList. This patch replaces AdaptedConstIterator and AdaptedIterable with llvm::iterator_adaped_base and llvm::iterator_range respectively. --- Full diff: https://github.com/llvm/llvm-project/pull/127507.diff 15 Files Affected: - (modified) lldb/include/lldb/Breakpoint/BreakpointList.h (+1-2) - (modified) lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h (+1-2) - (modified) lldb/include/lldb/Breakpoint/BreakpointLocationList.h (+1-2) - (modified) lldb/include/lldb/Breakpoint/WatchpointList.h (+1-2) - (modified) lldb/include/lldb/Breakpoint/WatchpointResource.h (+1-2) - (modified) lldb/include/lldb/Core/ModuleList.h (+2-3) - (modified) lldb/include/lldb/Core/ModuleSpec.h (+1-2) - (modified) lldb/include/lldb/Host/common/NativeProcessProtocol.h (+3-7) - (modified) lldb/include/lldb/Symbol/SymbolContext.h (+1-1) - (modified) lldb/include/lldb/Symbol/TypeList.h (+1-2) - (modified) lldb/include/lldb/Symbol/TypeMap.h (+2-1) - (modified) lldb/include/lldb/Target/QueueList.h (+1-3) - (modified) lldb/include/lldb/Target/TargetList.h (+1-2) - (modified) lldb/include/lldb/Target/ThreadCollection.h (+1-2) - (modified) lldb/include/lldb/Utility/Iterable.h (+20-155) ``diff diff --git a/lldb/include/lldb/Breakpoint/BreakpointList.h b/lldb/include/lldb/Breakpoint/BreakpointList.h index a7399d385f6f0..4a921fadfc066 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointList.h @@ -163,8 +163,7 @@ class BreakpointList { bool m_is_internal; public: - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable BreakpointIterable; BreakpointIterable Breakpoints() { return BreakpointIterable(m_breakpoints, GetMutex()); diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h index 34bd309864871..3aef1d658c0e5 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocationCollection.h @@ -165,8 +165,7 @@ class BreakpointLocationCollection { mutable std::mutex m_collection_mutex; public: - typedef AdaptedIterable + typedef llvm::iterator_range BreakpointLocationCollectionIterable; BreakpointLocationCollectionIterable BreakpointLocations() { return BreakpointLocationCollectionIterable(m_break_loc_collection); diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h index f76a8fcfdd7e7..17dc0bfe03148 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointLocationList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointLocationList.h @@ -204,8 +204,7 @@ class BreakpointLocationList { BreakpointLocationCollection *m_new_location_recorder; public: - typedef AdaptedIterable + typedef llvm::iterator_range BreakpointLocationIterable; BreakpointLocationIterable BreakpointLocations() { diff --git a/lldb/include/lldb/Breakpoint/WatchpointList.h b/lldb/include/lldb/Breakpoint/WatchpointList.h index bf87495d79dba..d037d36e64290 100644 --- a/lldb/include/lldb/Breakpoint/WatchpointList.h +++ b/lldb/include/lldb/Breakpoint/WatchpointList.h @@ -39,8 +39,7 @@ class WatchpointList { ~WatchpointList(); typedef std::list wp_collection; - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable WatchpointIterable; /// Add a Watchpoint to the list. diff --git a/lldb/include/lldb/Breakpoint/WatchpointResource.h b/lldb/include/lldb/Breakpoint/WatchpointResource.h index 070d84cff8f26..c1a81fc486eb6 100644 --- a/lldb/include/lldb/Breakpoint/WatchpointResource.h +++ b/lldb/include/lldb/Breakpoint/WatchpointResource.h @@ -39,8 +39,7 @@ class WatchpointResource void SetType(bool read, bool write); typedef std::vector WatchpointCollection; - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable WatchpointIterable; /// Iterate over the watchpoint constituents for this resource diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 43d931a844740..29b87de88520d 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -521,14 +521,13 @@ class ModuleList { Notifier *m_notifier = nullptr; public: - typedef LockingAdaptedIterable + typedef LockingAdaptedIterable ModuleIterable; ModuleIterable Modules() const { return ModuleIterable(m_modules, GetMutex()); } - typedef AdaptedIterable + typedef llvm::iterator_range ModuleIterableNoLocking; ModuleIterableNoLocking ModulesNoLocking() const { return ModuleIterableNoLocking(m_modules); diff --git a/lldb/include/lldb/Core/ModuleSpec.h b/lldb/include/lldb/Core/ModuleSpec.h index 4cbbbfa8a26e
[Lldb-commits] [lldb] [lldb] fix LR/SC handling in lldb-server (PR #127505)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 4d7192a5ecabb36263a2cacd4e9243b958424805 2ab6cea7391b00ec865e6b7838452511320a2eee --extensions cpp -- lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp `` View the diff from clang-format here. ``diff diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp index e4de28d97d..34c259a8e6 100644 --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -351,8 +351,8 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; current_pc += 4; - // The second instruction should be BNE or C.BNEZ to exit address - inst = emulator.ReadInstructionAt(current_pc); + // The second instruction should be BNE or C.BNEZ to exit address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_exit = std::get(inst->decoded); @@ -370,8 +370,8 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; current_pc += 4; - // The fourth instruction should be BNE or C.BNEZ to entry address - inst = emulator.ReadInstructionAt(current_pc); + // The fourth instruction should be BNE or C.BNEZ to entry address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_start = std::get(inst->decoded); `` https://github.com/llvm/llvm-project/pull/127505 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] fix LR/SC handling in lldb-server (PR #127505)
https://github.com/dlav-sc updated https://github.com/llvm/llvm-project/pull/127505 >From 8691dc941dab6c04e980b0b84098d665833209ea Mon Sep 17 00:00:00 2001 From: Daniil Avdeev Date: Tue, 11 Feb 2025 16:38:53 + Subject: [PATCH] [lldb] fix LR/SC handling in lldb-server lldb-server didn't consider that LR instruction may be followed not only by BNE instruction (takes 4 bytes), but by BNEZ too, which is a compressed instruction (takes 2 bytes). As a result, after BNEZ lldb-server reseived an incorrect PC value and couldn't parse the next instruction opcode. --- .../RISCV/EmulateInstructionRISCV.cpp | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp index badc7ba36f011..34c259a8e6a09 100644 --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -349,9 +349,10 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The second instruction should be BNE to exit address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The second instruction should be BNE or C.BNEZ to exit address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_exit = std::get(inst->decoded); @@ -359,15 +360,18 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; // save the exit address to check later const auto exit_pc = current_pc + SextW(bne_exit.imm); + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; // The third instruction should be SC.W or SC.D - inst = emulator.ReadInstructionAt(current_pc += 4); + inst = emulator.ReadInstructionAt(current_pc); if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The fourth instruction should be BNE to entry address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The fourth instruction should be BNE or C.BNEZ to entry address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_start = std::get(inst->decoded); @@ -375,8 +379,9 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; if (entry_pc != current_pc + SextW(bne_start.imm)) return false; + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; - current_pc += 4; // check the exit address and jump to it return exit_pc == current_pc && emulator.WritePC(current_pc); } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] fix LR/SC handling in lldb-server (PR #127505)
https://github.com/dlav-sc updated https://github.com/llvm/llvm-project/pull/127505 >From 244a67ec597d74df382825fce475b269e27a18ef Mon Sep 17 00:00:00 2001 From: Daniil Avdeev Date: Tue, 11 Feb 2025 16:38:53 + Subject: [PATCH] [lldb][RISCV] fix LR/SC handling in lldb-server lldb-server didn't consider that LR instruction may be followed not only by BNE instruction (takes 4 bytes), but by BNEZ too, which is a compressed instruction (takes 2 bytes). As a result, after BNEZ lldb-server reseived an incorrect PC value and couldn't parse the next instruction opcode. --- .../RISCV/EmulateInstructionRISCV.cpp | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp index badc7ba36f011..34c259a8e6a09 100644 --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -349,9 +349,10 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The second instruction should be BNE to exit address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The second instruction should be BNE or C.BNEZ to exit address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_exit = std::get(inst->decoded); @@ -359,15 +360,18 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; // save the exit address to check later const auto exit_pc = current_pc + SextW(bne_exit.imm); + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; // The third instruction should be SC.W or SC.D - inst = emulator.ReadInstructionAt(current_pc += 4); + inst = emulator.ReadInstructionAt(current_pc); if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The fourth instruction should be BNE to entry address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The fourth instruction should be BNE or C.BNEZ to entry address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_start = std::get(inst->decoded); @@ -375,8 +379,9 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; if (entry_pc != current_pc + SextW(bne_start.imm)) return false; + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; - current_pc += 4; // check the exit address and jump to it return exit_pc == current_pc && emulator.WritePC(current_pc); } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][NFC] remove AdaptedConstIterator and AdaptedIterable (PR #127507)
https://github.com/dlav-sc edited https://github.com/llvm/llvm-project/pull/127507 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
@@ -544,7 +545,7 @@ bool operator==(const CompilerType &lhs, const CompilerType &rhs); bool operator!=(const CompilerType &lhs, const CompilerType &rhs); struct CompilerType::IntegralTemplateArgument { - llvm::APSInt value; + clang::APValue value; Michael137 wrote: Ah good point. Changed to Scalar, wasn't a difficult transformation to make https://github.com/llvm/llvm-project/pull/127206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
@@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); Michael137 wrote: We probably also want to check for the other possible virtual thunk override maglings? https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-special-thunks https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127419 >From c533d71a56fa7d6347b1698c63c8626513e70ab0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sun, 16 Feb 2025 13:27:07 -0800 Subject: [PATCH 1/4] [lldb] Support stepping over C++ thunks This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 --- lldb/include/lldb/Target/LanguageRuntime.h| 2 + .../CPlusPlus/CPPLanguageRuntime.cpp | 6 +++ .../CPlusPlus/CPPLanguageRuntime.h| 3 ++ .../Target/ThreadPlanShouldStopHere.cpp | 51 +++ lldb/test/API/lang/cpp/thunk/Makefile | 3 ++ lldb/test/API/lang/cpp/thunk/TestThunk.py | 24 + lldb/test/API/lang/cpp/thunk/main.cpp | 36 + 7 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 lldb/test/API/lang/cpp/thunk/Makefile create mode 100644 lldb/test/API/lang/cpp/thunk/TestThunk.py create mode 100644 lldb/test/API/lang/cpp/thunk/main.cpp diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..e648b9665bef6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..723d7965c3467 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) + should_stop_here = false; + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +122,34 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to step through it. bool just_step_out = false; -if (sc.symbol && sc.symbol->ValueIsAddress()) { - Address symbol_end = sc.symbol->GetAddress(); - symbol_end.Slide(sc.symbol->GetByteSize() - 1); - if (range.Cont
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Pavel Labath (labath) Changes The motivation is #123622 and the fact that is hard to fine the last line entry in a given range. `FindLineEntryByAddress(range_end-1)` is the best we have, but it's not ideal because it has a magic -1 and that it relies on there existing a line entry at that address (generally, it should be there, but if for some case it isn't, we might end up ignoring the entries that are there (or -- like my incorrect fix in #123622 did -- iterating through the entire line table). What we really want is to get the last entry that exists in the given range. Or, equivalently (and more STL-like) the first entry after that range. This is what these functions do. I've used the STL names since they do pretty much exactly what the standard functions do (the main head-scratcher comes from the fact that our entries represent ranges rather than single values). The functions can also be used to simplify the maze of `if` statements in `FindLineEntryByAddress`, but I'm keeping that as a separate patch. For now, I'm just adding some unit testing for that function to gain more confidence that the patch does not change the function behavior. --- Full diff: https://github.com/llvm/llvm-project/pull/127519.diff 4 Files Affected: - (modified) lldb/include/lldb/Symbol/LineTable.h (+13) - (modified) lldb/source/Symbol/LineTable.cpp (+43-1) - (modified) lldb/unittests/Symbol/CMakeLists.txt (+1) - (added) lldb/unittests/Symbol/LineTableTest.cpp (+286) ``diff diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h index 6d158ab518879..2d7a6310758a9 100644 --- a/lldb/include/lldb/Symbol/LineTable.h +++ b/lldb/include/lldb/Symbol/LineTable.h @@ -102,6 +102,19 @@ class LineTable { void GetDescription(Stream *s, Target *target, lldb::DescriptionLevel level); + /// Helper function for line table iteration. \c lower_bound returns the index + /// of the first line entry which ends after the given address (i.e., the + /// first entry which contains the given address or it comes after it). + /// \c upper_bound returns the index of the first line entry which begins on + /// or after the given address (i.e., the entry which would come after the entry + /// containing the given address, if such an entry exists). Functions return + /// GetSize() if there is no such entry. + /// The functions are most useful in combination: iterating from + /// lower_bound(a) to upper_bound(b) returns all line tables + /// which intersect the half-open range [a,b). + uint32_t lower_bound(const Address &so_addr) const; + uint32_t upper_bound(const Address &so_addr) const; + /// Find a line entry that contains the section offset address \a so_addr. /// /// \param[in] so_addr diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 3d2afcdd11997..c9cad0cb30d73 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -123,7 +123,7 @@ void LineTable::InsertSequence(LineSequence *sequence) { entry_collection::iterator end_pos = m_entries.end(); LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); entry_collection::iterator pos = - upper_bound(begin_pos, end_pos, entry, less_than_bp); + std::upper_bound(begin_pos, end_pos, entry, less_than_bp); // We should never insert a sequence in the middle of another sequence if (pos != begin_pos) { @@ -185,6 +185,48 @@ bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { return false; } +uint32_t LineTable::lower_bound(const Address &so_addr) const { + if (so_addr.GetModule() != m_comp_unit->GetModule()) +return GetSize(); + + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr == LLDB_INVALID_ADDRESS) +return GetSize(); + + // This is not a typo. upper_bound returns the first entry which definitely + // does not contain this address, which means the entry before it *might* + // contain it -- if it is not a termination entry. + auto pos = + llvm::upper_bound(m_entries, search_entry, Entry::EntryAddressLessThan); + + if (pos != m_entries.begin() && !std::prev(pos)->is_terminal_entry) +--pos; + + return std::distance(m_entries.begin(), pos); +} + +uint32_t LineTable::upper_bound(const Address &so_addr) const { + if (so_addr.GetModule() != m_comp_unit->GetModule()) +return GetSize(); + + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr == LLDB_INVALID_ADDRESS) +return GetSize(); + + // This is not a typo. lower_bound returns the first entry which starts on or + // after the given address, which is exactly what we want -- *except* if the + // entry is a termination entry (in that case, we want the one after it). + auto pos = + llvm::lower_bound(m_entries, search_entry, Entry::EntryAddressLess
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 6812fc02fbb81d679f95d5c3e15768ae11e1bad8 b5904f01c64b2c6005f986886ce00ac507172bd2 --extensions cpp,h -- lldb/test/API/lang/cpp/thunk/main.cpp lldb/include/lldb/Target/LanguageRuntime.h lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h lldb/source/Target/ThreadPlanShouldStopHere.cpp `` View the diff from clang-format here. ``diff diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 4885095528..21a5ebe530 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -478,10 +478,12 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, } bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { - llvm::StringRef mangled_name = symbol.GetMangled().GetMangledName().GetStringRef(); + llvm::StringRef mangled_name = + symbol.GetMangled().GetMangledName().GetStringRef(); // Virtual function overriding from a non-virtual base use a "Th" prefix. // Virtual function overriding from a virtual base must use a "Tv" prefix. - // Virtual function overriding thunks with covariant returns use a "Tc" prefix. + // Virtual function overriding thunks with covariant returns use a "Tc" + // prefix. return mangled_name.starts_with("_ZTh") || mangled_name.starts_with("_ZTv") || mangled_name.starts_with("_ZTc"); } `` https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127419 >From c533d71a56fa7d6347b1698c63c8626513e70ab0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sun, 16 Feb 2025 13:27:07 -0800 Subject: [PATCH 1/5] [lldb] Support stepping over C++ thunks This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 --- lldb/include/lldb/Target/LanguageRuntime.h| 2 + .../CPlusPlus/CPPLanguageRuntime.cpp | 6 +++ .../CPlusPlus/CPPLanguageRuntime.h| 3 ++ .../Target/ThreadPlanShouldStopHere.cpp | 51 +++ lldb/test/API/lang/cpp/thunk/Makefile | 3 ++ lldb/test/API/lang/cpp/thunk/TestThunk.py | 24 + lldb/test/API/lang/cpp/thunk/main.cpp | 36 + 7 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 lldb/test/API/lang/cpp/thunk/Makefile create mode 100644 lldb/test/API/lang/cpp/thunk/TestThunk.py create mode 100644 lldb/test/API/lang/cpp/thunk/main.cpp diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..e648b9665bef6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..723d7965c3467 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) + should_stop_here = false; + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +122,34 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to step through it. bool just_step_out = false; -if (sc.symbol && sc.symbol->ValueIsAddress()) { - Address symbol_end = sc.symbol->GetAddress(); - symbol_end.Slide(sc.symbol->GetByteSize() - 1); - if (range.Cont
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/127519 >From 2e363a1c0653f7a35d2cdcbc79353badf9fa86f0 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 17 Feb 2025 17:29:40 +0100 Subject: [PATCH] [lldb] Add LineTable::{upper,lower}_bound The motivation is #123622 and the fact that is hard to fine the last line entry in a given range. `FindLineEntryByAddress(range_end-1)` is the best we have, but it's not ideal because it has a magic -1 and that it relies on there existing a line entry at that address (generally, it should be there, but if for some case it isn't, we might end up ignoring the entries that are there (or -- like my incorrect fix in #123622 did -- iterating through the entire line table). What we really want is to get the last entry that exists in the given range. Or, equivalently (and more STL-like) the first entry after that range. This is what these functions do. I've used the STL names since they do pretty much exactly what the standard functions do (the main head-scratcher comes from the fact that our entries represent ranges rather than single values). The functions can also be used to simplify the maze of `if` statements in `FindLineEntryByAddress`, but I'm keeping that as a separate patch. For now, I'm just adding some unit testing for that function to gain more confidence that the patch does not change the function behavior. --- lldb/include/lldb/Symbol/LineTable.h| 13 ++ lldb/source/Symbol/LineTable.cpp| 44 +++- lldb/unittests/Symbol/CMakeLists.txt| 1 + lldb/unittests/Symbol/LineTableTest.cpp | 285 4 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 lldb/unittests/Symbol/LineTableTest.cpp diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h index 6d158ab518879..f66081b6ee110 100644 --- a/lldb/include/lldb/Symbol/LineTable.h +++ b/lldb/include/lldb/Symbol/LineTable.h @@ -102,6 +102,19 @@ class LineTable { void GetDescription(Stream *s, Target *target, lldb::DescriptionLevel level); + /// Helper function for line table iteration. \c lower_bound returns the index + /// of the first line entry which ends after the given address (i.e., the + /// first entry which contains the given address or it comes after it). + /// \c upper_bound returns the index of the first line entry which begins on + /// or after the given address (i.e., the entry which would come after the + /// entry containing the given address, if such an entry exists). Functions + /// return GetSize() if there is no such entry. The functions are + /// most useful in combination: iterating from lower_bound(a) to + /// upper_bound(b) returns all line tables which intersect the half-open + /// range [a,b). + uint32_t lower_bound(const Address &so_addr) const; + uint32_t upper_bound(const Address &so_addr) const; + /// Find a line entry that contains the section offset address \a so_addr. /// /// \param[in] so_addr diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 3d2afcdd11997..c9cad0cb30d73 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -123,7 +123,7 @@ void LineTable::InsertSequence(LineSequence *sequence) { entry_collection::iterator end_pos = m_entries.end(); LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); entry_collection::iterator pos = - upper_bound(begin_pos, end_pos, entry, less_than_bp); + std::upper_bound(begin_pos, end_pos, entry, less_than_bp); // We should never insert a sequence in the middle of another sequence if (pos != begin_pos) { @@ -185,6 +185,48 @@ bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { return false; } +uint32_t LineTable::lower_bound(const Address &so_addr) const { + if (so_addr.GetModule() != m_comp_unit->GetModule()) +return GetSize(); + + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr == LLDB_INVALID_ADDRESS) +return GetSize(); + + // This is not a typo. upper_bound returns the first entry which definitely + // does not contain this address, which means the entry before it *might* + // contain it -- if it is not a termination entry. + auto pos = + llvm::upper_bound(m_entries, search_entry, Entry::EntryAddressLessThan); + + if (pos != m_entries.begin() && !std::prev(pos)->is_terminal_entry) +--pos; + + return std::distance(m_entries.begin(), pos); +} + +uint32_t LineTable::upper_bound(const Address &so_addr) const { + if (so_addr.GetModule() != m_comp_unit->GetModule()) +return GetSize(); + + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr == LLDB_INVALID_ADDRESS) +return GetSize(); + + // This is not a typo. lower_bound returns the first entry which starts on or + // after the given address, which is exactly what we want -- *
[Lldb-commits] [lldb] [lldb] Synchronize the debugger's stdout and stderr streams (PR #126630)
labath wrote: > > > A random idea, I don't know if it's a good one: have one object > > > (LockableStreamPair?) that holds the two streams and their mutex. One > > > less argument to pass around? > > > > > > Sounds good, that simplifies the signatures (which this PR is already > > touching) and keeps the mutex abstracted away. > > I did implement this and I'm not happy with the result: even though you only > pass one object, you still need to get the output or error stream out of it > which ends up being more verbose. And because of the `IOHandler` and > `Debugger::AdoptTopIOHandlerFilesIfInvalid` it needs to be a shared pointer. > Here's what that looks like: > [d62fdae](https://github.com/llvm/llvm-project/commit/d62fdaec4cd322574e1ab78c8cacd1effe2c29c0). > It compiles but some tests are failing. Probably something small but given I > don't like the approach I haven't looked into it. That's okay. I thought it might not work out. Thanks for giving it a shot. I feel bad about bringing this up after you did all the work, but there is one more thing going through my head. I now have a very awkward feeling about this because it seems like this is solving mostly the same problem that StreamAsynchronousIO (and Debugger::PrintAsync) was trying to solve. You mentioned that in the first version of the patch and said that it doesn't work in some cases, but it's not quite clear why is that the case. If the motivation is status line, then it sounds like it *might* be possible to plumb the updates through the async streams. I can imagine that it might not work for some reason, but then I think it's important to know why, and come up with some sort of an story for which of the two systems should be used for a particular use case. Or, (I am dreaming, I know) actually deprecate/remove the async IO system. https://github.com/llvm/llvm-project/pull/126630 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Synchronize the debugger's stdout and stderr streams (PR #126630)
@@ -574,10 +581,10 @@ int Editline::GetCharacter(EditLineGetCharType *c) { // indefinitely. This gives a chance for someone to interrupt us. After // Read returns, immediately lock the mutex again and check if we were // interrupted. -m_output_mutex.unlock(); +m_output_stream_sp->GetMutex().unlock(); labath wrote: I see a thumbs up but no change? Any reason for not doing it. Or are you waiting until the other stuff is sorted out first? https://github.com/llvm/llvm-project/pull/126630 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
https://github.com/labath approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/127206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127419 >From c533d71a56fa7d6347b1698c63c8626513e70ab0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sun, 16 Feb 2025 13:27:07 -0800 Subject: [PATCH 1/2] [lldb] Support stepping over C++ thunks This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 --- lldb/include/lldb/Target/LanguageRuntime.h| 2 + .../CPlusPlus/CPPLanguageRuntime.cpp | 6 +++ .../CPlusPlus/CPPLanguageRuntime.h| 3 ++ .../Target/ThreadPlanShouldStopHere.cpp | 51 +++ lldb/test/API/lang/cpp/thunk/Makefile | 3 ++ lldb/test/API/lang/cpp/thunk/TestThunk.py | 24 + lldb/test/API/lang/cpp/thunk/main.cpp | 36 + 7 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 lldb/test/API/lang/cpp/thunk/Makefile create mode 100644 lldb/test/API/lang/cpp/thunk/TestThunk.py create mode 100644 lldb/test/API/lang/cpp/thunk/main.cpp diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..e648b9665bef6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..723d7965c3467 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) + should_stop_here = false; + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +122,34 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to step through it. bool just_step_out = false; -if (sc.symbol && sc.symbol->ValueIsAddress()) { - Address symbol_end = sc.symbol->GetAddress(); - symbol_end.Slide(sc.symbol->GetByteSize() - 1); - if (range.Cont
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
levy wrote: I'm the one who recently added an example reproducing the #43413 issue. I compiled this PR version of lldb and related tools and tested it against the simple reproduction I added to the issue, and also with our complex project where I first faced this issue. In both cases lldb works as expected with this patch. Thank you very much! https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
Michael137 wrote: Makes sense to me but I'll defer to @jimingham and co. for the stepping bits https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
tedwoodward wrote: @JDevlieghere would you mind getting rid of the nullptr in the testcase, main.cpp line 13? Base2 *b = nullptr; *b is set to nullptr per language standard, and those of use stuck in c++03 on embedded targets would appreciate it! https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
@@ -476,3 +476,12 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + // Virtual function override thunks come in two forms. Those overriding from a + // non-virtual base, with fixed this adjustments, use a "Th" prefix and encode + // the required adjustment offset, probably negative, indicated by a 'n' + // prefix, and the encoding of the target function. + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( Michael137 wrote: Hmm i think we also want to check `Tc` and `Tv`? `Tv` you can test by inheriting one of the bases virtually. And here's an example of a `Tc` encoding: ``` struct V1 { }; struct V2 : virtual V1 { }; struct A { virtual V1 *f(); }; struct B : A { virtual void b(); virtual V2 *f(); }; V2 *B::f() { return 0; } ``` ``` $ c++filt -n _ZTch0_v0_n24_N1B1fEv covariant return thunk to B::f() ``` https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Store the return ValueObject in the CommandReturnObject (PR #127566)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) Changes There are a lot of lldb commands whose result is really a ValueObject that we then print with the ValueObjectPrinter. Now that we have the ability to access the SBCommandReturnObject through a callback (#125006), we can store the resultant ValueObject in the return object, allowing an IDE to access the SBValue and do its own rich formatting. rdar://143965453 --- Full diff: https://github.com/llvm/llvm-project/pull/127566.diff 8 Files Affected: - (modified) lldb/include/lldb/API/SBCommandReturnObject.h (+2) - (modified) lldb/include/lldb/API/SBValue.h (+1) - (modified) lldb/include/lldb/Interpreter/CommandReturnObject.h (+10) - (modified) lldb/source/API/SBCommandReturnObject.cpp (+12-2) - (modified) lldb/source/Commands/CommandObjectDWIMPrint.cpp (+3) - (modified) lldb/source/Commands/CommandObjectExpression.cpp (+2) - (modified) lldb/source/Commands/CommandObjectFrame.cpp (+3-2) - (modified) lldb/test/API/api/command-return-object/TestSBCommandReturnObject.py (+13) ``diff diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index 9a63c1f96aa70..96dda239d3c97 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -136,6 +136,8 @@ class LLDB_API SBCommandReturnObject { void SetError(const char *error_cstr); + lldb::SBValue GetReturnValue(lldb::DynamicValueType use_dynamic); + protected: friend class SBCommandInterpreter; friend class SBOptions; diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 46ef6daa95264..75d20a4378f09 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -442,6 +442,7 @@ class LLDB_API SBValue { protected: friend class SBBlock; + friend class SBCommandReturnObject; friend class SBFrame; friend class SBModule; friend class SBTarget; diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index 803bcd76995ed..20600ff667bb6 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -14,6 +14,7 @@ #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StreamTee.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" #include "llvm/ADT/StringRef.h" @@ -165,6 +166,12 @@ class CommandReturnObject { return m_diagnostic_indent; } + lldb::ValueObjectSP GetValueObjectSP() const { return m_value_object_sp; } + + void SetValueObjectSP(lldb::ValueObjectSP value_object_sp) { +m_value_object_sp = value_object_sp; + } + lldb::ReturnStatus GetStatus() const; void SetStatus(lldb::ReturnStatus status); @@ -197,6 +204,9 @@ class CommandReturnObject { lldb::ReturnStatus m_status = lldb::eReturnStatusStarted; + /// An optional ValueObjectSP if the command created one. + lldb::ValueObjectSP m_value_object_sp; + bool m_did_change_process_state = false; bool m_suppress_immediate_output = false; diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index 6f54581e64ef4..b0de4adc6e241 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -12,6 +12,7 @@ #include "lldb/API/SBFile.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStructuredData.h" +#include "lldb/API/SBValue.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/ConstString.h" @@ -62,8 +63,8 @@ SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs) { m_opaque_up = clone(rhs.m_opaque_up); } -SBCommandReturnObject &SBCommandReturnObject:: -operator=(const SBCommandReturnObject &rhs) { +SBCommandReturnObject & +SBCommandReturnObject::operator=(const SBCommandReturnObject &rhs) { LLDB_INSTRUMENT_VA(this, rhs); if (this != &rhs) @@ -356,3 +357,12 @@ void SBCommandReturnObject::SetError(const char *error_cstr) { if (error_cstr) ref().AppendError(error_cstr); } + +SBValue +SBCommandReturnObject::GetReturnValue(lldb::DynamicValueType use_dynamic) { + LLDB_INSTRUMENT_VA(this, use_dynamic); + + SBValue sb_value; + sb_value.SetSP(ref().GetValueObjectSP(), use_dynamic); + return sb_value; +} diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index d4d038d28f675..aab99441c63a3 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -205,6 +205,9 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, ExpressionResults expr_result = target.EvaluateExpression( expr, exe_scope, valobj_sp, eval_options, &fixed_expression); +if (valobj_
[Lldb-commits] [lldb] [lldb] Store the return ValueObject in the CommandReturnObject (PR #127566)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff f71b83b3593588c56fd4ab3e1347ad9c7bec624f 9c290f5d55e888c2674030da9ea06778573332da --extensions cpp,h -- lldb/include/lldb/API/SBCommandReturnObject.h lldb/include/lldb/API/SBValue.h lldb/include/lldb/Interpreter/CommandReturnObject.h lldb/source/API/SBCommandReturnObject.cpp lldb/source/Commands/CommandObjectDWIMPrint.cpp lldb/source/Commands/CommandObjectExpression.cpp lldb/source/Commands/CommandObjectFrame.cpp `` View the diff from clang-format here. ``diff diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index 69bce205dd..908549848e 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -320,8 +320,8 @@ protected: // to produce an error, but rather to just go to the top. OTOH, start // by seeing if the requested frame exists, in which case we can avoid // counting the stack here... -const uint32_t frame_requested = frame_idx -+ *m_options.relative_frame_offset; +const uint32_t frame_requested = +frame_idx + *m_options.relative_frame_offset; StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested); if (frame_sp) frame_idx = frame_requested; `` https://github.com/llvm/llvm-project/pull/127566 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Store the return ValueObject in the CommandReturnObject (PR #127566)
https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/127566 There are a lot of lldb commands whose result is really a ValueObject that we then print with the ValueObjectPrinter. Now that we have the ability to access the SBCommandReturnObject through a callback (#125006), we can store the resultant ValueObject in the return object, allowing an IDE to access the SBValue and do its own rich formatting. rdar://143965453 >From 9c290f5d55e888c2674030da9ea06778573332da Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 17 Feb 2025 20:44:51 -0800 Subject: [PATCH] [lldb] Store the return ValueObject in the CommandReturnObject There are a lot of lldb commands whose result is really a ValueObject that we then print with the ValueObjectPrinter. Now that we have the ability to access the SBCommandReturnObject through a callback (#125006), we can store the resultant ValueObject in the return object, allowing an IDE to access the SBValue and do its own rich formatting. rdar://143965453 --- lldb/include/lldb/API/SBCommandReturnObject.h | 2 ++ lldb/include/lldb/API/SBValue.h| 1 + .../include/lldb/Interpreter/CommandReturnObject.h | 10 ++ lldb/source/API/SBCommandReturnObject.cpp | 14 -- lldb/source/Commands/CommandObjectDWIMPrint.cpp| 3 +++ lldb/source/Commands/CommandObjectExpression.cpp | 2 ++ lldb/source/Commands/CommandObjectFrame.cpp| 5 +++-- .../TestSBCommandReturnObject.py | 13 + 8 files changed, 46 insertions(+), 4 deletions(-) diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index 9a63c1f96aa70..96dda239d3c97 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -136,6 +136,8 @@ class LLDB_API SBCommandReturnObject { void SetError(const char *error_cstr); + lldb::SBValue GetReturnValue(lldb::DynamicValueType use_dynamic); + protected: friend class SBCommandInterpreter; friend class SBOptions; diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 46ef6daa95264..75d20a4378f09 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -442,6 +442,7 @@ class LLDB_API SBValue { protected: friend class SBBlock; + friend class SBCommandReturnObject; friend class SBFrame; friend class SBModule; friend class SBTarget; diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index 803bcd76995ed..20600ff667bb6 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -14,6 +14,7 @@ #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StreamTee.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-forward.h" #include "lldb/lldb-private.h" #include "llvm/ADT/StringRef.h" @@ -165,6 +166,12 @@ class CommandReturnObject { return m_diagnostic_indent; } + lldb::ValueObjectSP GetValueObjectSP() const { return m_value_object_sp; } + + void SetValueObjectSP(lldb::ValueObjectSP value_object_sp) { +m_value_object_sp = value_object_sp; + } + lldb::ReturnStatus GetStatus() const; void SetStatus(lldb::ReturnStatus status); @@ -197,6 +204,9 @@ class CommandReturnObject { lldb::ReturnStatus m_status = lldb::eReturnStatusStarted; + /// An optional ValueObjectSP if the command created one. + lldb::ValueObjectSP m_value_object_sp; + bool m_did_change_process_state = false; bool m_suppress_immediate_output = false; diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index 6f54581e64ef4..b0de4adc6e241 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -12,6 +12,7 @@ #include "lldb/API/SBFile.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStructuredData.h" +#include "lldb/API/SBValue.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/ConstString.h" @@ -62,8 +63,8 @@ SBCommandReturnObject::SBCommandReturnObject(const SBCommandReturnObject &rhs) { m_opaque_up = clone(rhs.m_opaque_up); } -SBCommandReturnObject &SBCommandReturnObject:: -operator=(const SBCommandReturnObject &rhs) { +SBCommandReturnObject & +SBCommandReturnObject::operator=(const SBCommandReturnObject &rhs) { LLDB_INSTRUMENT_VA(this, rhs); if (this != &rhs) @@ -356,3 +357,12 @@ void SBCommandReturnObject::SetError(const char *error_cstr) { if (error_cstr) ref().AppendError(error_cstr); } + +SBValue +SBCommandReturnObject::GetReturnValue(lldb::DynamicValueType use_dynamic) { + LLDB_INSTRUMENT_VA(this, use_dynamic); + + SBValue sb_value; + sb_value.SetSP(ref().GetValueObjectSP(), use_dynamic); + return sb_value; +}
[Lldb-commits] [lldb] [lldb] Store the return ValueObject in the CommandReturnObject (PR #127566)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127566 >From 6f59b1116dd83b9cce526103cca98a5d2056720f Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 17 Feb 2025 20:58:30 -0800 Subject: [PATCH] [lldb] Store the return ValueObject in the CommandReturnObject There are a lot of lldb commands whose result is really a ValueObject that we then print with the ValueObjectPrinter. Now that we have the ability to access the SBCommandReturnObject through a callback (#125006), we can store the resultant ValueObject in the return object, allowing an IDE to access the SBValue and do its own rich formatting. rdar://143965453 --- lldb/include/lldb/API/SBCommandReturnObject.h | 2 ++ lldb/include/lldb/API/SBValue.h | 1 + lldb/include/lldb/Interpreter/CommandReturnObject.h | 9 + lldb/source/API/SBCommandReturnObject.cpp | 10 ++ lldb/source/Commands/CommandObjectDWIMPrint.cpp | 3 +++ lldb/source/Commands/CommandObjectExpression.cpp| 2 ++ lldb/source/Commands/CommandObjectFrame.cpp | 1 + .../TestSBCommandReturnObject.py| 13 + 8 files changed, 41 insertions(+) diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index 9a63c1f96aa70..96dda239d3c97 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -136,6 +136,8 @@ class LLDB_API SBCommandReturnObject { void SetError(const char *error_cstr); + lldb::SBValue GetReturnValue(lldb::DynamicValueType use_dynamic); + protected: friend class SBCommandInterpreter; friend class SBOptions; diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 46ef6daa95264..75d20a4378f09 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -442,6 +442,7 @@ class LLDB_API SBValue { protected: friend class SBBlock; + friend class SBCommandReturnObject; friend class SBFrame; friend class SBModule; friend class SBTarget; diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index 803bcd76995ed..1a6cc5c6de060 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -165,6 +165,12 @@ class CommandReturnObject { return m_diagnostic_indent; } + lldb::ValueObjectSP GetValueObjectSP() const { return m_value_object_sp; } + + void SetValueObjectSP(lldb::ValueObjectSP value_object_sp) { +m_value_object_sp = value_object_sp; + } + lldb::ReturnStatus GetStatus() const; void SetStatus(lldb::ReturnStatus status); @@ -197,6 +203,9 @@ class CommandReturnObject { lldb::ReturnStatus m_status = lldb::eReturnStatusStarted; + /// An optional return ValueObjectSP. + lldb::ValueObjectSP m_value_object_sp; + bool m_did_change_process_state = false; bool m_suppress_immediate_output = false; diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index 6f54581e64ef4..085bfac57c0a8 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -12,6 +12,7 @@ #include "lldb/API/SBFile.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStructuredData.h" +#include "lldb/API/SBValue.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Utility/ConstString.h" @@ -356,3 +357,12 @@ void SBCommandReturnObject::SetError(const char *error_cstr) { if (error_cstr) ref().AppendError(error_cstr); } + +SBValue +SBCommandReturnObject::GetReturnValue(lldb::DynamicValueType use_dynamic) { + LLDB_INSTRUMENT_VA(this, use_dynamic); + + SBValue sb_value; + sb_value.SetSP(ref().GetValueObjectSP(), use_dynamic); + return sb_value; +} diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index d4d038d28f675..aab99441c63a3 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -205,6 +205,9 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, ExpressionResults expr_result = target.EvaluateExpression( expr, exe_scope, valobj_sp, eval_options, &fixed_expression); +if (valobj_sp) + result.SetValueObjectSP(valobj_sp); + // Record the position of the expression in the command. std::optional indent; if (fixed_expression.empty()) { diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 7e26381c92405..b0c92d9391b13 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -434,6 +434,8 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, }
[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)
@@ -0,0 +1,284 @@ +//===-- DILEval.cpp ---===// +// +// 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 +// +//===--===// + +#include "lldb/ValueObject/DILEval.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/ValueObject/DILAST.h" +#include "lldb/ValueObject/ValueObject.h" +#include "lldb/ValueObject/ValueObjectRegister.h" +#include "lldb/ValueObject/ValueObjectVariable.h" +#include "llvm/Support/FormatAdapters.h" +#include + +namespace lldb_private::dil { + +static lldb::ValueObjectSP +LookupStaticIdentifier(lldb::TargetSP target_sp, + const llvm::StringRef &name_ref, + ConstString unqualified_name) { + // List global variable with the same "basename". There can be many matches + // from other scopes (namespaces, classes), so we do additional filtering + // later. + VariableList variable_list; + ConstString name(name_ref); + target_sp->GetImages().FindGlobalVariables(name, 1, variable_list); + if (variable_list.Empty()) +return nullptr; + + ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); + if (exe_scope == nullptr) +exe_scope = target_sp.get(); + for (const lldb::VariableSP &var_sp : variable_list) { +lldb::ValueObjectSP valobj_sp( +ValueObjectVariable::Create(exe_scope, var_sp)); +if (valobj_sp && valobj_sp->GetVariable() && +(valobj_sp->GetVariable()->NameMatches(unqualified_name) || + valobj_sp->GetVariable()->NameMatches(ConstString(name_ref + return valobj_sp; + } + + return nullptr; +} + +static lldb::VariableSP DILFindVariable(ConstString name, +VariableList *variable_list) { + lldb::VariableSP exact_match; + std::vector possible_matches; + + typedef std::vector collection; + typedef collection::iterator iterator; + + iterator pos, end = variable_list->end(); + for (pos = variable_list->begin(); pos != end; ++pos) { +llvm::StringRef str_ref_name = pos->get()->GetName().GetStringRef(); +// Check for global vars, which might start with '::'. +str_ref_name.consume_front("::"); + +if (str_ref_name == name.GetStringRef()) + possible_matches.push_back(*pos); +else if (pos->get()->NameMatches(name)) + possible_matches.push_back(*pos); + } + + // Look for exact matches (favors local vars over global vars) + auto exact_match_it = + llvm::find_if(possible_matches, [&](lldb::VariableSP var_sp) { +return var_sp->GetName() == name; + }); + + if (exact_match_it != llvm::adl_end(possible_matches)) +exact_match = *exact_match_it; + + if (!exact_match) +// Look for a global var exact match. +for (auto var_sp : possible_matches) { + llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef(); + if (str_ref_name.size() > 2 && str_ref_name[0] == ':' && + str_ref_name[1] == ':') +str_ref_name = str_ref_name.drop_front(2); + ConstString tmp_name(str_ref_name); + if (tmp_name == name) { +exact_match = var_sp; +break; + } +} + + // Take any match at this point. + if (!exact_match && possible_matches.size() > 0) +exact_match = possible_matches[0]; + + return exact_match; +} + +std::unique_ptr +LookupIdentifier(const std::string &name, + std::shared_ptr ctx_scope, + lldb::DynamicValueType use_dynamic, CompilerType *scope_ptr) { + ConstString name_str(name); + llvm::StringRef name_ref = name_str.GetStringRef(); + + // Support $rax as a special syntax for accessing registers. + // Will return an invalid value in case the requested register doesn't exist. + if (name_ref.starts_with("$")) { +lldb::ValueObjectSP value_sp; +const char *reg_name = name_ref.drop_front(1).data(); +Target *target = ctx_scope->CalculateTarget().get(); +Process *process = ctx_scope->CalculateProcess().get(); +if (!target || !process) + return nullptr; + +StackFrame *stack_frame = ctx_scope->CalculateStackFrame().get(); +if (!stack_frame) + return nullptr; + +lldb::RegisterContextSP reg_ctx(stack_frame->GetRegisterContext()); +if (!reg_ctx) + return nullptr; + +if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name)) + value_sp = ValueObjectRegister::Create(stack_frame, reg_ctx, reg_info); + +if (value_sp) + return IdentifierInfo::FromValue(*value_sp); + +return nullptr; + } + + // Internally values don't have global scope qualifier in their names and + // LLDB doesn't support queries with it too. + bool global_scope = false; + if (name_ref.starts_with("::")) { +name_ref = na
[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)
@@ -0,0 +1,284 @@ +//===-- DILEval.cpp ---===// +// +// 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 +// +//===--===// + +#include "lldb/ValueObject/DILEval.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/ValueObject/DILAST.h" +#include "lldb/ValueObject/ValueObject.h" +#include "lldb/ValueObject/ValueObjectRegister.h" +#include "lldb/ValueObject/ValueObjectVariable.h" +#include "llvm/Support/FormatAdapters.h" +#include + +namespace lldb_private::dil { + +static lldb::ValueObjectSP +LookupStaticIdentifier(lldb::TargetSP target_sp, + const llvm::StringRef &name_ref, + ConstString unqualified_name) { + // List global variable with the same "basename". There can be many matches + // from other scopes (namespaces, classes), so we do additional filtering + // later. + VariableList variable_list; + ConstString name(name_ref); + target_sp->GetImages().FindGlobalVariables(name, 1, variable_list); + if (variable_list.Empty()) +return nullptr; + + ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); + if (exe_scope == nullptr) +exe_scope = target_sp.get(); + for (const lldb::VariableSP &var_sp : variable_list) { +lldb::ValueObjectSP valobj_sp( +ValueObjectVariable::Create(exe_scope, var_sp)); +if (valobj_sp && valobj_sp->GetVariable() && +(valobj_sp->GetVariable()->NameMatches(unqualified_name) || + valobj_sp->GetVariable()->NameMatches(ConstString(name_ref + return valobj_sp; + } + + return nullptr; +} + +static lldb::VariableSP DILFindVariable(ConstString name, +VariableList *variable_list) { + lldb::VariableSP exact_match; + std::vector possible_matches; + + typedef std::vector collection; + typedef collection::iterator iterator; + + iterator pos, end = variable_list->end(); + for (pos = variable_list->begin(); pos != end; ++pos) { +llvm::StringRef str_ref_name = pos->get()->GetName().GetStringRef(); +// Check for global vars, which might start with '::'. +str_ref_name.consume_front("::"); + +if (str_ref_name == name.GetStringRef()) + possible_matches.push_back(*pos); +else if (pos->get()->NameMatches(name)) + possible_matches.push_back(*pos); + } + + // Look for exact matches (favors local vars over global vars) + auto exact_match_it = + llvm::find_if(possible_matches, [&](lldb::VariableSP var_sp) { +return var_sp->GetName() == name; + }); + + if (exact_match_it != llvm::adl_end(possible_matches)) +exact_match = *exact_match_it; + + if (!exact_match) +// Look for a global var exact match. +for (auto var_sp : possible_matches) { + llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef(); + if (str_ref_name.size() > 2 && str_ref_name[0] == ':' && + str_ref_name[1] == ':') +str_ref_name = str_ref_name.drop_front(2); + ConstString tmp_name(str_ref_name); + if (tmp_name == name) { +exact_match = var_sp; +break; + } +} + + // Take any match at this point. + if (!exact_match && possible_matches.size() > 0) +exact_match = possible_matches[0]; + + return exact_match; +} + +std::unique_ptr +LookupIdentifier(const std::string &name, + std::shared_ptr ctx_scope, + lldb::DynamicValueType use_dynamic, CompilerType *scope_ptr) { + ConstString name_str(name); + llvm::StringRef name_ref = name_str.GetStringRef(); + + // Support $rax as a special syntax for accessing registers. + // Will return an invalid value in case the requested register doesn't exist. + if (name_ref.starts_with("$")) { +lldb::ValueObjectSP value_sp; +const char *reg_name = name_ref.drop_front(1).data(); +Target *target = ctx_scope->CalculateTarget().get(); +Process *process = ctx_scope->CalculateProcess().get(); +if (!target || !process) + return nullptr; + +StackFrame *stack_frame = ctx_scope->CalculateStackFrame().get(); +if (!stack_frame) + return nullptr; + +lldb::RegisterContextSP reg_ctx(stack_frame->GetRegisterContext()); +if (!reg_ctx) + return nullptr; + +if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name)) + value_sp = ValueObjectRegister::Create(stack_frame, reg_ctx, reg_info); + +if (value_sp) + return IdentifierInfo::FromValue(*value_sp); + +return nullptr; + } + + // Internally values don't have global scope qualifier in their names and + // LLDB doesn't support queries with it too. + bool global_scope = false; + if (name_ref.starts_with("::")) { +name_ref = na
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `lldb-aarch64-windows` running on `linaro-armv8-windows-msvc-05` while building `lldb` at step 6 "test". Full details are available at: https://lab.llvm.org/buildbot/#/builders/141/builds/6383 Here is the relevant piece of the build log for the reference ``` Step 6 (test) failure: build (failure) ... PASS: lldb-api :: lang/cpp/structured-binding/TestStructuredBinding.py (851 of 2085) PASS: lldb-api :: lang/cpp/subst_template_type_param/TestSubstTemplateTypeParam.py (852 of 2085) UNSUPPORTED: lldb-api :: lang/cpp/symbols/TestSymbols.py (853 of 2085) UNSUPPORTED: lldb-api :: lang/cpp/template-function/TestTemplateFunctions.py (854 of 2085) PASS: lldb-api :: lang/cpp/template-arguments/TestCppTemplateArguments.py (855 of 2085) PASS: lldb-api :: lang/cpp/template-specialization-type/TestTemplateSpecializationType.py (856 of 2085) PASS: lldb-api :: lang/cpp/template/TestTemplateArgs.py (857 of 2085) UNSUPPORTED: lldb-api :: lang/cpp/this/TestCPPThis.py (858 of 2085) PASS: lldb-api :: lang/cpp/this_class_type_mixing/TestThisClassTypeMixing.py (859 of 2085) UNSUPPORTED: lldb-api :: lang/cpp/thread_local/TestThreadLocal.py (860 of 2085) FAIL: lldb-api :: lang/cpp/thunk/TestThunk.py (861 of 2085) TEST 'lldb-api :: lang/cpp/thunk/TestThunk.py' FAILED Script: -- C:/Users/tcwg/scoop/apps/python/current/python.exe C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/llvm-project/lldb\test\API\dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --env LLVM_INCLUDE_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/include --env LLVM_TOOLS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --arch aarch64 --build-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex --lldb-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-lldb\lldb-api --clang-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-clang\lldb-api --executable C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/lldb.exe --compiler C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/clang.exe --dsymutil C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/dsymutil.exe --make C:/Users/tcwg/scoop/shims/make.exe --llvm-tools-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --lldb-obj-root C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/tools/lldb --lldb-libs-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --skip-category=watchpoint C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\test\API\lang\cpp\thunk -p TestThunk.py -- Exit Code: 1 Command Output (stdout): -- lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision a3dc77c00a012bb613cb08e669dab4fadf88e935) clang revision a3dc77c00a012bb613cb08e669dab4fadf88e935 llvm revision a3dc77c00a012bb613cb08e669dab4fadf88e935 Skipping the following test categories: ['watchpoint', 'libc++', 'libstdcxx', 'dwo', 'dsym', 'gmodules', 'debugserver', 'objc', 'fork', 'pexpect'] -- Command Output (stderr): -- UNSUPPORTED: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_step_out_thunk_dsym (TestThunk.ThunkTest.test_step_out_thunk_dsym) (test case does not fall in any category of interest for this run) FAIL: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_step_out_thunk_dwarf (TestThunk.ThunkTest.test_step_out_thunk_dwarf) UNSUPPORTED: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_step_out_thunk_dwo (TestThunk.ThunkTest.test_step_out_thunk_dwo) (test case does not fall in any category of interest for this run) UNSUPPORTED: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_step_through_thunk_dsym (TestThunk.ThunkTest.test_step_through_thunk_dsym) (test case does not fall in any category of interest for this run) PASS: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_step_through_thunk_dwarf (TestThunk.ThunkTest.test_step_through_thunk_dwarf) UNSUPPORTED: LLDB (C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe-aarch64) :: test_step_through_thunk_dwo (TestThunk.ThunkTest.test_step_through_thunk_dwo) (test case does not fall in any category of interest for this run) == FAIL: test_step_out_thunk_dwarf (TestThunk.ThunkTest.test_step_out_thunk_dwarf) -- Traceback (most recent call last): ``` https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailin
[Lldb-commits] [lldb] 2b41277 - [lldb] Disable test_step_out_thunk on Windows
Author: Jonas Devlieghere Date: 2025-02-17T16:25:13-08:00 New Revision: 2b41277a09820bc47dc533ad37b5213edc2e8d52 URL: https://github.com/llvm/llvm-project/commit/2b41277a09820bc47dc533ad37b5213edc2e8d52 DIFF: https://github.com/llvm/llvm-project/commit/2b41277a09820bc47dc533ad37b5213edc2e8d52.diff LOG: [lldb] Disable test_step_out_thunk on Windows On Windows we end up in assembly. Not sure if the thread plans behave differently or this is a debug info issue. I have no environment to reproduce and investigate this in, so I'm disabling the test for now. Added: Modified: lldb/test/API/lang/cpp/thunk/TestThunk.py Removed: diff --git a/lldb/test/API/lang/cpp/thunk/TestThunk.py b/lldb/test/API/lang/cpp/thunk/TestThunk.py index ceb16263648d6..9370c1c58c18b 100644 --- a/lldb/test/API/lang/cpp/thunk/TestThunk.py +++ b/lldb/test/API/lang/cpp/thunk/TestThunk.py @@ -24,6 +24,7 @@ def test_step_through_thunk(self): substrs=["stop reason = step in", "Derived2::doit"], ) +@skipIfWindows def test_step_out_thunk(self): self.build() lldbutil.run_to_name_breakpoint(self, "testit_debug") ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
@@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { medismailben wrote: nit: ```suggestion if (Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol) { ``` https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/medismailben approved this pull request. Nice! LGTM with comment. https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][RISCV] fix LR/SC handling in lldb-server (PR #127505)
https://github.com/dlav-sc edited https://github.com/llvm/llvm-project/pull/127505 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127419 >From c533d71a56fa7d6347b1698c63c8626513e70ab0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sun, 16 Feb 2025 13:27:07 -0800 Subject: [PATCH 1/7] [lldb] Support stepping over C++ thunks This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 --- lldb/include/lldb/Target/LanguageRuntime.h| 2 + .../CPlusPlus/CPPLanguageRuntime.cpp | 6 +++ .../CPlusPlus/CPPLanguageRuntime.h| 3 ++ .../Target/ThreadPlanShouldStopHere.cpp | 51 +++ lldb/test/API/lang/cpp/thunk/Makefile | 3 ++ lldb/test/API/lang/cpp/thunk/TestThunk.py | 24 + lldb/test/API/lang/cpp/thunk/main.cpp | 36 + 7 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 lldb/test/API/lang/cpp/thunk/Makefile create mode 100644 lldb/test/API/lang/cpp/thunk/TestThunk.py create mode 100644 lldb/test/API/lang/cpp/thunk/main.cpp diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..e648b9665bef6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..723d7965c3467 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) + should_stop_here = false; + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +122,34 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to step through it. bool just_step_out = false; -if (sc.symbol && sc.symbol->ValueIsAddress()) { - Address symbol_end = sc.symbol->GetAddress(); - symbol_end.Slide(sc.symbol->GetByteSize() - 1); - if (range.Cont
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
https://github.com/labath created https://github.com/llvm/llvm-project/pull/127519 The motivation is #123622 and the fact that is hard to fine the last line entry in a given range. `FindLineEntryByAddress(range_end-1)` is the best we have, but it's not ideal because it has a magic -1 and that it relies on there existing a line entry at that address (generally, it should be there, but if for some case it isn't, we might end up ignoring the entries that are there (or -- like my incorrect fix in #123622 did -- iterating through the entire line table). What we really want is to get the last entry that exists in the given range. Or, equivalently (and more STL-like) the first entry after that range. This is what these functions do. I've used the STL names since they do pretty much exactly what the standard functions do (the main head-scratcher comes from the fact that our entries represent ranges rather than single values). The functions can also be used to simplify the maze of `if` statements in `FindLineEntryByAddress`, but I'm keeping that as a separate patch. For now, I'm just adding some unit testing for that function to gain more confidence that the patch does not change the function behavior. >From eedf83a50503967244ffad1fdcb7ecb43e312c49 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 17 Feb 2025 17:29:40 +0100 Subject: [PATCH] [lldb] Add LineTable::{upper,lower}_bound The motivation is #123622 and the fact that is hard to fine the last line entry in a given range. `FindLineEntryByAddress(range_end-1)` is the best we have, but it's not ideal because it has a magic -1 and that it relies on there existing a line entry at that address (generally, it should be there, but if for some case it isn't, we might end up ignoring the entries that are there (or -- like my incorrect fix in #123622 did -- iterating through the entire line table). What we really want is to get the last entry that exists in the given range. Or, equivalently (and more STL-like) the first entry after that range. This is what these functions do. I've used the STL names since they do pretty much exactly what the standard functions do (the main head-scratcher comes from the fact that our entries represent ranges rather than single values). The functions can also be used to simplify the maze of `if` statements in `FindLineEntryByAddress`, but I'm keeping that as a separate patch. For now, I'm just adding some unit testing for that function to gain more confidence that the patch does not change the function behavior. --- lldb/include/lldb/Symbol/LineTable.h| 13 ++ lldb/source/Symbol/LineTable.cpp| 44 +++- lldb/unittests/Symbol/CMakeLists.txt| 1 + lldb/unittests/Symbol/LineTableTest.cpp | 286 4 files changed, 343 insertions(+), 1 deletion(-) create mode 100644 lldb/unittests/Symbol/LineTableTest.cpp diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h index 6d158ab518879..2d7a6310758a9 100644 --- a/lldb/include/lldb/Symbol/LineTable.h +++ b/lldb/include/lldb/Symbol/LineTable.h @@ -102,6 +102,19 @@ class LineTable { void GetDescription(Stream *s, Target *target, lldb::DescriptionLevel level); + /// Helper function for line table iteration. \c lower_bound returns the index + /// of the first line entry which ends after the given address (i.e., the + /// first entry which contains the given address or it comes after it). + /// \c upper_bound returns the index of the first line entry which begins on + /// or after the given address (i.e., the entry which would come after the entry + /// containing the given address, if such an entry exists). Functions return + /// GetSize() if there is no such entry. + /// The functions are most useful in combination: iterating from + /// lower_bound(a) to upper_bound(b) returns all line tables + /// which intersect the half-open range [a,b). + uint32_t lower_bound(const Address &so_addr) const; + uint32_t upper_bound(const Address &so_addr) const; + /// Find a line entry that contains the section offset address \a so_addr. /// /// \param[in] so_addr diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 3d2afcdd11997..c9cad0cb30d73 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -123,7 +123,7 @@ void LineTable::InsertSequence(LineSequence *sequence) { entry_collection::iterator end_pos = m_entries.end(); LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); entry_collection::iterator pos = - upper_bound(begin_pos, end_pos, entry, less_than_bp); + std::upper_bound(begin_pos, end_pos, entry, less_than_bp); // We should never insert a sequence in the middle of another sequence if (pos != begin_pos) { @@ -185,6 +185,48 @@ bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { return false; } +uint32_t LineTable::lower_bound(const Address &so
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/127519 >From 627bb23342ee22dd263f0142ea43f644afd6faae Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 17 Feb 2025 17:29:40 +0100 Subject: [PATCH] [lldb] Add LineTable::{upper,lower}_bound The motivation is #123622 and the fact that is hard to fine the last line entry in a given range. `FindLineEntryByAddress(range_end-1)` is the best we have, but it's not ideal because it has a magic -1 and that it relies on there existing a line entry at that address (generally, it should be there, but if for some case it isn't, we might end up ignoring the entries that are there (or -- like my incorrect fix in #123622 did -- iterating through the entire line table). What we really want is to get the last entry that exists in the given range. Or, equivalently (and more STL-like) the first entry after that range. This is what these functions do. I've used the STL names since they do pretty much exactly what the standard functions do (the main head-scratcher comes from the fact that our entries represent ranges rather than single values). The functions can also be used to simplify the maze of `if` statements in `FindLineEntryByAddress`, but I'm keeping that as a separate patch. For now, I'm just adding some unit testing for that function to gain more confidence that the patch does not change the function behavior. --- lldb/include/lldb/Symbol/LineTable.h| 13 ++ lldb/source/Symbol/LineTable.cpp| 46 +++- lldb/unittests/Symbol/CMakeLists.txt| 1 + lldb/unittests/Symbol/LineTableTest.cpp | 285 4 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 lldb/unittests/Symbol/LineTableTest.cpp diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h index 6d158ab518879..f66081b6ee110 100644 --- a/lldb/include/lldb/Symbol/LineTable.h +++ b/lldb/include/lldb/Symbol/LineTable.h @@ -102,6 +102,19 @@ class LineTable { void GetDescription(Stream *s, Target *target, lldb::DescriptionLevel level); + /// Helper function for line table iteration. \c lower_bound returns the index + /// of the first line entry which ends after the given address (i.e., the + /// first entry which contains the given address or it comes after it). + /// \c upper_bound returns the index of the first line entry which begins on + /// or after the given address (i.e., the entry which would come after the + /// entry containing the given address, if such an entry exists). Functions + /// return GetSize() if there is no such entry. The functions are + /// most useful in combination: iterating from lower_bound(a) to + /// upper_bound(b) returns all line tables which intersect the half-open + /// range [a,b). + uint32_t lower_bound(const Address &so_addr) const; + uint32_t upper_bound(const Address &so_addr) const; + /// Find a line entry that contains the section offset address \a so_addr. /// /// \param[in] so_addr diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 3d2afcdd11997..aae4ab59ff156 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -123,7 +123,7 @@ void LineTable::InsertSequence(LineSequence *sequence) { entry_collection::iterator end_pos = m_entries.end(); LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); entry_collection::iterator pos = - upper_bound(begin_pos, end_pos, entry, less_than_bp); + std::upper_bound(begin_pos, end_pos, entry, less_than_bp); // We should never insert a sequence in the middle of another sequence if (pos != begin_pos) { @@ -185,6 +185,48 @@ bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { return false; } +uint32_t LineTable::lower_bound(const Address &so_addr) const { + if (so_addr.GetModule() != m_comp_unit->GetModule()) +return GetSize(); + + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr == LLDB_INVALID_ADDRESS) +return GetSize(); + + // This is not a typo. upper_bound returns the first entry which definitely + // does not contain this address, which means the entry before it *might* + // contain it -- if it is not a termination entry. + auto pos = + llvm::upper_bound(m_entries, search_entry, Entry::EntryAddressLessThan); + + if (pos != m_entries.begin() && !std::prev(pos)->is_terminal_entry) +--pos; + + return std::distance(m_entries.begin(), pos); +} + +uint32_t LineTable::upper_bound(const Address &so_addr) const { + if (so_addr.GetModule() != m_comp_unit->GetModule()) +return GetSize(); + + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr == LLDB_INVALID_ADDRESS) +return GetSize(); + + // This is not a typo. lower_bound returns the first entry which starts on or + // after the given address, which is exactly what we want --
[Lldb-commits] [lldb] [lldb] Synchronize the debugger's stdout and stderr streams (PR #126630)
@@ -574,10 +581,10 @@ int Editline::GetCharacter(EditLineGetCharType *c) { // indefinitely. This gives a chance for someone to interrupt us. After // Read returns, immediately lock the mutex again and check if we were // interrupted. -m_output_mutex.unlock(); +m_output_stream_sp->GetMutex().unlock(); JDevlieghere wrote: Just hadn't gotten around to it. I've pushed a commit that adds this. https://github.com/llvm/llvm-project/pull/126630 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere closed https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] a3dc77c - [lldb] Support stepping through C++ thunks (#127419)
Author: Jonas Devlieghere Date: 2025-02-17T15:44:41-08:00 New Revision: a3dc77c00a012bb613cb08e669dab4fadf88e935 URL: https://github.com/llvm/llvm-project/commit/a3dc77c00a012bb613cb08e669dab4fadf88e935 DIFF: https://github.com/llvm/llvm-project/commit/a3dc77c00a012bb613cb08e669dab4fadf88e935.diff LOG: [lldb] Support stepping through C++ thunks (#127419) This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 Added: lldb/test/API/lang/cpp/thunk/Makefile lldb/test/API/lang/cpp/thunk/TestThunk.py lldb/test/API/lang/cpp/thunk/main.cpp Modified: lldb/include/lldb/Target/LanguageRuntime.h lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h lldb/source/Target/ThreadPlanShouldStopHere.cpp Removed: diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..21a5ebe53073a 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,14 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::StringRef mangled_name = + symbol.GetMangled().GetMangledName().GetStringRef(); + // Virtual function overriding from a non-virtual base use a "Th" prefix. + // Virtual function overriding from a virtual base must use a "Tv" prefix. + // Virtual function overriding thunks with covariant returns use a "Tc" + // prefix. + return mangled_name.starts_with("_ZTh") || mangled_name.starts_with("_ZTv") || + mangled_name.starts_with("_ZTc"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..fa6bc08a9914d 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,19 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +if (Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) { + should_stop_here = false; + break; +} + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +123,35 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to
[Lldb-commits] [lldb] Allow option to ignore module load errors in ScriptedProcess (PR #127153)
rchamala wrote: > I'm not convinced of that this change needs to be happen in ScriptedProcess .. Just so that we’re on the same page, the logic to skip loading modules upon a module load error is part of ScriptedProcess conversion logic in “scriptedprocess::GetLoadedDynamicLibrariesInfos”. The method does not call target to load modules upon a single module load error. Can you please expand your thoughts on why this change should not be part of ScriptedProcess ? https://github.com/llvm/llvm-project/pull/127153 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)
@@ -0,0 +1,284 @@ +//===-- DILEval.cpp ---===// +// +// 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 +// +//===--===// + +#include "lldb/ValueObject/DILEval.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/ValueObject/DILAST.h" +#include "lldb/ValueObject/ValueObject.h" +#include "lldb/ValueObject/ValueObjectRegister.h" +#include "lldb/ValueObject/ValueObjectVariable.h" +#include "llvm/Support/FormatAdapters.h" +#include + +namespace lldb_private::dil { + +static lldb::ValueObjectSP +LookupStaticIdentifier(lldb::TargetSP target_sp, + const llvm::StringRef &name_ref, + ConstString unqualified_name) { + // List global variable with the same "basename". There can be many matches + // from other scopes (namespaces, classes), so we do additional filtering + // later. + VariableList variable_list; + ConstString name(name_ref); + target_sp->GetImages().FindGlobalVariables(name, 1, variable_list); + if (variable_list.Empty()) +return nullptr; + + ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get(); + if (exe_scope == nullptr) +exe_scope = target_sp.get(); + for (const lldb::VariableSP &var_sp : variable_list) { +lldb::ValueObjectSP valobj_sp( +ValueObjectVariable::Create(exe_scope, var_sp)); +if (valobj_sp && valobj_sp->GetVariable() && +(valobj_sp->GetVariable()->NameMatches(unqualified_name) || + valobj_sp->GetVariable()->NameMatches(ConstString(name_ref + return valobj_sp; + } + + return nullptr; +} + +static lldb::VariableSP DILFindVariable(ConstString name, +VariableList *variable_list) { + lldb::VariableSP exact_match; + std::vector possible_matches; + + typedef std::vector collection; + typedef collection::iterator iterator; + + iterator pos, end = variable_list->end(); + for (pos = variable_list->begin(); pos != end; ++pos) { +llvm::StringRef str_ref_name = pos->get()->GetName().GetStringRef(); +// Check for global vars, which might start with '::'. +str_ref_name.consume_front("::"); + +if (str_ref_name == name.GetStringRef()) + possible_matches.push_back(*pos); +else if (pos->get()->NameMatches(name)) + possible_matches.push_back(*pos); + } + + // Look for exact matches (favors local vars over global vars) + auto exact_match_it = + llvm::find_if(possible_matches, [&](lldb::VariableSP var_sp) { +return var_sp->GetName() == name; + }); + + if (exact_match_it != llvm::adl_end(possible_matches)) +exact_match = *exact_match_it; + + if (!exact_match) +// Look for a global var exact match. +for (auto var_sp : possible_matches) { + llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef(); + if (str_ref_name.size() > 2 && str_ref_name[0] == ':' && + str_ref_name[1] == ':') +str_ref_name = str_ref_name.drop_front(2); + ConstString tmp_name(str_ref_name); + if (tmp_name == name) { +exact_match = var_sp; +break; + } +} + + // Take any match at this point. + if (!exact_match && possible_matches.size() > 0) +exact_match = possible_matches[0]; + + return exact_match; +} + +std::unique_ptr +LookupIdentifier(const std::string &name, + std::shared_ptr ctx_scope, + lldb::DynamicValueType use_dynamic, CompilerType *scope_ptr) { + ConstString name_str(name); + llvm::StringRef name_ref = name_str.GetStringRef(); + + // Support $rax as a special syntax for accessing registers. + // Will return an invalid value in case the requested register doesn't exist. + if (name_ref.starts_with("$")) { +lldb::ValueObjectSP value_sp; +const char *reg_name = name_ref.drop_front(1).data(); +Target *target = ctx_scope->CalculateTarget().get(); +Process *process = ctx_scope->CalculateProcess().get(); +if (!target || !process) + return nullptr; + +StackFrame *stack_frame = ctx_scope->CalculateStackFrame().get(); +if (!stack_frame) + return nullptr; + +lldb::RegisterContextSP reg_ctx(stack_frame->GetRegisterContext()); +if (!reg_ctx) + return nullptr; + +if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name)) + value_sp = ValueObjectRegister::Create(stack_frame, reg_ctx, reg_info); + +if (value_sp) + return IdentifierInfo::FromValue(*value_sp); + +return nullptr; + } + + // Internally values don't have global scope qualifier in their names and + // LLDB doesn't support queries with it too. + bool global_scope = false; + if (name_ref.starts_with("::")) { +name_ref = na
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
https://github.com/JDevlieghere approved this pull request. Thanks for taking the time to add the `FakeSymbolFile`, I'm sure that'll be valuable in the future. LGTM. https://github.com/llvm/llvm-project/pull/127519 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
@@ -185,6 +185,48 @@ bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { return false; } +uint32_t LineTable::lower_bound(const Address &so_addr) const { + if (so_addr.GetModule() != m_comp_unit->GetModule()) +return GetSize(); + + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr == LLDB_INVALID_ADDRESS) +return GetSize(); + + // This is not a typo. upper_bound returns the first entry which definitely + // does not contain this address, which means the entry before it *might* + // contain it -- if it is not a termination entry. + auto pos = + llvm::upper_bound(m_entries, search_entry, Entry::EntryAddressLessThan); + + if (pos != m_entries.begin() && !std::prev(pos)->is_terminal_entry) +--pos; + + return std::distance(m_entries.begin(), pos); JDevlieghere wrote: I assume you're returning the index rather than the iterator because that's easier to test in the unit test? https://github.com/llvm/llvm-project/pull/127519 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
@@ -0,0 +1,285 @@ +//===-- LineTableTest.cpp -===// +// +// 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 +// +//===--===// + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" +#include "TestingSupport/SubsystemRAII.h" +#include "TestingSupport/TestUtilities.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/SymbolFile.h" +#include "gtest/gtest.h" +#include + +using namespace lldb; +using namespace llvm; +using namespace lldb_private; + +namespace { + +// A fake symbol file class to allow us to create the line table "the right +// way". Pretty much all methods except for GetCompileUnitAtIndex and +// GetNumCompileUnits are stubbed out. +class FakeSymbolFile : public SymbolFile { +public: + /// LLVM RTTI support. + /// \{ + bool isA(const void *ClassID) const override { +return ClassID == &ID || SymbolFile::isA(ClassID); + } + static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } + /// \} + + static void Initialize() { +PluginManager::RegisterPlugin("FakeSymbolFile", "", CreateInstance, + DebuggerInitialize); + } + static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } + + void InjectCompileUnit(std::unique_ptr cu_up) { +m_cu_sp = std::move(cu_up); + } + +private: + /// LLVM RTTI support. + static char ID; + + static SymbolFile *CreateInstance(ObjectFileSP objfile_sp) { +return new FakeSymbolFile(std::move(objfile_sp)); + } + static void DebuggerInitialize(Debugger &) {} + + StringRef GetPluginName() override { return "FakeSymbolFile"; } + uint32_t GetAbilities() override { return UINT32_MAX; } + uint32_t CalculateAbilities() override { return UINT32_MAX; } + uint32_t GetNumCompileUnits() override { return 1; } + CompUnitSP GetCompileUnitAtIndex(uint32_t) override { return m_cu_sp; } + Symtab *GetSymtab() override { return nullptr; } + LanguageType ParseLanguage(CompileUnit &) override { return eLanguageTypeC; } + size_t ParseFunctions(CompileUnit &) override { return 0; } + bool ParseLineTable(CompileUnit &) override { return true; } + bool ParseDebugMacros(CompileUnit &) override { return true; } + bool ParseSupportFiles(CompileUnit &, SupportFileList &) override { +return true; + } + size_t ParseTypes(CompileUnit &) override { return 0; } + bool ParseImportedModules(const SymbolContext &, +std::vector &) override { +return false; + } + size_t ParseBlocksRecursive(Function &) override { return 0; } + size_t ParseVariablesForContext(const SymbolContext &) override { return 0; } + Type *ResolveTypeUID(user_id_t) override { return nullptr; } + std::optional + GetDynamicArrayInfoForUID(user_id_t, const ExecutionContext *) override { +return std::nullopt; + } + bool CompleteType(CompilerType &) override { return true; } + uint32_t ResolveSymbolContext(const Address &, SymbolContextItem, +SymbolContext &) override { +return 0; + } + void GetTypes(SymbolContextScope *, TypeClass, TypeList &) override {} + Expected GetTypeSystemForLanguage(LanguageType) override { +return createStringError(std::errc::not_supported, ""); + } + const ObjectFile *GetObjectFile() const override { +return m_objfile_sp.get(); + } + ObjectFile *GetObjectFile() override { return m_objfile_sp.get(); } + ObjectFile *GetMainObjectFile() override { return m_objfile_sp.get(); } + void SectionFileAddressesChanged() override {} + void Dump(Stream &) override {} + uint64_t GetDebugInfoSize(bool) override { return 0; } + bool GetDebugInfoIndexWasLoadedFromCache() const override { return false; } + void SetDebugInfoIndexWasLoadedFromCache() override {} + bool GetDebugInfoIndexWasSavedToCache() const override { return false; } + void SetDebugInfoIndexWasSavedToCache() override {} + bool GetDebugInfoHadFrameVariableErrors() const override { return false; } + void SetDebugInfoHadFrameVariableErrors() override {} + TypeSP MakeType(user_id_t, ConstString, std::optional, + SymbolContextScope *, user_id_t, Type::EncodingDataType, + const Declaration &, const CompilerType &, Type::ResolveState, + uint32_t) override { +return nullptr; + } + TypeSP CopyType(const TypeSP &) override { return nullptr; } + + FakeSymbolFile(ObjectFileSP objfile_sp) + : m_objfile_sp(std::move(objfile_sp)) {} + + ObjectFileSP m_objfile_sp; + CompUnitSP m_cu_sp; +}; + +struct FakeModuleFixture { + TestFile file; + ModuleSP module_sp; + SectionSP text_sp; + LineTable *line_table; +}; + +class LineTableTest : public testing::Test { + SubsystemRAII subsys
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
@@ -0,0 +1,285 @@ +//===-- LineTableTest.cpp -===// +// +// 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 +// +//===--===// + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" +#include "TestingSupport/SubsystemRAII.h" +#include "TestingSupport/TestUtilities.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/SymbolFile.h" +#include "gtest/gtest.h" +#include + +using namespace lldb; +using namespace llvm; +using namespace lldb_private; + +namespace { + +// A fake symbol file class to allow us to create the line table "the right +// way". Pretty much all methods except for GetCompileUnitAtIndex and +// GetNumCompileUnits are stubbed out. +class FakeSymbolFile : public SymbolFile { +public: + /// LLVM RTTI support. + /// \{ + bool isA(const void *ClassID) const override { +return ClassID == &ID || SymbolFile::isA(ClassID); + } + static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } + /// \} + + static void Initialize() { +PluginManager::RegisterPlugin("FakeSymbolFile", "", CreateInstance, + DebuggerInitialize); + } + static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } + + void InjectCompileUnit(std::unique_ptr cu_up) { +m_cu_sp = std::move(cu_up); + } + +private: + /// LLVM RTTI support. + static char ID; + + static SymbolFile *CreateInstance(ObjectFileSP objfile_sp) { +return new FakeSymbolFile(std::move(objfile_sp)); + } + static void DebuggerInitialize(Debugger &) {} + + StringRef GetPluginName() override { return "FakeSymbolFile"; } + uint32_t GetAbilities() override { return UINT32_MAX; } + uint32_t CalculateAbilities() override { return UINT32_MAX; } + uint32_t GetNumCompileUnits() override { return 1; } + CompUnitSP GetCompileUnitAtIndex(uint32_t) override { return m_cu_sp; } + Symtab *GetSymtab() override { return nullptr; } + LanguageType ParseLanguage(CompileUnit &) override { return eLanguageTypeC; } + size_t ParseFunctions(CompileUnit &) override { return 0; } + bool ParseLineTable(CompileUnit &) override { return true; } + bool ParseDebugMacros(CompileUnit &) override { return true; } + bool ParseSupportFiles(CompileUnit &, SupportFileList &) override { +return true; + } + size_t ParseTypes(CompileUnit &) override { return 0; } + bool ParseImportedModules(const SymbolContext &, +std::vector &) override { +return false; + } + size_t ParseBlocksRecursive(Function &) override { return 0; } + size_t ParseVariablesForContext(const SymbolContext &) override { return 0; } + Type *ResolveTypeUID(user_id_t) override { return nullptr; } + std::optional + GetDynamicArrayInfoForUID(user_id_t, const ExecutionContext *) override { +return std::nullopt; + } + bool CompleteType(CompilerType &) override { return true; } + uint32_t ResolveSymbolContext(const Address &, SymbolContextItem, +SymbolContext &) override { +return 0; + } + void GetTypes(SymbolContextScope *, TypeClass, TypeList &) override {} + Expected GetTypeSystemForLanguage(LanguageType) override { +return createStringError(std::errc::not_supported, ""); + } + const ObjectFile *GetObjectFile() const override { +return m_objfile_sp.get(); + } + ObjectFile *GetObjectFile() override { return m_objfile_sp.get(); } + ObjectFile *GetMainObjectFile() override { return m_objfile_sp.get(); } + void SectionFileAddressesChanged() override {} + void Dump(Stream &) override {} + uint64_t GetDebugInfoSize(bool) override { return 0; } + bool GetDebugInfoIndexWasLoadedFromCache() const override { return false; } + void SetDebugInfoIndexWasLoadedFromCache() override {} + bool GetDebugInfoIndexWasSavedToCache() const override { return false; } + void SetDebugInfoIndexWasSavedToCache() override {} + bool GetDebugInfoHadFrameVariableErrors() const override { return false; } + void SetDebugInfoHadFrameVariableErrors() override {} + TypeSP MakeType(user_id_t, ConstString, std::optional, + SymbolContextScope *, user_id_t, Type::EncodingDataType, + const Declaration &, const CompilerType &, Type::ResolveState, + uint32_t) override { +return nullptr; + } + TypeSP CopyType(const TypeSP &) override { return nullptr; } + + FakeSymbolFile(ObjectFileSP objfile_sp) + : m_objfile_sp(std::move(objfile_sp)) {} + + ObjectFileSP m_objfile_sp; + CompUnitSP m_cu_sp; +}; + +struct FakeModuleFixture { + TestFile file; + ModuleSP module_sp; + SectionSP text_sp; + LineTable *line_table; +}; + +class LineTableTest : public testing::Test { + SubsystemRAII subsys
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
https://github.com/JDevlieghere edited https://github.com/llvm/llvm-project/pull/127519 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127419 >From c533d71a56fa7d6347b1698c63c8626513e70ab0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sun, 16 Feb 2025 13:27:07 -0800 Subject: [PATCH 1/9] [lldb] Support stepping over C++ thunks This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 --- lldb/include/lldb/Target/LanguageRuntime.h| 2 + .../CPlusPlus/CPPLanguageRuntime.cpp | 6 +++ .../CPlusPlus/CPPLanguageRuntime.h| 3 ++ .../Target/ThreadPlanShouldStopHere.cpp | 51 +++ lldb/test/API/lang/cpp/thunk/Makefile | 3 ++ lldb/test/API/lang/cpp/thunk/TestThunk.py | 24 + lldb/test/API/lang/cpp/thunk/main.cpp | 36 + 7 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 lldb/test/API/lang/cpp/thunk/Makefile create mode 100644 lldb/test/API/lang/cpp/thunk/TestThunk.py create mode 100644 lldb/test/API/lang/cpp/thunk/main.cpp diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..e648b9665bef6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..723d7965c3467 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) + should_stop_here = false; + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +122,34 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to step through it. bool just_step_out = false; -if (sc.symbol && sc.symbol->ValueIsAddress()) { - Address symbol_end = sc.symbol->GetAddress(); - symbol_end.Slide(sc.symbol->GetByteSize() - 1); - if (range.Cont
[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)
@@ -0,0 +1,285 @@ +//===-- LineTableTest.cpp -===// +// +// 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 +// +//===--===// + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" +#include "TestingSupport/SubsystemRAII.h" +#include "TestingSupport/TestUtilities.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/SymbolFile.h" +#include "gtest/gtest.h" +#include + +using namespace lldb; +using namespace llvm; +using namespace lldb_private; + +namespace { + +// A fake symbol file class to allow us to create the line table "the right +// way". Pretty much all methods except for GetCompileUnitAtIndex and +// GetNumCompileUnits are stubbed out. +class FakeSymbolFile : public SymbolFile { +public: + /// LLVM RTTI support. + /// \{ + bool isA(const void *ClassID) const override { +return ClassID == &ID || SymbolFile::isA(ClassID); + } + static bool classof(const SymbolFile *obj) { return obj->isA(&ID); } + /// \} + + static void Initialize() { +PluginManager::RegisterPlugin("FakeSymbolFile", "", CreateInstance, + DebuggerInitialize); + } + static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } + + void InjectCompileUnit(std::unique_ptr cu_up) { +m_cu_sp = std::move(cu_up); + } + +private: + /// LLVM RTTI support. + static char ID; + + static SymbolFile *CreateInstance(ObjectFileSP objfile_sp) { +return new FakeSymbolFile(std::move(objfile_sp)); + } + static void DebuggerInitialize(Debugger &) {} + + StringRef GetPluginName() override { return "FakeSymbolFile"; } + uint32_t GetAbilities() override { return UINT32_MAX; } + uint32_t CalculateAbilities() override { return UINT32_MAX; } + uint32_t GetNumCompileUnits() override { return 1; } + CompUnitSP GetCompileUnitAtIndex(uint32_t) override { return m_cu_sp; } + Symtab *GetSymtab() override { return nullptr; } + LanguageType ParseLanguage(CompileUnit &) override { return eLanguageTypeC; } + size_t ParseFunctions(CompileUnit &) override { return 0; } + bool ParseLineTable(CompileUnit &) override { return true; } + bool ParseDebugMacros(CompileUnit &) override { return true; } + bool ParseSupportFiles(CompileUnit &, SupportFileList &) override { +return true; + } + size_t ParseTypes(CompileUnit &) override { return 0; } + bool ParseImportedModules(const SymbolContext &, +std::vector &) override { +return false; + } + size_t ParseBlocksRecursive(Function &) override { return 0; } + size_t ParseVariablesForContext(const SymbolContext &) override { return 0; } + Type *ResolveTypeUID(user_id_t) override { return nullptr; } + std::optional + GetDynamicArrayInfoForUID(user_id_t, const ExecutionContext *) override { +return std::nullopt; + } + bool CompleteType(CompilerType &) override { return true; } + uint32_t ResolveSymbolContext(const Address &, SymbolContextItem, +SymbolContext &) override { +return 0; + } + void GetTypes(SymbolContextScope *, TypeClass, TypeList &) override {} + Expected GetTypeSystemForLanguage(LanguageType) override { +return createStringError(std::errc::not_supported, ""); + } + const ObjectFile *GetObjectFile() const override { +return m_objfile_sp.get(); + } + ObjectFile *GetObjectFile() override { return m_objfile_sp.get(); } + ObjectFile *GetMainObjectFile() override { return m_objfile_sp.get(); } + void SectionFileAddressesChanged() override {} + void Dump(Stream &) override {} + uint64_t GetDebugInfoSize(bool) override { return 0; } + bool GetDebugInfoIndexWasLoadedFromCache() const override { return false; } + void SetDebugInfoIndexWasLoadedFromCache() override {} + bool GetDebugInfoIndexWasSavedToCache() const override { return false; } + void SetDebugInfoIndexWasSavedToCache() override {} + bool GetDebugInfoHadFrameVariableErrors() const override { return false; } + void SetDebugInfoHadFrameVariableErrors() override {} + TypeSP MakeType(user_id_t, ConstString, std::optional, + SymbolContextScope *, user_id_t, Type::EncodingDataType, + const Declaration &, const CompilerType &, Type::ResolveState, + uint32_t) override { +return nullptr; + } + TypeSP CopyType(const TypeSP &) override { return nullptr; } + + FakeSymbolFile(ObjectFileSP objfile_sp) + : m_objfile_sp(std::move(objfile_sp)) {} + + ObjectFileSP m_objfile_sp; + CompUnitSP m_cu_sp; +}; + +struct FakeModuleFixture { + TestFile file; + ModuleSP module_sp; + SectionSP text_sp; + LineTable *line_table; +}; + +class LineTableTest : public testing::Test { + SubsystemRAII subsys
[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)
@@ -0,0 +1,308 @@ +//===-- DILParser.cpp -===// +// +// 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 +// +// This implements the recursive descent parser for the Data Inspection +// Language (DIL), and its helper functions, which will eventually underlie the +// 'frame variable' command. The language that this parser recognizes is +// described in lldb/docs/dil-expr-lang.ebnf +// +//===--===// + +#include "lldb/ValueObject/DILParser.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/ValueObject/DILAST.h" +#include "lldb/ValueObject/DILEval.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FormatAdapters.h" +#include +#include +#include +#include +#include + +namespace lldb_private::dil { + +inline void TokenKindsJoinImpl(std::ostringstream &os, Token::Kind k) { + os << "'" << Token::GetTokenName(k).str() << "'"; +} + +template +inline void TokenKindsJoinImpl(std::ostringstream &os, Token::Kind k, + Ts... ks) { + TokenKindsJoinImpl(os, k); + os << ", "; + TokenKindsJoinImpl(os, ks...); +} + +template +inline std::string TokenKindsJoin(Token::Kind k, Ts... ks) { + std::ostringstream os; + TokenKindsJoinImpl(os, k, ks...); + + return os.str(); +} + +std::string FormatDiagnostics(llvm::StringRef text, const std::string &message, + uint32_t loc) { + // Get the source buffer and the location of the current token. + size_t loc_offset = (size_t)loc; + + // Look for the start of the line. + size_t line_start = text.rfind('\n', loc_offset); + line_start = line_start == llvm::StringRef::npos ? 0 : line_start + 1; + + // Look for the end of the line. + size_t line_end = text.find('\n', loc_offset); + line_end = line_end == llvm::StringRef::npos ? text.size() : line_end; + + // Get a view of the current line in the source code and the position of the + // diagnostics pointer. + llvm::StringRef line = text.slice(line_start, line_end); + int32_t arrow = loc + 1; // Column offset starts at 1, not 0. + + // Calculate the padding in case we point outside of the expression (this can + // happen if the parser expected something, but got EOF).˚ + size_t expr_rpad = std::max(0, arrow - static_cast(line.size())); + size_t arrow_rpad = std::max(0, static_cast(line.size()) - arrow); + + return llvm::formatv(": {1}\n{2}\n{3}", loc, message, + llvm::fmt_pad(line, 0, expr_rpad), + llvm::fmt_pad("^", arrow - 1, arrow_rpad)); cmtice wrote: llvm::fmt_pad requires a right-padding argument, so we need to supply one. https://github.com/llvm/llvm-project/pull/120971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Allow option to ignore module load errors in ScriptedProcess (PR #127153)
medismailben wrote: I'd like to get a better understanding of what you're trying to achieve: Does the child elf-core process doesn't have any module loaded ? Are they only described in the tombstone and require to be downloaded which could potentially fail ? https://github.com/llvm/llvm-project/pull/127153 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)
https://github.com/cmtice edited https://github.com/llvm/llvm-project/pull/120971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [LLDB] Add DIL code for handling plain variable names. (PR #120971)
@@ -0,0 +1,308 @@ +//===-- DILParser.cpp -===// +// +// 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 +// +// This implements the recursive descent parser for the Data Inspection +// Language (DIL), and its helper functions, which will eventually underlie the +// 'frame variable' command. The language that this parser recognizes is +// described in lldb/docs/dil-expr-lang.ebnf +// +//===--===// + +#include "lldb/ValueObject/DILParser.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/ValueObject/DILAST.h" +#include "lldb/ValueObject/DILEval.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FormatAdapters.h" +#include +#include +#include +#include +#include + +namespace lldb_private::dil { + +inline void TokenKindsJoinImpl(std::ostringstream &os, Token::Kind k) { + os << "'" << Token::GetTokenName(k).str() << "'"; +} + +template +inline void TokenKindsJoinImpl(std::ostringstream &os, Token::Kind k, + Ts... ks) { + TokenKindsJoinImpl(os, k); + os << ", "; + TokenKindsJoinImpl(os, ks...); +} + +template +inline std::string TokenKindsJoin(Token::Kind k, Ts... ks) { + std::ostringstream os; + TokenKindsJoinImpl(os, k, ks...); + + return os.str(); +} + +std::string FormatDiagnostics(llvm::StringRef text, const std::string &message, + uint32_t loc) { + // Get the source buffer and the location of the current token. + size_t loc_offset = (size_t)loc; + + // Look for the start of the line. + size_t line_start = text.rfind('\n', loc_offset); + line_start = line_start == llvm::StringRef::npos ? 0 : line_start + 1; + + // Look for the end of the line. + size_t line_end = text.find('\n', loc_offset); + line_end = line_end == llvm::StringRef::npos ? text.size() : line_end; + + // Get a view of the current line in the source code and the position of the + // diagnostics pointer. + llvm::StringRef line = text.slice(line_start, line_end); + int32_t arrow = loc + 1; // Column offset starts at 1, not 0. cmtice wrote: Looking at this further (now that I understand StringRefs better) I think I can simplify this quite a bit. https://github.com/llvm/llvm-project/pull/120971 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] fix LR/SC handling in lldb-server (PR #127505)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: None (dlav-sc) Changes lldb-server didn't consider that LR instruction may be followed not only by BNE instruction (takes 4 bytes), but by BNEZ too, which is a compressed instruction (takes 2 bytes). As a result, after BNEZ lldb-server reseived an incorrect PC value and couldn't parse the next instruction opcode. --- Full diff: https://github.com/llvm/llvm-project/pull/127505.diff 1 Files Affected: - (modified) lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp (+11-6) ``diff diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp index badc7ba36f011..e4de28d97d1ff 100644 --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -349,9 +349,10 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The second instruction should be BNE to exit address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The second instruction should be BNE or C.BNEZ to exit address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_exit = std::get(inst->decoded); @@ -359,15 +360,18 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; // save the exit address to check later const auto exit_pc = current_pc + SextW(bne_exit.imm); + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; // The third instruction should be SC.W or SC.D - inst = emulator.ReadInstructionAt(current_pc += 4); + inst = emulator.ReadInstructionAt(current_pc); if (!inst || (!std::holds_alternative(inst->decoded) && !std::holds_alternative(inst->decoded))) return false; + current_pc += 4; - // The fourth instruction should be BNE to entry address - inst = emulator.ReadInstructionAt(current_pc += 4); + // The fourth instruction should be BNE or C.BNEZ to entry address + inst = emulator.ReadInstructionAt(current_pc); if (!inst || !std::holds_alternative(inst->decoded)) return false; auto bne_start = std::get(inst->decoded); @@ -375,8 +379,9 @@ bool AtomicSequence(EmulateInstructionRISCV &emulator) { return false; if (entry_pc != current_pc + SextW(bne_start.imm)) return false; + // Can be C.BNEZ (2 bytes) or BNE (4 bytes) + current_pc += inst->is_rvc ? 2 : 4; - current_pc += 4; // check the exit address and jump to it return exit_pc == current_pc && emulator.WritePC(current_pc); } `` https://github.com/llvm/llvm-project/pull/127505 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Allow option to ignore module load errors in ScriptedProcess (PR #127153)
rchamala wrote: > I'd like to get a better understanding of what you're trying to achieve: > > Does the child elf-core process doesn't have any module loaded ? Are they > only described in the tombstone and require to be downloaded which could > potentially fail ? Child elf-core process has module information for shared libraries directly loaded from the shared library file(.so file) but does not have module information from the ones loaded from .apk. For an Android app runtime, some shared libraries are directly loaded from .so files and some are loaded from .apk. Apk is like a compressed file used by the installer to run the app and contains all artifacts needed to run the app which includes shared libraries. Due to the limitation in Android Kernel as explained [here](https://discourse.llvm.org/t/load-tombstones-and-coredumps-plugins-together-in-lldb/84190/19), the coredump generated from Android kernel does not dump program headers for the shared libraries in .apk. Note that Android linker when running the Android app, is able to understand the shared libraries inside .apk, can mmap the address of all shared libraries in _/proc/PID/maps_ correctly and can run the app correctly. [Tombstone](https://source.android.com/docs/core/tests/debug) is basically extracted from the live memory map in _/proc/PID/maps_, and has information about all shared libraries and their load addresses. Additionally, tombstone has thread names which are not contained in coredump. So, our design is as follows for the parent scripted process: 1. All the read memory api's to read memory regions from coredump file are used from child elf-core process 2. Get all modules(shared library name & load address), thread names from tombstone file We use [locate module callback](https://github.com/llvm/llvm-project/blob/a57e58dbfaae0e86eb5cafeddf8b598f14b96e36/lldb/source/Target/Platform.cpp#L1593) to fetch the module from our symbol server during lldb process creation. For scripted process, when we call [target.GetOrCreatemodule](https://github.com/llvm/llvm-project/blob/ed38d6702f7695092c9486016e2504f8c6bfef37/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp#L468C16-L468C33) the module callback is called to fetch the module from symbol server. When the symbol is not found or [when the module is already appended](https://github.com/llvm/llvm-project/blob/ed38d6702f7695092c9486016e2504f8c6bfef37/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp#L495), ScriptedProcess method GetLoadedDynamicLibrariesInfos is designed to fail and [skips loading all modules without loading to target](https://github.com/llvm/llvm-project/blob/ed38d6702f7695092c9486016e2504f8c6bfef37/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp#L498). Due to this, all modules end up not being loaded. My request is to return [the successful loaded modules in target](https://github.com/llvm/llvm-project/blob/ed38d6702f7695092c9486016e2504f8c6bfef37/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp#L502C10-L502C24) when ScriptedProcess is asked to get loaded dynamic libraries instead of returning nothing. Please let m e know if you have more questions https://github.com/llvm/llvm-project/pull/127153 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 6fde8fe - [lldb] Provide default impl for MightHaveChildren (NFC) (#119977)
Author: Dave Lee Date: 2025-02-17T11:19:14-08:00 New Revision: 6fde8fe9adc835df50ea57b710781ffe8a6657e8 URL: https://github.com/llvm/llvm-project/commit/6fde8fe9adc835df50ea57b710781ffe8a6657e8 DIFF: https://github.com/llvm/llvm-project/commit/6fde8fe9adc835df50ea57b710781ffe8a6657e8.diff LOG: [lldb] Provide default impl for MightHaveChildren (NFC) (#119977) The vast majority of `SyntheticChildrenFrontEnd` subclasses provide children, and as such implement `MightHaveChildren` with a constant value of `true`. This change makes `true` the default value. With this change, `MightHaveChildren` only needs to be implemented by synthetic providers that can return `false`, which is only 3 subclasses. Added: Modified: lldb/include/lldb/DataFormatters/TypeSynthetic.h lldb/include/lldb/DataFormatters/VectorIterator.h lldb/source/DataFormatters/VectorType.cpp lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp lldb/source/Plugins/Language/CPlusPlus/Coroutines.h lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp lldb/source/Plugins/Language/CPlusPlus/GenericOptional.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxx.h lldb/source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxProxyArray.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxRangesRefView.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxValarray.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp lldb/source/Plugins/Language/CPlusPlus/LibStdcppTuple.cpp lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp lldb/source/Plugins/Language/ObjC/NSArray.cpp lldb/source/Plugins/Language/ObjC/NSDictionary.cpp lldb/source/Plugins/Language/ObjC/NSError.cpp lldb/source/Plugins/Language/ObjC/NSException.cpp lldb/source/Plugins/Language/ObjC/NSSet.cpp Removed: diff --git a/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/lldb/include/lldb/DataFormatters/TypeSynthetic.h index bf6dc6a0c3c6b..14e516964f250 100644 --- a/lldb/include/lldb/DataFormatters/TypeSynthetic.h +++ b/lldb/include/lldb/DataFormatters/TypeSynthetic.h @@ -68,7 +68,7 @@ class SyntheticChildrenFrontEnd { // a false return value from this call if it returns true, then // CalculateNumChildren() can return any number >= 0 (0 being valid) it // should if at all possible be more efficient than CalculateNumChildren() - virtual bool MightHaveChildren() = 0; + virtual bool MightHaveChildren() { return true; } // if this function returns a non-null ValueObject, then the returned // ValueObject will stand for this ValueObject whenever a "value" request is diff --git a/lldb/include/lldb/DataFormatters/VectorIterator.h b/lldb/include/lldb/DataFormatters/VectorIterator.h index 70bcf50ca1b1d..d095f085cabab 100644 --- a/lldb/include/lldb/DataFormatters/VectorIterator.h +++ b/lldb/include/lldb/DataFormatters/VectorIterator.h @@ -30,8 +30,6 @@ class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { lldb::ChildCacheState Update() override; - bool MightHaveChildren() override; - size_t GetIndexOfChildWithName(ConstString name) override; private: diff --git a/lldb/source/DataFormatters/VectorType.cpp b/lldb/source/DataFormatters/VectorType.cpp index cba107b7da890..fa3fb1b674efb 100644 --- a/lldb/source/DataFormatters/VectorType.cpp +++ b/lldb/source/DataFormatters/VectorType.cpp @@ -268,8 +268,6 @@ class VectorTypeSyntheticFrontEnd : public SyntheticChildrenFrontEnd { return lldb::ChildCacheState::eRefetch; } - bool MightHaveChildren() override { return true; } - size_t GetIndexOfChildWithName(ConstString name) override { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); diff --git a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index d7d4654a6b5f4..6a22501c98aab 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -144,9 +144,6 @@ class BlockPointerSyntheticFrontEnd : public SyntheticChildre
[Lldb-commits] [lldb] [lldb] Provide default impl for MightHaveChildren (NFC) (PR #119977)
https://github.com/kastiglione closed https://github.com/llvm/llvm-project/pull/119977 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/medismailben edited https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Allow option to ignore module load errors in ScriptedProcess (PR #127153)
medismailben wrote: I'm not convinced of that this change needs to be happen in ScriptedProcess ... May be we could have a setting to not discard all modules loaded in case 1 of them failed to load that would also work with other Process plugins. @jimingham what do you think ? https://github.com/llvm/llvm-project/pull/127153 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127419 >From c533d71a56fa7d6347b1698c63c8626513e70ab0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sun, 16 Feb 2025 13:27:07 -0800 Subject: [PATCH 01/10] [lldb] Support stepping over C++ thunks This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 --- lldb/include/lldb/Target/LanguageRuntime.h| 2 + .../CPlusPlus/CPPLanguageRuntime.cpp | 6 +++ .../CPlusPlus/CPPLanguageRuntime.h| 3 ++ .../Target/ThreadPlanShouldStopHere.cpp | 51 +++ lldb/test/API/lang/cpp/thunk/Makefile | 3 ++ lldb/test/API/lang/cpp/thunk/TestThunk.py | 24 + lldb/test/API/lang/cpp/thunk/main.cpp | 36 + 7 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 lldb/test/API/lang/cpp/thunk/Makefile create mode 100644 lldb/test/API/lang/cpp/thunk/TestThunk.py create mode 100644 lldb/test/API/lang/cpp/thunk/main.cpp diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..e648b9665bef6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..723d7965c3467 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) + should_stop_here = false; + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +122,34 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to step through it. bool just_step_out = false; -if (sc.symbol && sc.symbol->ValueIsAddress()) { - Address symbol_end = sc.symbol->GetAddress(); - symbol_end.Slide(sc.symbol->GetByteSize() - 1); - if (range.Co
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/jimingham approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Synchronize the debugger's stdout and stderr streams (PR #126630)
JDevlieghere wrote: > That said, not needing to replicate the locking logic in every IOHandler > would definitely be nice. However, I'm not certain about the feasibility of > that. In a way, I think that the PrintAsync approach is better because it > lets the IOHandler know that some async printing is happening, and it can > choose how to deal with it. For example, the ProcessIOHandler (forwarding > stdout of the debugger proces) can end up in a state where the debugged > process has written only a half a line. If async printing is plumbed through > it, it will know that is happening, and it can choose to do something about > (print an extra newline to delimit process output, or maybe erase the last > output line, and then redraw it after the async output -- I don't know). Are you saying this is how it _could_ work? Looking at `IOHandlerProcessSTDIO`, it doesn't implement `PrintAsync` so it's just using the default implementation which prints to the debugger output stream. > I'm not a mind reader nor a time traveller, but I have a feeling this is the > reason why the async functionality is implemented the way it is. Maybe that's > something we don't need? I think I could live without it. But if that is the > case, I would like to see it dismantled, at least partially. For example, do > you think it would be possible to change Debugger::PrintAsync to print the > output directly (after locking the stream and such) -- without going through > the IOHandlers and stuff? I ran the test suite with this change: ``` diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 65f0502143bc..7e306fd7dcf4 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1200,13 +1200,10 @@ bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type, } void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { - bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout); - if (!printed) { -LockableStreamFileSP stream_sp = -is_stdout ? m_output_stream_sp : m_error_stream_sp; -LockedStreamFile locked_stream = stream_sp->Lock(); -locked_stream.Write(s, len); - } + LockableStreamFileSP stream_sp = + is_stdout ? m_output_stream_sp : m_error_stream_sp; + LockedStreamFile locked_stream = stream_sp->Lock(); + locked_stream.Write(s, len); } llvm::StringRef Debugger::GetTopIOHandlerControlSequence(char ch) { ``` I'm not sure how representative it is to rely on the test suite for something like this, but I got one failure (`TestBreakpointCallbackCommandSource.py`) because we don't redraw the prompt. @labath After reading your last message I'm not sure where you want to take this. I understand the desire to not have two ways of doing things, but I don't necessarily see how they have to be tied together. I'm convinced that protecting the underlying streams is a net benefit. We were doing that in an ad-hoc way in the IOHandler previously and this moves it up a level. If that means we can improve other things (like the asynchronous IOHandler) then I'm happy to continue chipping away at this, but your earlier message sounds like you're proposing that as an alternative and I'm not sure I fully understand what you have in mind. https://github.com/llvm/llvm-project/pull/126630 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] a377cdd - [lldb][TypeSystemClang] Add support for floating point template argument constants (#127206)
Author: Michael Buch Date: 2025-02-17T22:03:53Z New Revision: a377cdd23db180b881f54fc7f88bf3aa85de21cc URL: https://github.com/llvm/llvm-project/commit/a377cdd23db180b881f54fc7f88bf3aa85de21cc DIFF: https://github.com/llvm/llvm-project/commit/a377cdd23db180b881f54fc7f88bf3aa85de21cc.diff LOG: [lldb][TypeSystemClang] Add support for floating point template argument constants (#127206) This patch adds support for template arguments of `clang::TemplateArgument::ArgKind::StructuralValue` kind (added in https://github.com/llvm/llvm-project/pull/78041). These are used for non-type template parameters such as floating point constants. When LLDB created `clang::NonTypeTemplateParmDecl`s, it previously assumed integral values, this patch accounts for structural values too. Anywhere LLDB assumed a `DW_TAG_template_value_parameter` was `Integral`, it will now also check for `StructuralValue`, and will unpack the `TemplateArgument` value and type accordingly. We can rely on the fact that any `TemplateArgument` of `StructuralValue` kind that the `DWARFASTParserClang` creates will have a valid value, because it gets those from `DW_AT_const_value`. Added: Modified: lldb/include/lldb/Symbol/CompilerType.h lldb/source/API/SBType.cpp lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp lldb/test/API/lang/cpp/template-arguments/TestCppTemplateArguments.py lldb/test/API/lang/cpp/template-arguments/main.cpp lldb/unittests/Symbol/TestTypeSystemClang.cpp Removed: diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 096a8f1ab68e8..fe4fcbccee370 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -14,6 +14,7 @@ #include #include +#include "lldb/Utility/Scalar.h" #include "lldb/lldb-private.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/Casting.h" @@ -544,7 +545,7 @@ bool operator==(const CompilerType &lhs, const CompilerType &rhs); bool operator!=(const CompilerType &lhs, const CompilerType &rhs); struct CompilerType::IntegralTemplateArgument { - llvm::APSInt value; + Scalar value; CompilerType type; }; diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index 6401d32c85795..9eb1f0c75ea05 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -697,6 +697,7 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, std::optional arg; const bool expand_pack = true; switch (GetTemplateArgumentKind(idx)) { + case eTemplateArgumentKindStructuralValue: case eTemplateArgumentKindIntegral: arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument( idx, expand_pack); @@ -708,9 +709,8 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, if (!arg) return {}; - Scalar value{arg->value}; DataExtractor data; - value.GetData(data); + arg->value.GetData(data); ExecutionContext exe_ctx; auto target_sp = target.GetSP(); diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index f83f81fbdd1e7..934b456884ac0 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -90,7 +90,7 @@ lldb::ChildCacheState GenericBitsetFrontEnd::Update() { size_t size = 0; if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) -size = arg->value.getLimitedValue(); +size = arg->value.GetAPSInt().getLimitedValue(); m_elements.assign(size, ValueObjectSP()); m_first = diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp index ab3a5cf954ec7..21ee83041c065 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp @@ -117,7 +117,7 @@ lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { } else if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { - m_num_elements = arg->value.getLimitedValue(); + m_num_elements = arg->value.GetAPSInt().getLimitedValue(); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ec0004c70c6da..2d4d22559963f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1973,6 +1973,33 @@ class DWARFASTParserClang::DelayedAddObjCClassProperty { ClangASTMetadata m_metadata;
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
https://github.com/Michael137 closed https://github.com/llvm/llvm-project/pull/127206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/127419 >From c533d71a56fa7d6347b1698c63c8626513e70ab0 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Sun, 16 Feb 2025 13:27:07 -0800 Subject: [PATCH 1/8] [lldb] Support stepping over C++ thunks This PR fixes LLDB stepping out, rather than stepping through a C++ thunk. The implementation is based on, and upstreams, the support for runtime thunks in the Swift fork. Fixes #43413 --- lldb/include/lldb/Target/LanguageRuntime.h| 2 + .../CPlusPlus/CPPLanguageRuntime.cpp | 6 +++ .../CPlusPlus/CPPLanguageRuntime.h| 3 ++ .../Target/ThreadPlanShouldStopHere.cpp | 51 +++ lldb/test/API/lang/cpp/thunk/Makefile | 3 ++ lldb/test/API/lang/cpp/thunk/TestThunk.py | 24 + lldb/test/API/lang/cpp/thunk/main.cpp | 36 + 7 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 lldb/test/API/lang/cpp/thunk/Makefile create mode 100644 lldb/test/API/lang/cpp/thunk/TestThunk.py create mode 100644 lldb/test/API/lang/cpp/thunk/main.cpp diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h index f9ae2dc589632..7e4c11df0da7f 100644 --- a/lldb/include/lldb/Target/LanguageRuntime.h +++ b/lldb/include/lldb/Target/LanguageRuntime.h @@ -201,6 +201,8 @@ class LanguageRuntime : public Runtime, public PluginInterface { return false; } + virtual bool IsSymbolARuntimeThunk(const Symbol &symbol) { return false; } + // Given the name of a runtime symbol (e.g. in Objective-C, an ivar offset // symbol), try to determine from the runtime what the value of that symbol // would be. Useful when the underlying binary is stripped. diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 42fa54634841c..e648b9665bef6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( + "_ZThn"); +} diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h index 57cfe28245808..05639e9798917 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h @@ -78,6 +78,9 @@ class CPPLanguageRuntime : public LanguageRuntime { bool stop_others) override; bool IsAllowedRuntimeValue(ConstString name) override; + + bool IsSymbolARuntimeThunk(const Symbol &symbol) override; + protected: // Classes that inherit from CPPLanguageRuntime can see and modify these CPPLanguageRuntime(Process *process); diff --git a/lldb/source/Target/ThreadPlanShouldStopHere.cpp b/lldb/source/Target/ThreadPlanShouldStopHere.cpp index e72f8d8f51a20..723d7965c3467 100644 --- a/lldb/source/Target/ThreadPlanShouldStopHere.cpp +++ b/lldb/source/Target/ThreadPlanShouldStopHere.cpp @@ -8,6 +8,7 @@ #include "lldb/Target/ThreadPlanShouldStopHere.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/LLDBLog.h" @@ -76,6 +77,18 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( } } + // Check whether the frame we are in is a language runtime thunk, only for + // step out: + if (operation == eFrameCompareOlder) { +Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol; +if (symbol) { + ProcessSP process_sp(current_plan->GetThread().GetProcess()); + for (auto *runtime : process_sp->GetLanguageRuntimes()) { +if (runtime->IsSymbolARuntimeThunk(*symbol)) + should_stop_here = false; + } +} + } // Always avoid code with line number 0. // FIXME: At present the ShouldStop and the StepFromHere calculate this // independently. If this ever @@ -109,18 +122,34 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback( if (sc.line_entry.line == 0) { AddressRange range = sc.line_entry.range; - -// If the whole function is marked line 0 just step out, that's easier & -// faster than continuing to step through it. bool just_step_out = false; -if (sc.symbol && sc.symbol->ValueIsAddress()) { - Address symbol_end = sc.symbol->GetAddress(); - symbol_end.Slide(sc.symbol->GetByteSize() - 1); - if (range.Cont
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
@@ -476,3 +476,12 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + // Virtual function override thunks come in two forms. Those overriding from a + // non-virtual base, with fixed this adjustments, use a "Th" prefix and encode + // the required adjustment offset, probably negative, indicated by a 'n' + // prefix, and the encoding of the target function. + return symbol.GetMangled().GetMangledName().GetStringRef().starts_with( JDevlieghere wrote: I should've read the whole paragraph :-) https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Synchronize the debugger's stdout and stderr streams (PR #126630)
labath wrote: The buffering doesn't sound like a problem to me. Basically it means you have to use the stream like an RAII object, which is sort of what we have here anyway. We also have the same problem with not being able to get everything to use the RAII locker object from this patch (due to legacy reasons..) That said, not needing to replicate the locking logic in every IOHandler would definitely be nice. However, I'm not certain about the feasibility of that. In a way, I think that the PrintAsync approach is better because it lets the IOHandler know that some async printing is happening, and it can choose how to deal with it. For example, the ProcessIOHandler (forwarding stdout of the debugger proces) can end up in a state where the debugged process has written only a half a line. If async printing is plumbed through it, it will know that is happening, and it can choose to do something about (print an extra newline to delimit process output, or maybe erase the last output line, and then redraw it after the async output -- I don't know). I'm not a mind reader nor a time traveller, but I have a feeling this is the reason why the async functionality is implemented the way it is. Maybe that's something we don't need? I think I could live without it. But if that is the case, I would like to see it dismantled, at least partially. For example, do you think it would be possible to change Debugger::PrintAsync to print the output directly (after locking the stream and such) -- without going through the IOHandlers and stuff? https://github.com/llvm/llvm-project/pull/126630 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
https://github.com/Michael137 edited https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Support stepping through C++ thunks (PR #127419)
@@ -476,3 +476,9 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, return ret_plan_sp; } + +bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) { + llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; Michael137 wrote: ```suggestion llvm::outs() << symbol.GetMangled().GetMangledName().GetStringRef() << '\n'; ``` leftover debug? https://github.com/llvm/llvm-project/pull/127419 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/127206 >From 759f0569807d00a059a78aeb3bd1eddeffcbdf36 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 14 Feb 2025 11:43:20 + Subject: [PATCH 1/7] Init --- lldb/include/lldb/Symbol/CompilerType.h | 3 +- lldb/source/API/SBType.cpp| 8 +++- .../Language/CPlusPlus/GenericBitset.cpp | 2 +- .../Plugins/Language/CPlusPlus/LibCxxSpan.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 33 ++--- .../TypeSystem/Clang/TypeSystemClang.cpp | 47 +-- .../TestCppTemplateArguments.py | 31 ++-- .../API/lang/cpp/template-arguments/main.cpp | 6 +++ lldb/unittests/Symbol/TestTypeSystemClang.cpp | 42 - 9 files changed, 143 insertions(+), 31 deletions(-) diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 096a8f1ab68e8..f7e3e552f3e45 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -15,6 +15,7 @@ #include #include "lldb/lldb-private.h" +#include "clang/AST/APValue.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/Casting.h" @@ -544,7 +545,7 @@ bool operator==(const CompilerType &lhs, const CompilerType &rhs); bool operator!=(const CompilerType &lhs, const CompilerType &rhs); struct CompilerType::IntegralTemplateArgument { - llvm::APSInt value; + clang::APValue value; CompilerType type; }; diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index 6401d32c85795..72f590947dff6 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -697,6 +697,7 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, std::optional arg; const bool expand_pack = true; switch (GetTemplateArgumentKind(idx)) { + case eTemplateArgumentKindStructuralValue: case eTemplateArgumentKindIntegral: arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument( idx, expand_pack); @@ -708,7 +709,12 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, if (!arg) return {}; - Scalar value{arg->value}; + Scalar value; + if (arg->value.isFloat()) +value = arg->value.getFloat(); + else +value = arg->value.getInt(); + DataExtractor data; value.GetData(data); diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index 33955dccb6ccc..99ff975825c71 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -91,7 +91,7 @@ lldb::ChildCacheState GenericBitsetFrontEnd::Update() { size_t size = 0; if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) -size = arg->value.getLimitedValue(); +size = arg->value.getInt().getLimitedValue(); m_elements.assign(size, ValueObjectSP()); m_first = diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp index 15040295efe6d..687ef1739ad11 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp @@ -119,7 +119,7 @@ lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { } else if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { - m_num_elements = arg->value.getLimitedValue(); + m_num_elements = arg->value.getInt().getLimitedValue(); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ec0004c70c6da..70af283ab7443 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1973,6 +1973,27 @@ class DWARFASTParserClang::DelayedAddObjCClassProperty { ClangASTMetadata m_metadata; }; +static clang::APValue MakeAPValue(CompilerType clang_type, uint64_t bit_width, + uint64_t value) { + bool is_signed = false; + const bool is_integral = clang_type.IsIntegerOrEnumerationType(is_signed); + + llvm::APSInt apint(bit_width, !is_signed); + apint = value; + + if (is_integral) +return clang::APValue(apint); + + uint32_t count; + bool is_complex; + assert(clang_type.IsFloatingPointType(count, is_complex)); + + if (bit_width == 32) +return clang::APValue(llvm::APFloat(apint.bitsToFloat())); + + return clang::APValue(llvm::APFloat(apint.bitsToDouble())); +} + bool DWARFASTParserClang::ParseTemplateDIE( const DWARFDIE &die, TypeSystemClang::TemplateParameterInfos &template_param_infos) { @@ -2050,9 +2071,6 @@ bool DWARFASTParserClang::ParseTemplateDIE( clang_type = m_ast.GetBasicType(eBasicTypeVoid); if (!is_templat
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/127206 >From 759f0569807d00a059a78aeb3bd1eddeffcbdf36 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 14 Feb 2025 11:43:20 + Subject: [PATCH 1/8] Init --- lldb/include/lldb/Symbol/CompilerType.h | 3 +- lldb/source/API/SBType.cpp| 8 +++- .../Language/CPlusPlus/GenericBitset.cpp | 2 +- .../Plugins/Language/CPlusPlus/LibCxxSpan.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 33 ++--- .../TypeSystem/Clang/TypeSystemClang.cpp | 47 +-- .../TestCppTemplateArguments.py | 31 ++-- .../API/lang/cpp/template-arguments/main.cpp | 6 +++ lldb/unittests/Symbol/TestTypeSystemClang.cpp | 42 - 9 files changed, 143 insertions(+), 31 deletions(-) diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 096a8f1ab68e8..f7e3e552f3e45 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -15,6 +15,7 @@ #include #include "lldb/lldb-private.h" +#include "clang/AST/APValue.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/Casting.h" @@ -544,7 +545,7 @@ bool operator==(const CompilerType &lhs, const CompilerType &rhs); bool operator!=(const CompilerType &lhs, const CompilerType &rhs); struct CompilerType::IntegralTemplateArgument { - llvm::APSInt value; + clang::APValue value; CompilerType type; }; diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index 6401d32c85795..72f590947dff6 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -697,6 +697,7 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, std::optional arg; const bool expand_pack = true; switch (GetTemplateArgumentKind(idx)) { + case eTemplateArgumentKindStructuralValue: case eTemplateArgumentKindIntegral: arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument( idx, expand_pack); @@ -708,7 +709,12 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, if (!arg) return {}; - Scalar value{arg->value}; + Scalar value; + if (arg->value.isFloat()) +value = arg->value.getFloat(); + else +value = arg->value.getInt(); + DataExtractor data; value.GetData(data); diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index 33955dccb6ccc..99ff975825c71 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -91,7 +91,7 @@ lldb::ChildCacheState GenericBitsetFrontEnd::Update() { size_t size = 0; if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) -size = arg->value.getLimitedValue(); +size = arg->value.getInt().getLimitedValue(); m_elements.assign(size, ValueObjectSP()); m_first = diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp index 15040295efe6d..687ef1739ad11 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp @@ -119,7 +119,7 @@ lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { } else if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { - m_num_elements = arg->value.getLimitedValue(); + m_num_elements = arg->value.getInt().getLimitedValue(); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ec0004c70c6da..70af283ab7443 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1973,6 +1973,27 @@ class DWARFASTParserClang::DelayedAddObjCClassProperty { ClangASTMetadata m_metadata; }; +static clang::APValue MakeAPValue(CompilerType clang_type, uint64_t bit_width, + uint64_t value) { + bool is_signed = false; + const bool is_integral = clang_type.IsIntegerOrEnumerationType(is_signed); + + llvm::APSInt apint(bit_width, !is_signed); + apint = value; + + if (is_integral) +return clang::APValue(apint); + + uint32_t count; + bool is_complex; + assert(clang_type.IsFloatingPointType(count, is_complex)); + + if (bit_width == 32) +return clang::APValue(llvm::APFloat(apint.bitsToFloat())); + + return clang::APValue(llvm::APFloat(apint.bitsToDouble())); +} + bool DWARFASTParserClang::ParseTemplateDIE( const DWARFDIE &die, TypeSystemClang::TemplateParameterInfos &template_param_infos) { @@ -2050,9 +2071,6 @@ bool DWARFASTParserClang::ParseTemplateDIE( clang_type = m_ast.GetBasicType(eBasicTypeVoid); if (!is_templat
[Lldb-commits] [lldb] Define Telemetry plugin for LLDB. (PR #126588)
labath wrote: > Given that they also need to support (1) they'd always have to be full blown > plugins, right? So it's not like they could be migrated over to a "plugin > light" if we came up with something like that? Sort of. There would have to be *a* full-blown plugin. But there's no reason why setting the host platform must be handled at the same place as registering a (remote) platform plugin. For example, if we had a super-succinct mechanism to register a full-blown plugin, and the host platform wouldn't fit into that, we could put that into completely different place, and everything would be fine. Conversely, we could also make registering the host platform use the same callback iteration code as everything else (we'd pass `PlatformLinux::CreateHostPlatformCallback` to the PluginManager -- if linux was the host -- and then it would create the host platform by iterating through the callbacks). But I don't think either of those is likely, so it's probably going to stay the way it is... > > We don't need to inherit from `PluginInterface` as it really doesn't give > > you anything. > > From my understanding, the benefit of inheriting from the interface is you > can re-use the existing cmake and C++ macros magic for defining vendor impl - > that is, you just put `LLDB_PLUGIN_DEFINE(MyPlugin)` in the vendor code, > along with the cmake declaration and you're done! The framework takes care of > ensuring the `::Initialize()` is called to set the instance. Not exactly. All `LLDB_PLUGIN_DEFINE` does is it sets up a call to `YourPlugin::Initialize`. Anything that happens after that is up to the plugin code. There is nothing requiring you to inherit `PluginInterface` in any object that you create. IOW, it's totally feasible to have a "plugin" which does not inherit from "PluginInterface". Whether that's a good idea is a different question. I'm personally fine with that as I never liked the PluginInterface interface much anyway. > > > How does that sound to you @oontvoo & @labath? > > SG, either way - the simpler the better :) SGTM https://github.com/llvm/llvm-project/pull/126588 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
@@ -119,7 +119,7 @@ lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { } else if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { - m_num_elements = arg->value.getLimitedValue(); + m_num_elements = arg->value.GetAPSInt().getLimitedValue(); Michael137 wrote: Since `Scalar` default initializes both float and integer members, i removed the `isInt` call from prior revisions here https://github.com/llvm/llvm-project/pull/127206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/127206 >From 759f0569807d00a059a78aeb3bd1eddeffcbdf36 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 14 Feb 2025 11:43:20 + Subject: [PATCH 1/9] Init --- lldb/include/lldb/Symbol/CompilerType.h | 3 +- lldb/source/API/SBType.cpp| 8 +++- .../Language/CPlusPlus/GenericBitset.cpp | 2 +- .../Plugins/Language/CPlusPlus/LibCxxSpan.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 33 ++--- .../TypeSystem/Clang/TypeSystemClang.cpp | 47 +-- .../TestCppTemplateArguments.py | 31 ++-- .../API/lang/cpp/template-arguments/main.cpp | 6 +++ lldb/unittests/Symbol/TestTypeSystemClang.cpp | 42 - 9 files changed, 143 insertions(+), 31 deletions(-) diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 096a8f1ab68e8..f7e3e552f3e45 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -15,6 +15,7 @@ #include #include "lldb/lldb-private.h" +#include "clang/AST/APValue.h" #include "llvm/ADT/APSInt.h" #include "llvm/Support/Casting.h" @@ -544,7 +545,7 @@ bool operator==(const CompilerType &lhs, const CompilerType &rhs); bool operator!=(const CompilerType &lhs, const CompilerType &rhs); struct CompilerType::IntegralTemplateArgument { - llvm::APSInt value; + clang::APValue value; CompilerType type; }; diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index 6401d32c85795..72f590947dff6 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -697,6 +697,7 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, std::optional arg; const bool expand_pack = true; switch (GetTemplateArgumentKind(idx)) { + case eTemplateArgumentKindStructuralValue: case eTemplateArgumentKindIntegral: arg = m_opaque_sp->GetCompilerType(false).GetIntegralTemplateArgument( idx, expand_pack); @@ -708,7 +709,12 @@ lldb::SBValue SBType::GetTemplateArgumentValue(lldb::SBTarget target, if (!arg) return {}; - Scalar value{arg->value}; + Scalar value; + if (arg->value.isFloat()) +value = arg->value.getFloat(); + else +value = arg->value.getInt(); + DataExtractor data; value.GetData(data); diff --git a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp index 33955dccb6ccc..99ff975825c71 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/GenericBitset.cpp @@ -91,7 +91,7 @@ lldb::ChildCacheState GenericBitsetFrontEnd::Update() { size_t size = 0; if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) -size = arg->value.getLimitedValue(); +size = arg->value.getInt().getLimitedValue(); m_elements.assign(size, ValueObjectSP()); m_first = diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp index 15040295efe6d..687ef1739ad11 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSpan.cpp @@ -119,7 +119,7 @@ lldb_private::formatters::LibcxxStdSpanSyntheticFrontEnd::Update() { } else if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(1)) { - m_num_elements = arg->value.getLimitedValue(); + m_num_elements = arg->value.getInt().getLimitedValue(); } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ec0004c70c6da..70af283ab7443 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1973,6 +1973,27 @@ class DWARFASTParserClang::DelayedAddObjCClassProperty { ClangASTMetadata m_metadata; }; +static clang::APValue MakeAPValue(CompilerType clang_type, uint64_t bit_width, + uint64_t value) { + bool is_signed = false; + const bool is_integral = clang_type.IsIntegerOrEnumerationType(is_signed); + + llvm::APSInt apint(bit_width, !is_signed); + apint = value; + + if (is_integral) +return clang::APValue(apint); + + uint32_t count; + bool is_complex; + assert(clang_type.IsFloatingPointType(count, is_complex)); + + if (bit_width == 32) +return clang::APValue(llvm::APFloat(apint.bitsToFloat())); + + return clang::APValue(llvm::APFloat(apint.bitsToDouble())); +} + bool DWARFASTParserClang::ParseTemplateDIE( const DWARFDIE &die, TypeSystemClang::TemplateParameterInfos &template_param_infos) { @@ -2050,9 +2071,6 @@ bool DWARFASTParserClang::ParseTemplateDIE( clang_type = m_ast.GetBasicType(eBasicTypeVoid); if (!is_templat
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
@@ -544,7 +545,7 @@ bool operator==(const CompilerType &lhs, const CompilerType &rhs); bool operator!=(const CompilerType &lhs, const CompilerType &rhs); struct CompilerType::IntegralTemplateArgument { - llvm::APSInt value; + clang::APValue value; labath wrote: I just realized this is adding a clang dependency on lldb core (non-plugin) code. What would you say to making this a `Scalar` instead? https://github.com/llvm/llvm-project/pull/127206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
@@ -1973,6 +1973,30 @@ class DWARFASTParserClang::DelayedAddObjCClassProperty { ClangASTMetadata m_metadata; }; +static std::optional MakeAPValue(const clang::ASTContext &ast, + CompilerType clang_type, + uint64_t bit_width, + uint64_t value) { + bool is_signed = false; + const bool is_integral = clang_type.IsIntegerOrEnumerationType(is_signed); + + llvm::APSInt apint(bit_width, !is_signed); + apint = value; + + if (is_integral) +return clang::APValue(apint); + + uint32_t count; + bool is_complex; + // FIXME: we currently support a limited set of floating point types. + // E.g., 16-bit floats are not supported. + if (!clang_type.IsFloatingPointType(count, is_complex)) +return std::nullopt; + + return clang::APValue(llvm::APFloat( + ast.getFloatTypeSemantics(ClangUtil::GetQualType(clang_type)), apint)); labath wrote: :+1: https://github.com/llvm/llvm-project/pull/127206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][TypeSystemClang] Add support for floating point template argument constants (PR #127206)
@@ -2061,17 +2082,22 @@ bool DWARFASTParserClang::ParseTemplateDIE( std::optional size = clang_type.GetBitSize(nullptr); if (!size) return false; labath wrote: It looks like this exists only to be passed to `MakeAPValue`. Since it already gets `clang_type` as an argument (and uses it to retrieve things like bit width and float semantics), could we move this there as well? https://github.com/llvm/llvm-project/pull/127206 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Addressed additional review comments from PR/119716. (PR #126757)
https://github.com/labath approved this pull request. https://github.com/llvm/llvm-project/pull/126757 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits