Fix and improve #187145 for following issues:
* Fix unhandled error.
* Align the log type with the file where it contains.
* The added test doesn't work on windows host for remote debugging, add
decorator to skip when host and target do not match.
Add a LoadCompilationPrefixMap() helper in SymbolFile::FindPlugin that
walks up from the symbol file's directory looking for a
compilation-prefix-map.json file. When found, each key→value entry is
applied to the module's source path mapping list, allowing LLDB to
resolve source file paths that were rewritten by -fdebug-prefix-map at
build time without requiring manual `settings set target.source-map`.
The JSON file format maps fake paths (as written into debug info) back
to their real on-disk counterparts:
{ "/fake/srcdir": "/real/srcdir" }
Directory results are cached so the filesystem is walked at most once
per unique directory across all modules loaded in a session.
Also apply the module's source path remappings in
SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex when constructing
compile units from N_SO stabs. This mirrors what MakeAbsoluteAndRemap
does for the dSYM case so that fake paths baked into the debug map are
transparently resolved to real paths.
rdar://84824567
Assisted-By: Claude
The [lldb-aarch64-windows](https://lab.llvm.org/buildbot/#/builders/141)
buildbot failed with:
```
lld-link: error: undefined symbol: printf
>>> referenced by main.o:(main)
```
I'm assuming that's because of the use of `__builtin_printf`. In other
tests, we use `printf` form `stdio.h` and these build fine, so I added
an include and used `printf`.
With MTE, the issue is caught by hardware and libmalloc records a
different message: "BUG IN CLIENT OF LIBMALLOC: MTE tag mismatch
(probable double-free)". Update the test accordingly.
Started passing when #185464 landed.
https://lab.llvm.org/buildbot/#/builders/211/builds/6880
UNEXPECTED SUCCESS: test_step_back_out_dwarf
(TestLongjmp.LongjmpTestCase.test_step_back_out_dwarf)
Test stepping when the inferior calls setjmp/longjmp, in particular,
thread step-out after thread step-in.
UNEXPECTED SUCCESS: test_step_out_dwarf
(TestLongjmp.LongjmpTestCase.test_step_out_dwarf)
Test stepping when the inferior calls setjmp/longjmp, in particular,
thread step-out.
(test_step_over is still expectedly failing)
It seems there may be a formatter bug when there's a time zone
difference between the target machine being debugged, and the host the
debugger is running on.
This is driven by the Swift language. In Swift many data types such as
Int, and String are structs, and LLDB provides summary formatters and
synthetic child providers for them. For String, for example, a summary
formatter pulls out the string data from the implementation, while a
synthetic child provider hides the implementation details from users, so
strings don't expand their children.
rdar://171646109
Synthetic providers for collection types use a child name format of
"[N]".
This `ValueObjectSynthetic` to automatically convert child names in this
convention to the index embedded in the subscript string. With this
change, synthetic formatters for collections will only need to implement
`GetIndexOfChildWithName` or `get_child_index` for non-indexed
collection children. Some examples of non-indexed children are
`$$dereference$$` support, or "hidden" children.
The automatic conversion applies to N values that are less than the
number of children reported by the synthetic provider.
I was working on something and broke the handling of breakpoint
conditions that crash. In fixing that I noticed that there wasn't a test
for this scenario, so this PR adds one.
---------
Co-authored-by: Med Ismail Bennani <ismail@bennani.ma>
This reverts commit 49c3cd15e8b4c21dd86eefdc76754ddfc2a7a65e.
I was going back and forth between llvm.org and my fork to prepare
this PR, but mistakenly pushed it from the wrong checkout.
Let's revert this and do it right...
When multiple threads are stopped at the same breakpoint, LLDB currently
steps each thread over the breakpoint one at a time. Each step requires
disabling the breakpoint, single-stepping one thread, and re-enabling
it, resulting in N disable/enable cycles and N individual vCont packets
for N threads. This is a common scenario for hot breakpoints in
multithreaded programs and scales poorly.
This patch batches the step-over so that all threads at the same
breakpoint site are stepped together in a single vCont packet, with the
breakpoint disabled once at the start and re-enabled once after the last
thread finishes.
At the top of WillResume, any leftover StepOverBreakpoint plans from a
previous cycle are popped with their re-enable side effect suppressed
via SetReenabledBreakpointSite, giving a clean slate.
SetupToStepOverBreakpointIfNeeded then creates fresh plans for all
threads that still need to step over a breakpoint, and these are grouped
by breakpoint address.
For groups with multiple threads, each plan is set to defer its
re-enable through SetDeferReenableBreakpointSite. Instead of re-enabling
the breakpoint directly when a plan completes, it calls
ThreadFinishedSteppingOverBreakpoint, which decrements a per-address
tracking count. The breakpoint is only re-enabled when the count reaches
zero.
All threads in the largest group are resumed together in a single
batched vCont packet. If some threads don't complete their step in one
cycle, the pop-and-recreate logic naturally re-batches the remaining
threads on the next WillResume call.
For 10 threads at the same breakpoint, this reduces the operation from
10 z0/Z0 pairs and 10 vCont packets to 1 z0 + 1 Z0 and a few
progressively smaller batched vCont packets.
EDIT:
Tried to merge this PR twice, the first time the test was flaky so we
had to revert. The second time, we broke 2 tests on windows machine:
https://lab.llvm.org/buildbot/#/builders/141/builds/15798
The tests that were failing were failing because the cleanup code in
`WillResume` was popping **ALL** `StepOverBreakpoint` plans, including
non-deferred ones from incomplete single-steps.
The issue was:
1) Multiple threads hit the same breakpoint. One thread's breakpoint
condition evaluates to false, so it needs to auto-continue.
2) A `StepOverBreakpoint` plan is created for that thread
(non-deferred).
3) On the next WillResume, the cleanup pops that non-deferred plan.
4) Now the `StopOthers` scan finds no thread with a StopOthers() plan,
so thread_to_run stays null.
5) The else branch runs, calling `SetupToStepOverBreakpointIfNeeded` on
**ALL** threads, including the thread that legitimately hit the
breakpoint with a true condition.
6) That thread gets a new `StepOverBreakpoint` plan pushed, which
overwrites its breakpoint stop reason with trace when the step
completes.
The error `trace (2) != breakpoint (3)` confirms this, the thread that
should have reported breakpoint as its stop reason instead reports
trace, because an unwanted `StepOverBreakpoint` plan was pushed on it
and completed.
The newly added code fixes it by only popping plans that have
`GetDeferReenableBreakpointSite() == true`
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
Re-land https://github.com/llvm/llvm-project/pull/180101 since it was
reverted here https://github.com/llvm/llvm-project/pull/182431 because
of a flaky test. This PR include the modified test that should pass from
https://github.com/llvm/llvm-project/pull/182415 :
When multiple threads are stopped at the same breakpoint, LLDB currently
steps each thread over the breakpoint one at a time. Each step requires
disabling the breakpoint, single-stepping one thread, and re-enabling
it, resulting in N disable/enable cycles and N individual vCont packets
for N threads. This is a common scenario for hot breakpoints in
multithreaded programs and scales poorly.
This patch batches the step-over so that all threads at the same
breakpoint site are stepped together in a single vCont packet, with the
breakpoint disabled once at the start and re-enabled once after the last
thread finishes.
At the top of WillResume, any leftover StepOverBreakpoint plans from a
previous cycle are popped with their re-enable side effect suppressed
via SetReenabledBreakpointSite, giving a clean slate.
SetupToStepOverBreakpointIfNeeded then creates fresh plans for all
threads that still need to step over a breakpoint, and these are grouped
by breakpoint address.
For groups with multiple threads, each plan is set to defer its
re-enable through SetDeferReenableBreakpointSite. Instead of re-enabling
the breakpoint directly when a plan completes, it calls
ThreadFinishedSteppingOverBreakpoint, which decrements a per-address
tracking count. The breakpoint is only re-enabled when the count reaches
zero.
All threads in the largest group are resumed together in a single
batched vCont packet. If some threads don't complete their step in one
cycle, the pop-and-recreate logic naturally re-batches the remaining
threads on the next WillResume call.
For 10 threads at the same breakpoint, this reduces the operation from
10 z0/Z0 pairs and 10 vCont packets to 1 z0 + 1 Z0 and a few
progressively smaller batched vCont packets.
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
There are two different ways to debug FreeBSD's kernel: core and remote
debugging. Remote debugging is done through `gdb-remote` plugin while
kernel dump and live core debugging is done through `freebsd-kernel`.
The name `freebsd-kernel` is vague for this reason, and following
`elf-core` and `mach-core`'s example, it would be clearer if this plugin
is renamed to `freebsd-kernel-core`.
---------
Signed-off-by: Minsoo Choo <minsoochoo0122@proton.me>
After https://github.com/llvm/llvm-project/pull/182297, we started generated `-gsimple-template-names` debug-info by default on macOS. The test was expecting template parameters in the error message. But with `simple-template-names` typenames would not contain template parameters (unless LLDB reconstructs them to do so). This formatter test was expecting template parameters, which would fail on macOS > 26.
Because the test is just concerned with checking that the `std::valarray` formatter works as expected (not that LLDB can retrieve typenames with/without template names), this patch relaxes the assertion.
In a follow-up we should fix up any type-name printing that would break with `simple-template-names`.
PR to fix failing test from
https://github.com/llvm/llvm-project/pull/180101 .
Fix the integration test to be resilient to non-deterministic thread
timing. Instead of requiring exact z0/Z0 counts, verify that batching
reduced toggles compared to one at a time stepping.
Also added: skip on `aarch64` where thread scheduling makes batching
unreliable.
Ran the test 20 times, passed all 20.
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
Following up from
https://discourse.llvm.org/t/improving-performance-of-multiple-threads-stepping-over-the-same-breakpoint/89637
When multiple threads are stopped at the same breakpoint, LLDB currently
steps each thread over the breakpoint one at a time. Each step requires
disabling the breakpoint, single-stepping one thread, and re-enabling
it, resulting in N disable/enable cycles and N individual vCont packets
for N threads.
Now we batch the step-over so that all threads at the same breakpoint
site are stepped together in a single vCont packet, with the breakpoint
disabled once at the start and re-enabled once after the last thread
finishes.
When we hit `WillResume` any leftover `StepOverBreakpoint` plans from a
previous cycle are popped with their re-enable side effect suppressed
via `SetReenabledBreakpointSite`, giving a clean slate.
`SetupToStepOverBreakpointIfNeeded` then creates fresh plans for all
threads that still need to step over a breakpoint, and these are grouped
by breakpoint address.
For groups with multiple threads, each plan is set to defer its
re-enable through `SetDeferReenableBreakpointSite`. Instead of
re-enabling the breakpoint directly when a plan completes, it calls
`ThreadFinishedSteppingOverBreakpoint`, which decrements a tracking
count per address. The breakpoint is only re-enabled when the count
reaches zero.
All threads in the largest group are resumed together in a single
batched vCont packet. If some threads don't complete their step in one
cycle, the pop-and-recreate logic naturally re-batches the remaining
threads on the next WillResume call.
Claude AI assisted in syntex fixes and making the comments more
understandable.
---------
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
#181283 removed fvc but it still remains in tests. This causes testing
on non-FreeBSD hosts. Thus add `skipUnlessPlatform` decorator.
Signed-off-by: Minsoo Choo <minsoochoo0122@proton.me>
PR #181720 introduced shared builds for LLDB API tests to improve test
efficiency. But several data formatter tests requiring PDB debug info
are failing on Windows x64 and AArch64 platforms.
This patch disables shared builds for these tests by setting
SHARED_BUILD_TESTCASE = False
The shared build optimization breaks these tests because they reuse
build artifacts between test methods
The test runs may could use multiple methods with different debug
formats or compiler flags. When a test runs first it builds with one set
of flags, but then it runs again but **make** sees the source unchanged
so it skips rebuilding and reuses the same old binary instead of
rebuilding with correct flags.
This changes Python API tests to use a single build shared across all
test functions, instead of the previous default behavior of a separate
build dir for each test function.
This build behavior opt-out, tests can use the previous behavior of one
individual (unshared) build directory per test function, by setting
`SHARED_BUILD_TESTCASE` to False (in the test class).
The motivation is to make the test suite more efficient, by not
repeatedly building the same test source. When running tests on my macOS
machine, this reduces the time of `ninja check-lldb-api` by almost 60%
(sample numbers: from ~492s down to ~207s = 58%). Almost 5min time
saved.
Each test function still calls `self.build()`, but only the first call
will do a build, in the subsequent tests `make` will be a no-op because
the sources won't have changed.
This revert #181334 and its follow-up PRs (including #181488, #181492,
#181493, #181494 and #181498) as well as Ismail's documentation changes
(#181594, #181717). The original commit causes a test failure in CI
(https://github.com/llvm/llvm-project/issues/181938) but the more I look
at the patch, the more I'm convinced it was not ready to land. It will
be easier to iterate on the feedback by re-landing this than by using
post-commit review.
This patch fixes where ELF cores will report all threads as `STOP REASON
0`.
This was/is a large personal annoyance of mine; added a test to verify a
default elf core process/thread has no valid stop reason.
## Summary
- Move `GetScriptedSymbolLocatorClassName()` from inline in `Target.h`
to out-of-line in `Target.cpp` to avoid collision with Windows
`winuser.h` `#define GetClassName GetClassNameW` macro.
- Replace `LaunchSimple(None, None, os.getcwd())` with
`lldbutil.run_to_breakpoint_do_run()` in `test_locate_source_file` to
fix test failure on remote platforms where the local working directory
doesn't exist.
Fixes CI failures from #181334.
## Test plan
- [ ] Windows (aarch64-windows) build passes
- [ ] remote-linux-win test passes
- [ ] Existing ScriptedSymbolLocator tests pass on local platforms
Co-authored-by: Rahul Reddy Chamala <rachamal@meta.com>
## Summary
Based on discussion from
[RFC](https://discourse.llvm.org/t/rfc-python-callback-for-source-file-resolution/83545),
this PR adds a new `SymbolLocatorScripted` plugin that allows Python
scripts to implement custom symbol and source file resolution logic.
This enables downstream users to build custom symbol servers, source
file remapping, and build artifact resolution entirely in Python.
### Changes
- Adds `LocateSourceFile()` to the SymbolLocator plugin interface,
called during source path resolution with a fully loaded `ModuleSP`, so
the plugin has access to the module's UUID, file paths, and symbols.
- Adds `SymbolLocatorScripted` plugin that delegates all four
SymbolLocator methods (`LocateExecutableObjectFile`,
`LocateExecutableSymbolFile`, `DownloadObjectAndSymbolFile`,
`LocateSourceFile`) to a user-provided Python class.
- Adds `ScriptedSymbolLocatorPythonInterface` to bridge C++ calls to
Python, with proper GIL management and error handling.
- Results for `LocateSourceFile` are cached per (module UUID, source
file) pair.
- The Python class is configured via: `settings set
plugin.symbol-locator.scripted.script-class module.ClassName`
### Python class interface
```python
class MyLocator:
def __init__(self, exe_ctx, args): ...
def locate_source_file(self, module, original_source_file):
...
def locate_executable_object_file(self, module_spec): ...
def locate_executable_symbol_file(self, module_spec,
default_search_paths): ...
def download_object_and_symbol_file(self, module_spec,
force_lookup, copy_executable): ...
```
### Test plan
```
Added TestScriptedSymbolLocator.py with 3 test cases:
- test_locate_source_file — verifies the locator resolves source
files, receives a valid SBModule with UUID, and remaps paths correctly
- test_locate_source_file_none_fallthrough — verifies returning
None falls through to default LLDB resolution, and that having no script
class set works normally
- test_invalid_script_class — verifies graceful handling of
invalid class names without crashing
```
Co-authored-by: Rahul Reddy Chamala <rachamal@fb.com>
This patch adds __getitem__ method to the SBAPI list classes that were
missing subscript support, enabling Pythonic index access (e.g.,
list[0], list[-1]) in Python bindings.
The implementation adds __getitem__ to the following classes:
- SBStringList
- SBFileSpecList
- SBProcessInfoList
- SBMemoryRegionInfoList
- SBThreadCollection
- SBBreakpointList
- SBModuleSpecList
- SBTypeList
Each implementation follows the same pattern:
- Type validation (raises TypeError for non-integer indices)
- Range validation with negative index support (raises IndexError for
out-of-range)
- Delegates to the appropriate Get*AtIndex() method
The changes are in SWIG interface extension files (.i), implementing the
__getitem__ method in Python bindings while maintaining compatibility
with existing Get*AtIndex() API.
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
StopCondition::SetText was computing the hash from the moved-from text
parameter instead of the stored m_text member. After std::move(text),
the source parameter becomes empty, causing the hash to always be
computed from an empty string.
This caused breakpoint condition updates to fail silently. When a user
modified a condition (e.g., from "x == y" to "x > y"), the hash remained
unchanged. Breakpoint locations use this hash to detect when conditions
need re-evaluation, so with a stale hash they would continue using
cached state for the old condition, triggering at incorrect locations.
The patch fixes this issue by computing the hash from m_text after the
move operation, ensuring it reflects the actual stored condition text.
It also adds API test that updates a breakpoint condition and verifies
the new condition is properly evaluated.
rdar://170191229
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
Several languages support some sort of "breakpoint" function, which adds
ISA-specific instructions to generate an interrupt at runtime. However,
on some platforms, these instructions don't increment the program
counter. When LLDB sets these instructions it isn't a problem, as we
remove them before continuing, then re-add them after stepping over the
location. However, for breakpoint sequences that are part of the
inferior process, this doesn't happen - and so users might be left
unable to continue past the breakpoint without manually interfering with
the program counter.
This patch adds logic to LLDB to intercept SIGTRAPs, inspect the bytes
of the inferior at the program counter, and if the instruction looks
like a BRK or BKPT or similar, increment the pc by the size of the
instruction we found. This unifies platform behaviour (e.g. on x86_64,
LLDB debug sessions already look like this) and improves UX (in my
opinion, but I think it beats messing with stuff every break).
Some ISAs (like AArch64) require slightly different handling, as while
there are multiple possible instructions, we should be careful only to
find the ones likely to have been emitted by a compiler backend, and not
those inserted from (for example) the UB sanitizer, or any others.
There is an existing builtin-debugtrap test which was under the macos
folder before. I've now moved that to "functionalities", made it pure C
only, and updated it a little bit so that it works regardless of
platform.
What I've not done is change the existing code in debugserver which was
added by Jason Molenda about five years ago
(https://reviews.llvm.org/D91238, 92b036d). It might not be required any
more after this change. Reading the history there, it seems like it was
agreed that this behaviour (skipping over unknown bps) was the desired
end goal.
Fixes#56268
---------
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
This reverts commit cc7292056683f592c33055bb6456d509201654ec.
This patch causes two tests to unexpectedly pass:
1. lldb-api.functionalities/tsan/cpp_global_location/TestTsanCPPGlobalLocation.py
2. lldb-api.functionalities/tsan/global_location/TestTsanGlobalLocation.py
Reverting to fix premerge. Not fixing forward so someone who is familiar
with LLDB can take a look and make sure those tests now should pass.
Ran my python script from
https://github.com/llvm/llvm-project/pull/97043 over the repo again and
there were 2 duplicate test-cases that have been introduced since I last
did this.
Also one of the WASM classes had a duplicate method which I just
removed.
We have a problem when some code on the private state thread needs to
run an expression. The private state thread is the one that fetches
"raw" events from the Process Plugin and decides how to handle them. But
if the private state thread needs to fetch the processed events to drive
running an expression, it can't also be the thread processing the raw
events.
We solve this by swapping in a modal private state thread just to handle
the events from the expression evaluation. That worked until you could
cause the expression evaluation to happen from Python, because then it
wasn't just the fetching of events that matter, but also the state of
the process and the state of the runlocks. The modal private state
thread is really a modal version of the thread and its associated state.
This patch gathers all the relevant control parameters into a structure
which we can swap in and out when needed.
It also adds a test using the new "was_hit" breakpoint resolver
affordance, which, since it acts as an asynchronous breakpoint callback,
gets run on the private state thread, showing that with the change we
can call expressions in the `was_hit` callback without problems.
We want to reload the call stack whenever the frame providers are
updated. To do so, we now emit a `eBroadcastBitStackChanged` on all
threads whenever any changes to the frame providers take place.
I found this very useful while iterating on a frame provider in
lldb-dap. So far, the new frame provider only took effect after
continuing execution. Now the backtrace in VS-Code gets refreshed
immediately upon running `target frame-provider add`.