Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions lldb/docs/use/aarch64-linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,64 @@ bytes.

`zt0`'s value and whether it is active or not will be saved prior to
expression evaluation and restored afterwards.

## Guarded Control Stack Extension (GCS)

GCS support includes the following new registers:

* `gcs_features_enabled`
* `gcs_features_locked`
* `gcspr_el0`

These map to the registers ptrace provides. The first two have a `gcs_`
prefix added as their names are too generic without it.

When the GCS is enabled the kernel allocates a memory region for it. This region
has a special attribute that LLDB will detect and presents like this:
```
(lldb) memory region --all
<...>
[0x0000fffff7a00000-0x0000fffff7e00000) rw-
shadow stack: yes
[0x0000fffff7e00000-0x0000fffff7e10000) ---
```

`shadow stack` is a generic term used in the kernel for secure stack
extensions like GCS.

### Expression Evaluation

To execute an expression when GCS is enabled, LLDB must push the return
address of the expression wrapper (usually the entry point of the program)
to the Guarded Control Stack. It does this by decrementing `gcspr_el0` and
writing to the location now pointed to by `gcspr_el0` (instead of using the
GCS push instructions).

After an expression finishes, LLDB will restore the contents of all 3
GCS registers, apart from the enable bit of `gcs_features_enabled`. This is
because there are limits on how often and from where you can set this
bit.

GCS cannot be enabled from ptrace and it is expected that a process which
has enabled and then disabled GCS, will not enable it again. The simplest
choice was to not restore the enable bit at all. It is up to the user or
program to manage that bit.

The return address that LLDB pushed onto the Guarded Control Stack will be left
in place. As will any values that were pushed to the stack by functions run
during the expression.

When the process resumes, `gcspr_el0` will be pointing to the original entry
on the guarded control stack. So the other values will have no effect and
likely be overwritten by future function calls.

LLDB does not track and restore changes to general memory during expressions,
so not restoring the GCS contents fits with the current behaviour.

Note that if GCS is disabled and an expression enables it, LLDB will not
be able to setup the return address and it is up to that expression to do that
if it wants to return to LLDB correctly.

If it does not do this, the expression will fail and although most process
state will be restored, GCS will be left enabled. Which means that the program
is very unlikely to be able to progress.
Loading