summaryrefslogtreecommitdiff
path: root/lldb/source/Target
AgeCommit message (Collapse)Author
2025-11-21[lldb] Remove redundant declarations (NFC) (#169003)Kazu Hirata
In C++17, static constexpr members are implicitly inline, so they no longer require an out-of-line definition. Identified with readability-redundant-declaration.
2025-11-20[lldb] Eliminate SupportFileSP nullptr derefs (#168624)Jonas Devlieghere
This patch fixes and eliminates the possibility of SupportFileSP ever being nullptr. The support file was originally treated like a value type, but became a polymorphic type and therefore has to be stored and passed around as a pointer. To avoid having all the callers check the validity of the pointer, I introduced the invariant that SupportFileSP is never null and always default constructed. However, without enforcement at the type level, that's fragile and indeed, we already identified two crashes where someone accidentally broke that invariant. This PR introduces a NonNullSharedPtr to prevent that. NonNullSharedPtr is a smart pointer wrapper around std::shared_ptr that guarantees the pointer is never null. If default-constructed, it creates a default-constructed instance of the contained type. Note that I'm using private inheritance because you shouldn't inherit from standard library classes due to the lack of virtual destructor. So while the new abstraction looks like a `std::shared_ptr`, it is in fact **not** a shared pointer. Given that our destructor is trivial, we could use public inheritance, but currently there's no need for it. rdar://164989579
2025-11-14[lldb] fix parallel module loading deadlock for Linux DYLD (#166480)Tom Yang
Another attempt at resolving the deadlock issue @GeorgeHuyubo discovered (his previous [attempt](https://github.com/llvm/llvm-project/pull/160225)). This change can be summarized as the following: * Plumb through a boolean flag to force no preload in `GetOrCreateModules` all the way through to `LoadModuleAtAddress`. * Parallelize `Module::PreloadSymbols` separately from `Target::GetOrCreateModule` and its caller `LoadModuleAtAddress` (this is what avoids the deadlock). These changes roughly maintain the performance characteristics of the previous implementation of parallel module loading. Testing on targets with between 5000 and 14000 modules, I saw similar numbers as before, often more than 10% faster in the new implementation across multiple trials for these massive targets. I think it's because we have less lock contention with this approach. # The deadlock See [bt.txt](https://github.com/user-attachments/files/22524471/bt.txt) for a sample backtrace of LLDB when the deadlock occurs. As @GeorgeHuyubo explains in his [PR](https://github.com/llvm/llvm-project/pull/160225), the deadlock occurs from an ABBA deadlock that happens when a thread context-switches out of `Module::PreloadSymbols`, goes into `Target::GetOrCreateModule` for another module, possibly entering this block: ``` if (!module_sp) { // The platform is responsible for finding and caching an appropriate // module in the shared module cache. if (m_platform_sp) { error = m_platform_sp->GetSharedModule( module_spec, m_process_sp.get(), module_sp, &search_paths, &old_modules, &did_create_module); } else { error = Status::FromErrorString("no platform is currently set"); } } ``` `Module::PreloadSymbols` holds a module-level mutex, and then `GetSharedModule` *attempts* to hold the mutex of the global shared `ModuleList`. So, this thread holds the module mutex, and waits on the global shared `ModuleList` mutex. A competing thread may execute `Target::GetOrCreateModule`, enter the same block as above, grabbing the global shared `ModuleList` mutex. Then, in `ModuleList::GetSharedModule`, we eventually call `ModuleList::FindModules` which eventually waits for the `Module` mutex held by the first thread (via `Module::GetUUID`). Thus, we deadlock. ## Reproducing the deadlock It might be worth noting that I've never been able to observe this deadlock issue during live debugging (e.g. launching or attaching to processes), however we were able to consistently reproduce this issue with coredumps when using the following settings: ``` (lldb) settings set target.parallel-module-load true (lldb) settings set target.preload-symbols true (lldb) settings set symbols.load-on-demand false (lldb) target create --core /some/core/file/here # deadlock happens ``` ## How this change avoids this deadlock This change avoids concurrent executions of `Module::PreloadSymbols` with `Target::GetOrCreateModule` by waiting until after the `Target::GetOrCreateModule` executions to run `Module::PreloadSymbols` in parallel. This avoids the ordering of holding a Module lock *then* the ModuleList lock, as `Target::GetOrCreateModule` executions maintain the ordering of the shared ModuleList lock first (from what I've read and tested). ## Why not read-write lock? Some feedback in https://github.com/llvm/llvm-project/pull/160225 was to modify mutexes used in these components with read-write locks. This might be a good idea overall, but I don't think it would *easily* resolve this specific deadlock. `Module::PreloadSymbols` would probably need a write lock to Module, so even if we had a read lock in `Module::GetUUID` we would still contend. Maybe the `ModuleList` lock could be a read lock that converts to a write lock if it chooses to update the module, but it seems likely that some thread would try to update the shared module list and then the write lock would contend again. Perhaps with deeper architectural changes, we could fix this issue? # Other attempts One downside of this approach (and the former approach of parallel module loading) is that each DYLD would need to implement this pattern themselves. With @clayborg's help, I looked at a few other approaches: * In `Target::GetOrCreateModule`, backgrounding the `Module::PreloadSymbols` call by adding it directly to the thread pool via `Debugger::GetThreadPool().async()`. This required adding a lock to `Module::SetLoadAddress` (probably should be one there already) since `ObjectFileELF::SetLoadAddress` is not thread-safe (updates sections). Unfortunately, during execution, this causes the preload symbols to run synchronously with `Target::GetOrCreateModule`, preventing us from truly parallelizing the execution. * In `Module::PreloadSymbols`, backgrounding the `symtab` and `sym_file` `PreloadSymbols` calls individually, but similar issues as the above. * Passing a callback function like https://github.com/swiftlang/llvm-project/pull/10746 instead of the boolean I use in this change. It's functionally the same change IMO, with some design tradeoffs: * Pro: the caller doesn't need to explicitly call `Module::PreloadSymbols` itself, and can instead call whatever function is passed into the callback. * Con: the caller needs to delay the execution of the callback such that it occurs after the `GetOrCreateModule` logic, otherwise we run into the same issue. I thought this would be trickier for the caller, requiring some kinda condition variable or otherwise storing the calls to execute afterwards. # Test Plan: ``` ninja check-lldb ``` --------- Co-authored-by: Tom Yang <toyang@fb.com>
2025-11-12Revert "[lldb] Introduce ScriptedFrameProvider for real threads" (#167662)Michael Buch
The new test fails on x86 and arm64 public macOS bots: ``` 09:27:59 ====================================================================== 09:27:59 FAIL: test_append_frames (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that we can add frames after real stack. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 122, in test_append_frames 09:27:59 self.assertEqual(new_frame_count, original_frame_count + 1) 09:27:59 AssertionError: 5 != 6 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_applies_to_thread (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that applies_to_thread filters which threads get the provider. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 218, in test_applies_to_thread 09:27:59 self.assertEqual( 09:27:59 AssertionError: 5 != 1 : Thread with ID 1 should have 1 synthetic frame 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_prepend_frames (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that we can add frames before real stack. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 84, in test_prepend_frames 09:27:59 self.assertEqual(new_frame_count, original_frame_count + 2) 09:27:59 AssertionError: 5 != 7 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_remove_frame_provider_by_id (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that RemoveScriptedFrameProvider removes a specific provider by ID. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 272, in test_remove_frame_provider_by_id 09:27:59 self.assertEqual(thread.GetNumFrames(), 3, "Should have 3 synthetic frames") 09:27:59 AssertionError: 5 != 3 : Should have 3 synthetic frames 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_replace_all_frames (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that we can replace the entire stack. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 41, in test_replace_all_frames 09:27:59 self.assertEqual(thread.GetNumFrames(), 3, "Should have 3 synthetic frames") 09:27:59 AssertionError: 5 != 3 : Should have 3 synthetic frames 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ====================================================================== 09:27:59 FAIL: test_scripted_frame_objects (TestScriptedFrameProvider.ScriptedFrameProviderTestCase) 09:27:59 Test that provider can return ScriptedFrame objects. 09:27:59 ---------------------------------------------------------------------- 09:27:59 Traceback (most recent call last): 09:27:59 File "/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py", line 159, in test_scripted_frame_objects 09:27:59 self.assertEqual(frame0.GetFunctionName(), "custom_scripted_frame_0") 09:27:59 AssertionError: 'thread_func(int)' != 'custom_scripted_frame_0' 09:27:59 - thread_func(int) 09:27:59 + custom_scripted_frame_0 09:27:59 09:27:59 Config=arm64-/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/lldb-build/bin/clang 09:27:59 ---------------------------------------------------------------------- 09:27:59 Ran 6 tests in 14.242s 09:27:59 09:27:59 FAILED (failures=6) ``` Reverts llvm/llvm-project#161870
2025-11-11[lldb] Introduce ScriptedFrameProvider for real threads (#161870)Med Ismail Bennani
This patch extends ScriptedFrame to work with real (non-scripted) threads, enabling frame providers to synthesize frames for native processes. Previously, ScriptedFrame only worked within ScriptedProcess/ScriptedThread contexts. This patch decouples ScriptedFrame from ScriptedThread, allowing users to augment or replace stack frames in real debugging sessions for use cases like custom calling conventions, reconstructing corrupted frames from core files, or adding diagnostic frames. Key changes: - ScriptedFrame::Create() now accepts ThreadSP instead of requiring ScriptedThread, extracting architecture from the target triple rather than ScriptedProcess.arch - Added SBTarget::RegisterScriptedFrameProvider() and ClearScriptedFrameProvider() APIs, with Target storing a SyntheticFrameProviderDescriptor template for new threads - Added "target frame-provider register/clear" commands for CLI access - Thread class gains LoadScriptedFrameProvider(), ClearScriptedFrameProvider(), and GetFrameProvider() methods for per-thread frame provider management - New SyntheticStackFrameList overrides FetchFramesUpTo() to lazily provide frames from either the frame provider or the real stack This enables practical use of the SyntheticFrameProvider infrastructure in real debugging workflows. rdar://161834688 Signed-off-by: Med Ismail Bennani <ismail@bennani.ma> Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
2025-11-07Fix a crash when a stop hook deletes itself in its callback. (#160416)jimingham
We're iterating over the stop hooks so if one of them changes the stop hook list by deleting itself or another stop hook, that invalidates our iterator. I chose to fix this by making a copy of the stop hook list and iterating over that. That's a cheap operation since this is just an array of shared pointers. But more importantly doing it this way means that if on a stop where one stop hook deletes another, the deleted hook will always get a chance to run. If you iterated over the list itself, then whether that to be deleted hook gets to run would be dependent on whether it was before or after the deleting stop hook, which would be confusing.
2025-11-07[lldb] Correctly detach (rather than kill) when connecting with gdb-remote ↵Jonas Devlieghere
(#166869) We weren't setting `m_should_detach` when going through the `DoConnectRemote` code path. This meant that when you would attaches to a remote process with `gdb-remote <port>` and use Ctrl+D, it would kill the process instead of detach from it. rdar://156111423
2025-11-06[lldb] Enable locate module callback for all module loading (#160199)GeorgeHuyubo
Main executables were bypassing the locate module callback that shared libraries use, preventing custom symbol file location logic from working consistently. This PR fix this by * Adding target context to ModuleSpec * Leveraging that context to use target search path and platform's locate module callback in ModuleList::GetSharedModule This ensures both main executables and shared libraries get the same callback treatment for symbol file resolution. --------- Co-authored-by: George Hu <hyubo@meta.com> Co-authored-by: George Hu <georgehuyubo@gmail.com>
2025-11-06[lldb/Target] Add SyntheticFrameProvider class (#166664)Med Ismail Bennani
This patch introduces a new way to reconstruct the thread stackframe list. New `SyntheticFrameProvider` classes can lazy fetch a StackFrame at index using a provided StackFrameList. In can either be the real unwinder StackFrameList or we could also chain SyntheticFrameProviders to each others. This is the foundation work to implement ScriptedFrameProviders, which will come in a follow-up patch. Signed-off-by: Med Ismail Bennani <ismail@bennani.ma> Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
2025-11-05[lldb] Mark single-argument SourceLanguage constructors explicit (#166527)Michael Buch
This avoids unintentional comparisons between `SourceLanguage` and `LanguageType`. Also marks `operator bool` explicit so we don't implicitly convert to bool.
2025-11-04[lldb][Runtime] Move VerboseTrapFrameRecognizer into CPPLanguageRuntime ↵Michael Buch
(#166157) https://github.com/llvm/llvm-project/pull/165996 is adding a Clang dependency to Target because we're moving some of the functionality of the VerboseTrapFrameRecognizer into libClang. To avoid adding this dependency this patch moves VerboseTrapFrameRecognizer into the CPPLanguageRuntime. Most of the frame recognizers already live in the various runtime plugins. An alternative discussed was to create a common `CLanguageRuntime` whose currently sole responsibility was to register the `VerboseTrapFrameRecognizer` and `AssertStackFrameRecognizer`. The main issue I ran into here was frame recognizers aren't uniqued in the target. Currently this only manifests when re-running a target, which re-triggers all the recognizer registration (added a test with a FIXME for this). If we had a common `CLanguageRuntime` that `CPPLanguageRuntime` and `ObjCLanguageRuntime` inherited from, I didn't find a great way to avoid registering the recognizer multiple times. We can't just call_once on it because we do want the recognisers to be re-registered for new targets in the same debugger session. If the recognisers were stored in something like a UniqueVector in the Target, then we wouldn't have that issue. But currently that's not the case, and it would take a bit of refactoring to de-dupe the recognisers. There may very well be solutions I haven't considered, but all the things I've tried so far I wasn't very happy with. So in the end I just moved this to the C++ runtime for now in order to unblock https://github.com/llvm/llvm-project/pull/165996. The C++ language runtime is always available (even for C targets) if the C++ language plugin is available. Which it should also be unless someone is using an LLDB with the C++ plugin compiled out. But at that point numerous things wouldn't work when even debugging just C.
2025-11-03[NFC][LLDB][BoundsSatety] Add `InstrumentationRuntime::MatchAllModules` ↵Dan Liew
(#166001) This adds a virtual method that allows `InstrumentationRuntime` sub classes to match against all modules rather than just a library that matches a particular regex. When the implementation returns true `GetPatternForRuntimeLibrary()` is ignored and all modules are iterated over. The default implementation returns false which was the previous behavior which uses `GetPatternForRuntimeLibrary()` to only match a particular runtime library. The intended use case here is for implementing an `InstrumentationRuntime` where the runtime library of interest can have multiple implementations and whose name is not known ahead of time. The concrete use case here is for a `InstrumentationRuntime` plugin for implementations of the `-fbounds-safety` soft-trap runtime which can have multiple different implementations and so the module containing the runtime functions isn't known ahead of time. This plug-in will be upstreamed as part of the process of upstreaming `-fbounds-safety`. An alternative to this would be for the `GetPatternForRuntimeLibrary()` function to return a regex that matches everything. While that technically works this new API more clearly indicates in the intent. We probably also save a little perf by not executing the regex match for every loaded module but I have not measured this. rdar://163230807
2025-11-03[lldb] Fix indentation when printing stop hooks (#165945)Julian Lettner
This commit aggregates the following changes: 1. Fix the format (i.e., indentation) when printing stop hooks via `target stop-hook list`. 2. Add `IndentScope Stream::MakeIndentScope()` to make managing (and restoring!) of the indentation level on `Stream` instances more ergonomic and less error prone. 3. Simplify printing of stop hooks using the new `IndentScope`.
2025-10-31[lldb] Refactor LLDB Breakpoint Event Notifications to centralize and ↵Piyush Jaiswal
eliminate code duplication (#164739) ### Summary This PR refactors breakpoint event notification in LLDB to centralize and eliminate code duplication. It creates a unified method in the `Target` class for sending breakpoint change events. The new methods check if listeners exist before broadcasting events ### Test <img width="1532" height="76" alt="Screenshot 2025-10-23 at 12 49 31 PM" src="https://github.com/user-attachments/assets/6d6a6da6-9684-463c-aeeb-90663cdbd077" /> --------- Co-authored-by: Piyush Jaiswal <piyushjais@meta.com>
2025-10-24[lldb] Introduce internal stop hooks (#164506)Julian Lettner
Introduce the concept of internal stop hooks. These are similar to LLDB's internal breakpoints: LLDB itself will add them and users of LLDB will not be able to add or remove them. This change adds the following 3 independently-useful concepts: * Maintain a list of internal stop hooks that will be populated by LLDB and cannot be added to or removed from by users. They are managed in a separate list in `Target::m_internal_stop_hooks`. * `StopHookKind:CodeBased` and `StopHookCoded` represent a stop hook defined by a C++ code callback (instead of command line expressions or a Python class). * Stop hooks that do not print any output can now also suppress the printing of their header and description when they are hit via `StopHook::GetSuppressOutput`. Combining these 3 concepts we can model "internal stop hooks" which serve the same function as LLDB's internal breakpoints: executing built-in, LLDB-defined behavior, leveraging the existing mechanism of stop hooks. This change also simplifies `Target::RunStopHooks`. We already have to materialize a new list for combining internal and user stop hooks. Filter and only add active hooks to this list to avoid the need for "isActive?" checks later on.
2025-10-21[lldb] Implement Process::ReadMemoryRanges (#163651)Felipe de Azevedo Piovezan
This commit introduces a base-class implementation for a method that reads memory from multiple ranges at once. This implementation simply calls the underlying `ReadMemoryFromInferior` method on each requested range, intentionally bypassing the memory caching mechanism (though this may be easily changed in the future). `Process` implementations that can be perform this operation more efficiently - e.g. with the MultiMemPacket described in [1] - are expected to override this method. As an example, this commit changes AppleObjCClassDescriptorV2 to use the new API. Note about the API ------------------ In the RFC, we discussed having the API return some kind of class `ReadMemoryRangesResult`. However, while writing such a class, it became clear that it was merely wrapping a vector, without providing anything useful. For example, this class: ``` struct ReadMemoryRangesResult { ReadMemoryRangesResult( llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> ranges) : ranges(std::move(ranges)) {} llvm::ArrayRef<llvm::MutableArrayRef<uint8_t>> getRanges() const { return ranges; } private: llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> ranges; }; ``` As can be seen in the added test and in the added use-case (AppleObjCClassDescriptorV2), users of this API will just iterate over the vector of memory buffers. So they want a return type that can be iterated over, and the vector seems more natural than creating a new class and defining iterators for it. Likewise, in the RFC, we discussed wrapping the result into an `Expected`. Upon experimenting with the code, this feels like it limits what the API is able to do as the base class implementation never needs to fail the entire result, it's the individual reads that may fail and this is expressed through a zero-length result. Any derived classes overriding `ReadMemoryRanges` should also never produce a top level failure: if they did, they can just fall back to the base class implementation, which would produce a better result. The choice of having the caller allocate a buffer and pass it to `Process::ReadMemoryRanges` is done mostly to follow conventions already done in the Process class. [1]: https://discourse.llvm.org/t/rfc-a-new-vectorized-memory-read-packet/
2025-10-20Fix a potential use-after-free in StopInfoBreakpoint. (#163471)jimingham
StopInfoBreakpoint keeps a BreakpointLocationCollection for all the breakpoint locations at the BreakpointSite that was hit. It is also lives through the time a given thread is stopped, so there are plenty of opportunities for one of the owning breakpoints to get deleted. But BreakpointLocations don't keep their owner Breakpoints alive, so if the BreakpointLocationCollection can live past when some code gets a chance to delete an owner breakpoint, and then you ask that location for some breakpoint information, it will access freed memory. This wasn't a problem before PR #158128 because the StopInfoBreakpoint just kept the BreakpointSite that was hit, and when you asked it questions, it relooked up that list. That was not great, however, because if you hit breakpoints 5 & 6, deleted 5 and then asked which breakpoints got hit, you would just get 6. For that and other reasons that PR changed to storing a BreakpointLocationCollection of the breakpoints that were hit. That's better from a UI perspective but caused this potential problem. I fix it by adding a variant of the BreakpointLocationCollection that also holds onto a shared pointer to the Breakpoints that own the locations that were hit, thus keeping them alive till the StopInfoBreakpoint goes away. This fixed the ASAN assertion. I also added a test that works harder to cause trouble by deleting breakpoints during a stop.
2025-10-13Delegate to ABI plugin to check if call frame addresses are valid (#161398)pveras
Specially when dealing with different address spaces, CFAs could start from addresses like 0. For instance, Nvidia GPUs have instructions to read from local memory that use 0-based offsets and stack memory can be referenced by these offsets rather than global addresses. Note that ABIs could already specify what they consider to be valid CFA values but this was never used in these parts of the unwinder code. For most ABIs, this makes the validation more strict, as they already used to discard 0s and then checked for alignment which would discard 1s. There a few exceptions where 0s were possible and this makes it less strict, like the RISCV and ARC ABIs. @jasonmolenda Would you be the appropriate reviewer for this? Also cc. @clayborg @walter-erquinigo
2025-10-09Add a scripted way to re-present a stop location (#158128)jimingham
This patch adds the notion of "Facade" locations which can be reported from a ScriptedResolver instead of the actual underlying breakpoint location for the breakpoint. Also add a "was_hit" method to the scripted resolver that allows the breakpoint to say which of these "Facade" locations was hit, and "get_location_description" to provide a description for the facade locations. I apologize in advance for the size of the patch. Almost all of what's here was necessary to (a) make the feature testable and (b) not break any of the current behavior. The motivation for this feature is given in the "Providing Facade Locations" section that I added to the python-reference.rst so I won't repeat it here. rdar://152112327
2025-10-09Fix comment typo in `StructuredDataPlugin.cpp` (#162637)Max Desiatov
`structured-data ommand` -> `structured-data command`
2025-10-08[lldb] Fix stepping out if the return address is not allowed to stop at ↵Igor Kudrin
(#161982) When a thread reaches a breakpoint at the return address set by `ThreadPlanStepOut`, `ThreadPlanStepOut::ShouldStop()` calls `ThreadPlanShouldStopHere::InvokeShouldStopHereCallback()`, and if it returns `false`, `ThreadPlanShouldStopHere::QueueStepOutFromHerePlan()` is called to queue a new plan to skip the corresponding range. Once the new plan finishes, `ThreadPlanStepOut::ShouldStop()` should recheck the stop condition; however, there is no code path in the method that sets `done` to `true`. Before #126838, if `done` was `false`, the method checked if a suitable frame had been reached. After the patch, the check is only performed at a breakpoint; thus, the execution continues. This patch causes `ThreadPlanStepOut::ShouldStop()` to recheck the stop condition when `m_step_out_further_plan_sp` completes.
2025-10-09[lldb][Language] Make SourceLanguage::GetDescription for language version ↵Michael Buch
(#162050) Depends on https://github.com/llvm/llvm-project/pull/162048 This makes sure we also include the version number in the description. For `C++17`, this would, e.g., now return `"C++17"` instead of `"ISO C++"`.
2025-10-08[lldb] Fix use after free on ModuleList::RemoveSharedModuleIfOrphaned (#155331)Augusto Noronha
This fixes a potential use after free where ModuleList::RemoveSharedModuleIfOrphaned -> SharedModuleList::RemoveIfOrphaned -> SharedModuleList::RemoveFromMap would potentially dereference a freed pointer. This fixes it by not calling ModuleList::RemoveSharedModuleIfOrphaned at all if the pointer was just freed.
2025-10-08[lldb] Fix off-by-one error in ToDwarfSourceLanguage (#162315)Joshua Peterson
The ToDwarfSourceLanguage function incorrectly excluded languages that equal eLanguageTypeLastStandardLanguage. The comparison used `<` instead of `<=`, causing the last standard language to fall through to the default case and return std::nullopt. This broke language plugins that use eLanguageTypeLastStandardLanguage (currently Mojo at 0x0033) as their language code, preventing proper DWARF language conversion and breaking REPL functionality. The fix changes the comparison from `<` to `<=` to include the last standard language in the automatic conversion to DWARF source language. This is a regression from commit 7f51a2a47d2e706d04855b0e41690ebafa2b3238 which introduced the ToDwarfSourceLanguage function.
2025-10-07[lldb] Add support for unique target ids (#160736)Janet Yang
### Summary Add support for unique target ids per Target instance. This is needed for upcoming changes to allow debugger instances to be shared across separate DAP instances for child process debugging. We want the IDE to be able to attach to existing targets in an already runny lldb-dap session, and having a unique ID per target would make that easier. Each Target instance will have its own unique id, and uses a function-local counter in `TargetList::CreateTargetInternal` to assign incremental unique ids. ### Tests Added several unit tests to test basic functionality, uniqueness of targets, and target deletion doesn't affect the uniqueness. ``` bin/lldb-dotest -p TestDebuggerAPI ```
2025-10-03[lldb][Language] Add Language::GetDisplayNameForLanguageType API (#161803)Michael Buch
The intention for this API is to be used when presenting language names to the user, e.g., in expression evaluation diagnostics or LLDB errors. Most uses of `GetNameForLanguageType` can be probably replaced with `GetDisplayNameForLanguageType`, but that's out of scope of this PR. This uses `llvm::dwarf::LanguageDescription` under the hood, so we would lose the version numbers in the names. If we deem those to be important, we could switch to an implementation that hardcodes a list of user-friendly names with version numbers included. The intention is to use it from https://github.com/llvm/llvm-project/pull/161688 Depends on https://github.com/llvm/llvm-project/pull/161804
2025-10-03[lldb][Language] Simplify SourceLanguage::GetDescription (#161804)Michael Buch
Currently we don't benefit from the user-friendly names that `LanguageDescription` returns because we would always use `Language::GetNameForLanguageType`. I'm not aware of a situation where `GetDescription` should prefer the non-human readable form of the name with. This patch removes the call to `GetNameForLanguageType`. `LanguageDescription` already handles languages that it doesn't know about. For those it would return `Unknown`. The LLDB language types should all be available via DWARF. If there are languages that don't map cleanly between `lldb::LanguageType` and `DW_LANG`, then we should add explicit support for that in the `SourceLanguage::SourceLanguage` constructor.
2025-10-03[lldb][Lanugage][NFC] Adapt Language::ForEach to IterationAction (#161830)Michael Buch
2025-10-01[LLDB] Add load core time to target metrics (#161581)Jacob Lalonde
This patch adds a load core time, right now we don't have much insight into the performance of load core, especially for large coredumps. To start collecting information on this I've added some minor instrumentation code to measure the two call sites of `LoadCore`. I've also added a test to validate the new metric is output in statistics dump
2025-09-23[lldb] Rework how we pass the execution context to the statusline (#159887)Jonas Devlieghere
Currently, we always pass the "selected" execution context to the statusline. When handling a process or thread event, we can be more precise, and build an execution context from the event data. This PR also adopts the new `StoppedExecutionContext` that was recently introduced.
2025-09-19[lldb] Don't call FixDataAddress when reading fp in ReadGPRValue (#159606)Felipe de Azevedo Piovezan
Based on testing on processors that use pointer metadata, and with all the work done to delay calls to FixDataAddress, this is no longer necessary. Note that, with debugserver in particular, this is an NFC change: the code path here is for frame zero, and debugserver will strip metadata when reading fp from frame zero anyway.
2025-09-18[lldb][nfc] Remove no-op calls to Fix*Address (#159586)Felipe de Azevedo Piovezan
The first call, in InitializeNonZerothFrame, is inside a logging branch. For that, it's better to log the real value instead of the fixed one. The second call, inside RegisterContextUnwind::ReadFrameAddress, is computing an address which is then passed to ReadRegisterValueFromMemory, which boils down to a Process::ReadMemory, which fixes the address if it wants to. The current variable names are misleading, making readers believe it is the cfa value itself that is being passed to Fix*Address; that's not the case. This commit renames the variable to make this abundantly clear.
2025-09-12[lldb] Track CFA pointer metadata in StackID (#157498)Felipe de Azevedo Piovezan
[lldb] Track CFA pointer metadata in StackID In this commit: 9c8e71644227 [lldb] Make StackID call Fix{Code,Data} pointers (#152796) We made StackID keep track of the CFA without any pointer metadata in it. This is necessary when comparing two StackIDs to determine which one is "younger". However, the CFA inside StackIDs is also used in other contexts through the method StackID::GetCallFrameAddress. One notable case is DWARFExpression: the computation of `DW_OP_call_frame_address` is done using StackID. This feeds into many other places, e.g. expression evaluation may require the address of a variable that is computed from the CFA; to access the variable without faulting, we may need to preserve the pointer metadata. As such, StackID must be able to provide both versions of the CFA. In the spirit of allowing consumers of pointers to decide what to do with pointer metadata, this patch changes StackID to store both versions of the cfa pointer. Two getter methods are provided, and all call sites except DWARFExpression preserve their existing behavior (stripped pointer). Other alternatives were considered: * Just store the raw pointer. This would require changing the comparisong operator `<` to also receive a Process, as the comparison requires stripped pointers. It wasn't clear if all call-sites had a non-null process, whereas we know we have a process when creating a StackID. * Store a weak pointer to the process inside the class, and then strip metadata as needed. This would require a `weak_ptr::lock` in many operations of LLDB, and it felt wasteful. It also prevents stripping of the pointer if the process has gone away. This patch also changes RegisterContextUnwind::ReadFrameAddress, which is the method computing the CFA fed into StackID, to also preserve the signature pointers.
2025-09-09NFC: SBThread should not be the one to compute StopReasonData. (#157577)jimingham
This is something the StopInfo class manages, so it should be allowed to compute this rather than having SBThread do so. This code just moves the computation to methods in StopInfo. It is mostly NFC. The one change that I actually had to adjust the tests for was a couple of tests that were asking for the UnixSignal stop info data by asking for the data at index 1. GetStopInfoDataCount returns 1 and we don't do 1 based indexing so the test code was clearly wrong. But I don't think it makes sense to perpetuate handing out the value regardless of what index you pass us.
2025-09-09[lldb] Unwind through ARM Cortex-M exceptions automatically (#153922)Jason Molenda
When a processor faults/is interrupted/gets an exception, it will stop running code and jump to an exception catcher routine. Most processors will store the pc that was executing in a system register, and the catcher functions have special instructions to retrieve that & possibly other registers. It may then save those values to stack, and the author can add .cfi directives to tell lldb's unwinder where to find those saved values. ARM Cortex-M (microcontroller) processors have a simpler mechanism where a fixed set of registers are saved to the stack on an exception, and a unique value is put in the link register to indicate to the caller that this has taken place. No special handling needs to be written into the exception catcher, unless it wants to inspect these preserved values. And it is possible for a general stack walker to walk the stack with no special knowledge about what the catch function does. This patch adds an Architecture plugin method to allow an Architecture to override/augment the UnwindPlan that lldb would use for a stack frame, given the contents of the return address register. It resembles a feature where the LanguageRuntime can replace/augment the unwind plan for a function, but it is doing it at offset by one level. The LanguageRuntime is looking at the local register context and/or symbol name to decide if it will override the unwind rules. For the Cortex-M exception unwinds, we need to modify THIS frame's unwind plan if the CALLER's LR had a specific value. RegisterContextUnwind has to retrieve the caller's LR value before it has completely decided on the UnwindPlan it will use for THIS stack frame. This does mean that we will need one additional read of stack memory than we currently do when unwinding, on Armv7 Cortex-M targets. The unwinder walks the stack lazily, as stack frames are requested, and so now if you ask for 2 stack frames, we will read enough stack to walk 2 frames, plus we will read one extra word of memory, the spilled LR value from the stack. In practice, with 512-byte memory cache reads, this is unlikely to be a real performance hit. This PR includes a test with a yaml corefile description and a JSON ObjectFile, incorporating all of the necessary stack memory and symbol names from a real debug session I worked on. The architectural default unwind plans are used for all stack frames except the 0th because there's no instructions for the functions, and no unwind info. I may need to add an encoding of unwind fules to ObjectFileJSON in the future as we create more test cases like this. This PR depends on the yaml2macho-core utility from https://github.com/llvm/llvm-project/pull/153911 to run its API test. rdar://110663219
2025-09-09Reland"[lldb] Add count for errors of DWO files in statistics and combine ↵Ziyi Wang
DWO file count functions" (#156980) This relands changes in https://github.com/llvm/llvm-project/pull/155023 for adding a count of dwo errors and combine all the dwo related stats into one struct. The previous PR was reverted in https://github.com/llvm/llvm-project/pull/156777 as the newly added unit test `test_dwo_id_mismatch_error_stats` sometimes fails due to inappropriate use of `glob.glob`. This change modified the tests created in the former PR to collect and modify the dwo files by there names instead of using index after `glob.glob`. This will avoid the possible failure in these tests if the order of dwo files changes. [Original PR: https://github.com/llvm/llvm-project/pull/155023](https://github.com/llvm/llvm-project/pull/155023) ## Testing Ran unit tests ``` $ ./bin/llvm-lit /data/users/ziyiww/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py ./bin/llvm-lit /data/users/ziyiww/llvm-project/lldb/test/API/commands/statistics/basic/TestStats.py -v -- Testing: 1 tests, 1 workers -- PASS: lldb-api :: commands/statistics/basic/TestStats.py (1 of 1) Testing Time: 388.52s Total Discovered Tests: 1 Passed: 1 (100.00%) $ bin/lldb-dotest -p TestStats.py /data/users/ziyiww/llvm-project/lldb/test/API/commands/statistics/basic/ ---------------------------------------------------------------------- Ran 27 tests in 386.302s OK (skipped=3) ```
2025-09-08[lldb][Instrumentation] Set selected frame to outside sanitizer libraries ↵Michael Buch
(#133079) When hitting a sanitizer breakpoint, LLDB currently displays the frame in the sanitizer dylib (which we usually don't have debug-info for), which isn't very helpful to the user. A more helpful frame to display would be the first frame not in the sanitizer library (we have a [similar heuristic when we trap inside libc++](https://github.com/llvm/llvm-project/pull/108825)). This patch does just that, by implementing the `GetSuggestedStackFrameIndex` API Depends on https://github.com/llvm/llvm-project/pull/133078
2025-09-08[lldb][Target] Clear selected frame index after a StopInfo::PerformAction ↵Michael Buch
(#133078) The motivation for this patch is that `StopInfo::GetSuggestedStackFrameIndex` would not take effect for `InstrumentationRuntimeStopInfo` (which we plan to implement in https://github.com/llvm/llvm-project/pull/133079). This was happening because the instrumentation runtime plugins would run utility expressions as part of the stop that would set the `m_selected_frame_idx`. This means `SelectMostRelevantFrame` was never called, and we would not be able to report the selected frame via the `StopInfo` object. This patch makes sure we clear the `m_selected_frame_idx` to allow `GetSuggestedStackFrameIndex` to take effect, regardless of what the frame recognizers choose to do.
2025-09-08[lldb][NFC] Fix style issues with StackID.h (#157483)Felipe de Azevedo Piovezan
Some comments were "suffixed" to member variable declarations; these are moved to before the variable. Some constructors and operators were just defaulted and not necessary. Some comments dividing the class into logical sections, like "// constructors and destructors", were not applied everywhere. These were removed. They are used in some parts of LLDB, but are the exception. An include was not needed. The operator != can be defined in terms of ==.
2025-09-08MC: Add Triple overloads for more MC constructors (#157321)Matt Arsenault
Avoids more Triple->string->Triple round trip. This is a continuation of f137c3d592e96330e450a8fd63ef7e8877fc1908
2025-09-03Revert "[lldb] Add count for errors of DWO files in statistics and combine ↵David Peixotto
DWO file count functions" (#156777) Reverts llvm/llvm-project#155023 The PR tests passed, but it failed in the CI. Reverting to give time to investigate.
2025-09-03[lldb] Mark scripted frames as synthetic instead of artificial (#153117)Med Ismail Bennani
This patch changes the way frames created from scripted affordances like Scripted Threads are displayed. Currently, they're marked artificial which is used usually for compiler generated frames. This patch changes that behaviour by introducing a new synthetic StackFrame kind and moves 'artificial' to be a distinct StackFrame attribut. On top of making these frames less confusing, this allows us to know when a frame was created from a scripted affordance. rdar://155949703 Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
2025-09-03[lldb] Add count for errors of DWO files in statistics and combine DWO file ↵Ziyi Wang
count functions (#155023) ## Summary A new `totalDwoErrorCount` counter is available in statistics when calling `statistics dump` to track the number of DWO errors. Additionally, this PR refactors the DWO file statistics by consolidating the existing functionality for counting loaded and total DWO files together with the number of DWO errors into a single function that returns a new DWOStats struct. 1. A new struct, `DWOStats` is created to hold the number of loaded DWO files, the total number of DWO files and the number of DWO errors. 2. Replaced the previous `GetDwoFileCounts` function for loaded and total DWO file counts with a single `GetDwoStats()` function returning the struct `DWOStats`. An override is implemented for `SymbolFileDWARF` that computes the new DWO error count alongside existing counts in one pass. If the status of a DWO CU is `Fail`, which means there is error happened during the loading process, we increment the DWO error counter. _Note: The newly created function `GetDwoStats` will only be called when we try to get statistics. Other codepaths will not be affected._ 3. In Statistics, we sum up the total number of DWO file loading errors. This is done by getting `DWOStats` for each symbol file and adding up the results for each module, then adding to the total count among all modules. 4. In Statistics, we also updated call sites to use the new combined function and struct for loaded and total DWO file counts. As it is possible for one module to have several symbol files, the DWO file counts in a module's stats are updated to be calculated by adding up the counts from all symbol files. ## Expected Behavior - When binaries are compiled with split-dwarf and separate DWO files, `totalDwoLoadErrorCount` would be the number of dwo files with error occurs during the loading process, 0 if no error occurs during a loading process. - When not using split-dwarf, we expect `totalDwoLoadErrorCount` to be 0 since there no DWO file loading errors would be caused. - `totalLoadedDwoFileCount` and `totalDwoFileCount` should be correctly calculated after refactoring and updating. ## Testing ### Manual Testing We created some files to simulate the possible DWO errors manually and observed the results generated by statistics dump. For example, if we delete one of the DWO files generated after compiling, we would get: ``` (lldb) statistics dump { ... "totalDwoLoadErrorCount": 1, ... } ``` We also checked the time cost of `statistics dump` w/o the modification to make sure no significant time cost increase imported. ### Unit test Added two unit tests that build with new "dwo_error_foo.cpp" and "dwo_error_main.cpp" files. For tests with flags -gsplit-dwarf, this generates 2 DWO files. In one of the tests, we delete both DWO files and check the result to see if it reflects the number of DWO files with errors correctly. In another test we update one of the files but loading the outdated .dwo file of it, expecting it increments the error count by 1. To run the test: ``` $ bin/lldb-dotest -p TestStats.py ~/local/llvm-project/lldb/test/API/commands/statistics/basic/ -G "dwo" ---------------------------------------------------------------------- Ran 27 tests in 2.680s OK (skipped=21) $ bin/lldb-dotest -p TestStats.py ~/local/llvm-project/lldb/test/API/commands/statistics/basic/ ---------------------------------------------------------------------- Ran 27 tests in 370.131s OK (skipped=3) ```
2025-08-28Stateful variable-location annotations in Disassembler::PrintInstructions() ↵Abdullah Mohammad Amin
(follow-up to #147460) (#152887) **Context** Follow-up to [#147460](https://github.com/llvm/llvm-project/pull/147460), which added the ability to surface register-resident variable locations. This PR moves the annotation logic out of `Instruction::Dump()` and into `Disassembler::PrintInstructions()`, and adds lightweight state tracking so we only print changes at range starts and when variables go out of scope. --- ## What this does While iterating the instructions for a function, we maintain a “live variable map” keyed by `lldb::user_id_t` (the `Variable`’s ID) to remember each variable’s last emitted location string. For each instruction: - **New (or newly visible) variable** → print `name = <location>` once at the start of its DWARF location range, cache it. - **Location changed** (e.g., DWARF range switched to a different register/const) → print the updated mapping. - **Out of scope** (was tracked previously but not found for the current PC) → print `name = <undef>` and drop it. This produces **concise, stateful annotations** that highlight variable lifetime transitions without spamming every line. --- ## Why in `PrintInstructions()`? - Keeps `Instruction` stateless and avoids changing the `Instruction::Dump()` virtual API. - Makes it straightforward to diff state across instructions (`prev → current`) inside the single driver loop. --- ## How it works (high-level) 1. For the current PC, get in-scope variables via `StackFrame::GetInScopeVariableList(/*get_parent=*/true)`. 2. For each `Variable`, query `DWARFExpressionList::GetExpressionEntryAtAddress(func_load_addr, current_pc)` (added in #144238). 3. If the entry exists, call `DumpLocation(..., eDescriptionLevelBrief, abi)` to get a short, ABI-aware location string (e.g., `DW_OP_reg3 RBX → RBX`). 4. Compare against the last emitted location in the live map: - If not present → emit `name = <location>` and record it. - If different → emit updated mapping and record it. 5. After processing current in-scope variables, compute the set difference vs. the previous map and emit `name = <undef>` for any that disappeared. Internally: - We respect file↔load address translation already provided by `DWARFExpressionList`. - We reuse the ABI to map LLVM register numbers to arch register names. --- ## Example output (x86_64, simplified) ``` -> 0x55c6f5f6a140 <+0>: cmpl $0x2, %edi ; argc = RDI, argv = RSI 0x55c6f5f6a143 <+3>: jl 0x55c6f5f6a176 ; <+54> at d_original_example.c:6:3 0x55c6f5f6a145 <+5>: pushq %r15 0x55c6f5f6a147 <+7>: pushq %r14 0x55c6f5f6a149 <+9>: pushq %rbx 0x55c6f5f6a14a <+10>: movq %rsi, %rbx 0x55c6f5f6a14d <+13>: movl %edi, %r14d 0x55c6f5f6a150 <+16>: movl $0x1, %r15d ; argc = R14 0x55c6f5f6a156 <+22>: nopw %cs:(%rax,%rax) ; i = R15, argv = RBX 0x55c6f5f6a160 <+32>: movq (%rbx,%r15,8), %rdi 0x55c6f5f6a164 <+36>: callq 0x55c6f5f6a030 ; symbol stub for: puts 0x55c6f5f6a169 <+41>: incq %r15 0x55c6f5f6a16c <+44>: cmpq %r15, %r14 0x55c6f5f6a16f <+47>: jne 0x55c6f5f6a160 ; <+32> at d_original_example.c:5:10 0x55c6f5f6a171 <+49>: popq %rbx ; i = <undef> 0x55c6f5f6a172 <+50>: popq %r14 ; argv = RSI 0x55c6f5f6a174 <+52>: popq %r15 ; argc = RDI 0x55c6f5f6a176 <+54>: xorl %eax, %eax 0x55c6f5f6a178 <+56>: retq ``` Only transitions are shown: the start of a location, changes, and end-of-lifetime. --- ## Scope & limitations (by design) - Handles **simple locations** first (registers, const-in-register cases surfaced by `DumpLocation`). - **Memory/composite locations** are out of scope for this PR. - Annotations appear **only at range boundaries** (start/change/end) to minimize noise. - Output is **target-independent**; register names come from the target ABI. ## Implementation notes - All annotation printing now happens in `Disassembler::PrintInstructions()`. - Uses `std::unordered_map<lldb::user_id_t, std::string>` as the live map. - No persistent state across calls; the map is rebuilt while walking instruction by instruction. - **No changes** to the `Instruction` interface. --- ## Requested feedback - Placement and wording of the `<undef>` marker. - Whether we should optionally gate this behind a setting (currently always on when disassembling with an `ExecutionContext`). - Preference for immediate inclusion of tests vs. follow-up patch. --- Thanks for reviewing! Happy to adjust behavior/format based on feedback. --------- Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com> Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
2025-08-11[lldb] remove a superfluous assignment statement (#152669)Matej Košík
`cfa_reg_contents` is a local variable. Whatever value we assign there right before the `return` statement will be lost anyway. Co-authored-by: Matej Košík <matej.kosik@codasip.com>
2025-08-11[lldb][NFC] Address follow up comments in ExecutionContext (#153110)Felipe de Azevedo Piovezan
The PR https://github.com/llvm/llvm-project/pull/152020 got merged by accident. This commit addresses some follow up review comments.
2025-08-11[lldb] Guard SBFrame/SBThread methods against running processes (#152020)Felipe de Azevedo Piovezan
Prior to this patch, SBFrame/SBThread methods exhibit racy behavior if called while the process is running, because they do not lock the `Process::RetRunLock` mutex. If they did, they would fail, correctly identifying that the process is not running. Some methods _attempt_ to protect against this with the pattern: ``` ExecutionContext exe_ctx(m_opaque_sp.get(), lock); // this is a different lock Process *process = exe_ctx.GetProcessPtr(); if (process) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&process->GetRunLock())) .... do work ... ``` However, this is also racy: the constructor of `ExecutionContext` will access the frame list, which is something that can only be done once the process is stopped. With this patch: 1. The constructor of `ExecutionContext` now expects a `ProcessRunLock` as an argument. It attempts to lock the run lock, and only fills in information about frames and threads if the lock can be acquired. Callers of the constructor are expected to check the lock. 2. All uses of ExecutionContext are adjusted to conform to the above. 3. The SBThread.cpp-defined helper function ResumeNewPlan now expects a locked ProcessRunLock as _proof_ that the execution is stopped. It will unlock the mutex prior to resuming the process. This commit exposes many opportunities for early-returns, but these would increase the diff of this patch and distract from the important changes, so we opt not to do it here.
2025-08-11[lldb] Make StackID call Fix{Code,Data} pointers (#152796)Felipe de Azevedo Piovezan
In architectures where pointers may contain metadata, such as arm64e, it is important to ignore those bits when comparing two different StackIDs, as the metadata may not be the same even if the pointers are. This patch is a step towards allowing consumers of pointers to decide whether they want to keep or remove metadata, as opposed to discarding metadata at the moment pointers are created. See https://github.com/llvm/llvm-project/pull/150537. This was tested running the LLDB test suite on arm64e.
2025-08-08[lldb-dap] persistent assembly breakpoints (#148061)Ely Ronnen
Resolves #141955 - Adds data to breakpoints `Source` object, in order for assembly breakpoints, which rely on a temporary `sourceReference` value, to be able to resolve in future sessions like normal path+line breakpoints - Adds optional `instructions_offset` parameter to `BreakpointResolver`
2025-08-06[lldb] Use const ref for looping over frame recognizers (NFC) (#152334)Dave Lee