This change adds initial support for managing the Permission Overlay
Extension (POE). This extension allows userspace programs to change
memory permissions without making a sycall.
This is used to implement Linux's memory protection keys
(https://docs.kernel.org/core-api/protection-keys.html) on AArch64.
Overview of POE:
* Page table entries have a set of permissions. To change these, a
program would have to use a syscall which adds overhead.
* 3 bits of the page table entry are used for a protection key 0-7.
* POE adds a new register "por" (POR_EL0 in the manual) which stores
4-bit sets of permissions.
* The protection key is an index into this por register.
* Permissions in POR are applied on top of the page table permissions,
but may only remove permissions. For example, if you overlay
read/execute over read/write, the result is read. Since execute was not
in the page table permissions.
* This register can be modified without leaving userspace, making
permission changes faster.
To help debug this, I have made the following changes to LLDB:
* Ability to read and write the por register.
* Save and restore of por when running expressions.
* Register field definitions to print the por permissions in a human
readable form.
* Recognition of memory protection key faults as a distinct type of
SIGSEGV (this will apply to Linux on any architecture).
There are a few more features to add around memory region information,
that will be in follow up changes. As will documentation and release
notes for all the POE features.
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.
https://github.com/llvm/llvm-project/pull/181143 introduced a regression
in Windows build bots, which is due to some Unicode characters not being
rendered properly.
The proper fix is to be able to configure the characters that are
rendered, and to force them to be ascii characters.
This is a reland of https://github.com/llvm/llvm-project/pull/167550.
Instead of relying on libcpp for testing, we emulate our own hidden
frames. This was originally causing tests failures on Windows.
This patch adds cross platform (Darwin, Linux, Windows) commands in
`Makefile.rules` which is used to build lldb test targets.
This maps POSIX commands like `mkdir -p` to their Windows equivalent,
which allows to create cross platform `Makefile` for lldb's test
targets. This is currently not needed by any test but might become
useful later as we are working on enabling more lldb Windows tests.
This was originally done in the `swiftlang/llvm-project` fork
(https://github.com/swiftlang/llvm-project/pull/12127)
EvaluateRequests handler now uses the target's context if no valid
frameId is provided, enabling evaluation of
global variables without requiring a valid stack frame.
In repl mode it now uses the last `successful` variable or command
expression, if the provided user's expression is empty.
Try to evaluate the expression if the evaluation context is `Unknown`
We are waiting for both stopped event at once.
We may not get both events within the (0.25 seconds) time interval to
fetch more events. Retry with the `DEFAULT TIMEOUT` if we got one of the
event.
Increase the `EVENT_QUIET_PERIOD`'s value for ASAN mode
Fixes#179648
Allows API tests to pass `SBExpressionOptions` when testing a successful
expression evaluation with `expect_expr`. Currently one would have to
use `SBFrame::EvaluateExpression` or pass the option as an argument to
the raw command (via `expect()` or `HandleCommand()`).
Chose not to do the `SetIgnoreBreakpoints`/`SetAutoApplyFixIts` with the
assumption that most expression evaluation tests don't actually need to
care about these. If the options are passed explicitly, lets use them
as-is. Otherwise default to the old options.
First usage of this new parameter would be in
https://github.com/llvm/llvm-project/pull/177926
Updates the 'stopped' event to use structure types.
Additionally, I adjusted the description to include the full
`GetStopDescription` that can have more details.
This restores files that were unintentionally added to commit
21a74f527839b5b8dd882e62a25093d980c79078, 'Revert "[lldb] Add FP
conversion instructions to IR interpreter (#175292)"'
Closes#119784
Probably closes#147105 as well, but I couldn't test due to #156473:
This PR fixes two bugs:
1. It generates unique variable reference IDs per suspended debuggee
state.
2. It stores all created variables in a stopped state instead of
dropping variables in unselected scopes. So it can properly handle all
scope/variable requests
It does this by storing all variables in their respective scopes and
using that mapping in request handlers that relied on the old mapping.
It dynamically creates new variable/scope IDs instead of resetting IDs
whenever a new scope is created.
I also removed some unused code as well.
---------
Co-authored-by: Med Ismail Bennani <ismail@bennani.ma>
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
Co-authored-by: Ebuka Ezike <yerimyah1@gmail.com>
the ubsan decorator previously assumes the platform is macOS.
macOS has an extra underscore in symbols names match two or more.
uses the llvm-nm that is built instead of the system's nm.
In the exceptionInfo request I've added additional information for crash
data, instrumentation data and more detailed exception data.
For example, when UBSan is enabled, you now see additional information
in the exception stack trace about the detected issue:
<img width="1728" height="538" alt="Screenshot 2026-01-15 at 3 05 08 PM"
src="https://github.com/user-attachments/assets/b761af2c-90ac-4eb7-9926-3ab133f1b753"
/>
I included a new test for stopping at `lldb::eStopReasonInstrumentation`
and ensuring we have additional information reported.
---------
Co-authored-by: Ebuka Ezike <yerimyah1@gmail.com>
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
Investigating some of the biggest slow downs during tests, the biggest
offender is 'wait_for_stopped' requiring a negative assertion around the
'stopped' event.
It currently waits for a negative predicate to fail before continuing.
This means it must wait for the full DEFAULT_TIMEOUT (50s) before the
test is allowed to continue.
To mitigate this, I added a new `collect_events` helper that will wait
for the given event to occur with the DEFAULT_TIMEOUT, then wait for a
quiet period (0.25s) before returning.
This greatly reduces the amount of idle waiting during tests.
Additionally, looking a the performance of individual test files,
`TestDAP_launch` is the slowest overall test. No individual test is that
slow, but the fact it has so many tests in the same file results in the
test harness waiting for that one file to finish.
To mitigate that, I split `TestDAP_launch` into individual test files
that run in parallel, reducing the runtime locally from over 2mins to
~5s.
When a server is unable to allocate memory for the `_M` packet, it may
respond with an error code. In this case,
`GDBRemoteCommunicationClient::AllocateMemory()` sets
`m_supports_alloc_dealloc_memory` to `eLazyBoolYes`; `eLazyBoolNo` is
only used if the server cannot handle the packet at all. Before this
patch, `ProcessGDBRemote::DoAllocateMemory()` checked this flag and
returned `LLDB_INVALID_ADDRESS` without setting an error, which caused
`Process::CanJIT()` to set `m_can_jit = eCanJITYes`, resulting in
`IRMemoryMap::FindSpace()` attempting to allocate memory in the inferior
process and failing. With the patch,
`ProcessGDBRemote::DoAllocateMemory()` returns an error and `m_can_jit`
is set to `eCanJITNo`.
Example debug session:
```
(lldb) platform connect...
(lldb) file test
(lldb) br set...
(lldb) run
Process 100 launched:...
Process 100 stopped
* thread #1,...
(lldb) expr $x0
error: Couldn't allocate space for materialized struct: Couldn't malloc: address space is full
error: errored out in virtual lldb_private::LLVMUserExpression::DoExecute, couldn't PrepareToExecuteJITExpression
```
This decorator is trying to reference the file that is already deleted
by the time the `nm` call is made.
Fix this by correcting how `_compiler_supports` the `output_file`
argument.
lldb-dap currently crashes when the first character is non ascii. This
is because we assume that the request column is ascii based instead of
UTF16 code units,
and end up in the middle of a character code point. causing an assertion
since we cannot not send invalid UTF-8 values.
This also handles the case in multilines and the column is outside the
range of the text.
Move completion description to the `CompletionItem.detail` property.
**This patch adds a marker to make hidden frames more explicit.**
---
Hidden frames can be confusing for some users, who see that the indexes
of the frames in a backtrace are not contiguous. This patch aims to
lessen the confusion by adding a delimiter for the first and last non
hidden frame, i.e the boundaries.
IDE's like Xcode and VSCode represent those in the UI by having the
hidden frames either greyed out or collapsed.
It's not possible to do this in the CLI, therefore, this patch makes use
of 2 unicode characters to mark the beginning and end of the hidden
frames range.
This patch depends on:
- https://github.com/llvm/llvm-project/pull/168603
# Examples
In the example below, frame `#2` to `#7` are is hidden, and therefore,
frame `#1` is the first non hidden frame of the range while frame `#8`
is the last non hidden frame:
<img width="488" height="112" alt="Screenshot 2025-11-18 at 18 41 11"
src="https://github.com/user-attachments/assets/a21431da-9729-4cf0-a6bc-024aa306fc45"
/>
If the selected frame is one of the 2 boundary frames, we replace the
delimiter character with the select character (`*`).
<img width="487" height="111" alt="Screenshot 2025-11-18 at 18 41 03"
src="https://github.com/user-attachments/assets/5616fa81-6db6-457d-9d1e-bbe46e710c26"
/>
<img width="488" height="111" alt="Screenshot 2025-11-18 at 18 40 55"
src="https://github.com/user-attachments/assets/93dfa6cf-0956-4718-b31c-f965ec72b56d"
/>
This makes it clear the fields required for attaching to an existing
debug session.
It also makes it easier to check mutually exclusive fields required to
attach.
There are some bugs when launching in terminal with args and stdio
redirection.
- lldb-dap `--stdio` args is passed to the debuggee (should we change
this to use `--` to separate debuggee args from lldb-dap args, similar
to how we handle the `--client` args? ).
#### It also changes the behaviour of stdio redirection.
If a redirection is not specified, it uses to lldb default value. e.g.
```jsonc
"stdio": ["./stdin"]`
// now becomes
"stdio", ["./stdio", "./default_stdout", "./default_stderr"]
// instead of
"stdio", ["./stdin", "./stdin", "./stdin"]
// took quite some time to figure out where my output is going to.
```
Fixes [#174445](https://github.com/llvm/llvm-project/issues/174445)
Other bug I noticed but should be in a different PR.
- debuggee args that contains newline are not properly escaped when sent
to the terminal.
Implementation files using the Intel syntax typically explicitly specify it.
Do the same for the few files using AT&T syntax.
This enables building LLVM with `-mllvm -x86-asm-syntax=intel` in one's Clang config files
(i.e. a global preference for Intel syntax).
Unreverts: 14c69497b31038b37c273417f43bd2cfe169c86f
The cause is that in `python3.14`, `fcntl.ioctl` now throws a buffer
overflow error
when the buffer is too small or too large (see
https://github.com/python/cpython/pull/132919). This caused the Python
interpreter to fail terminal detection and not properly echo user
commands back to the screen.
Fix by dropping the custom terminal size check entirely and using the
built-in `sys.stdin.isatty()` instead.
Fixes#173302
I know this is required for at least one feature, because
TestSectionAPI.py has failures if zlib isn't enabled. So I think it's
useful for users to be able to check.
Now that it's in the config, I have also used it to make a test
annotation so we don't get the failure in TestSectionAPI.py when zlib is
disabled.
Which for future reference was:
Traceback (most recent call last):
File
"/home/davspi01/llvm-project/lldb/packages/Python/lldbsuite/test/decorators.py",
line 452, in wrapper
return func(self, *args, **kwargs)
File
"/home/davspi01/llvm-project/lldb/test/API/python_api/section/TestSectionAPI.py",
line 67, in test_compressed_section_data
self.assertEqual(section_data, [0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
0x80, 0x90])
AssertionError: Lists differ: [] != [32, 48, 64, 80, 96, 112, 128, 144]
As it failed to decode the compressed section.
This patch fixes a timeout in the monitor thread of the
`test_by_name_waitFor` test.
Currently, if `self.attach` fails, the `spawn_thread` will never finish
and the test will eventually timeout after the 15mins timeout. We now
ensure that we always join the thread at the end of the test.
Additionally, this change also uses of the `spawnSubprocess` method to
create the process. This should ensure the process is always properly
cleaned up after an exception occurs.
In https://github.com/llvm/llvm-project/pull/170523 it was pointed out
that the spec does specifically specify that launch/attach should not
respond until configurationDone is handled.
This means we do need to support async request handlers. To better align
with the spec, I've added a new `lldb_dap::AsyncRequestHandler`. This is
an additional handler type that allows us to respond at a later point.
Additionally, I refactored `launch` and `attach` to only respond once
the `configurationDone` is complete, specifically during the `PostRun`
operation of the `configurationDone` handler.
I merged some of the common behavior between `RequestHandler` and
`AsyncRequestHandler` into their common `BaseRequestHandler`.
The flow should now be:
```
<-> initialize request / response
--> launch/attach request
<-- event initialized
... optionally ...
<-> setBreakpoints request / response
<-> setFunctionBreakpoints request / response
<-> setExceptionBreakpoints request / response
<-> setInstructionBreakpoints request / response
... finally ...
<-> configurationDone request / response
<-- launch/attach response
```
---------
Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
Python 3.8 does not support subscriptable built-in types (dict[int],
list[str], etc.) without importing annotations from __future__.
This change adds `annotations` imports and handles missing API
functions.
This patch refactors the way we check for the windows version in the
`@skipIfWindows` decorator.
The new logic reuses the `expectedCompilerVersion` method logic for the
parsing and comparison of the version.
When using --platform remote-* options, explicitly clear the libcxx
configuration variables instead of just warning and continuing with
potentially set values. This prevents the test suite from attempting to
use custom libcxx paths on remote platforms where they're not
applicable.
Also initialize libcxx variables to None when not specified, ensuring a
clean state regardless of how the arguments are parsed.
Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
Flag changes reverted as those require the X86 target to be enabled.
Don't have time to test fixes as I need to go to sleep so will revert for now.
Reverts: 423919d31f4b55f22b09cd5066534f7c91e71d4b