]> gcc.gnu.org Git - gcc.git/commit
Morello unwinder including register merging.
authorMatthew Malcomson <matthew.malcomson@arm.com>
Wed, 2 Nov 2022 14:51:15 +0000 (14:51 +0000)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Wed, 2 Nov 2022 14:51:15 +0000 (14:51 +0000)
commit5ddc12ffe4f6bc3953635fe8e29d11ec1a7d7494
treeb0cce8f405884fd4f104bb8d996a399d5538c2e3
parentb8ad03811a0703efe77111e11ffd20f28b6b12fa
Morello unwinder including register merging.

This is the first step towards getting unwinding past signal frames
working correctly.

When unwinding past signal frames we have to look in different places
to restore registers.  Usually there is a DWARF description telling the
unwinder where to find register information, but there is not in signal
frames.

A signal frame is identified by looking at the instructions which are
pointed to by the LR.  For a signal frame these are known to be a
special kernel trampoline that can be identified by its code.

Usually on a Morello-Linux system the CLR is sealed, which means that
the instructions pointed to be the CLR could not be read.  However this
is specifically not the case for the CLR in a signal frame.  Hence the
same mechanism by which we can inspect the trampoline for non-Morello
systems can be used again.
The kernel provides an extension context containing the capability
metadata for each register.  We could directly take all registers from
there but this gives a slightly different behaviour to what happens in a
non-Morello system.  For Morello the kernel "merges" registers on
returning from a signal frame.  This only matters if a signal handler
has modified the saved registers on the stack, and we do not believe
this case is ever really used.  However it's still nice to match
logical behaviour.

The "merging" happens by taking the u64 values in the standard signal
context and combining them with the capability metadata for each
corresponding register in the morello_context extension.  This means
that a signal frame can change the values in its callers by adjusting
the values in this non-capability structure.  Hence in order to unwind
in such a way that the unwinder would see the same register values as
the user-frame above the signal handler would see we need to express
this register "merging" for uw_update_context to handle.

The unwinder first makes a description of how to calculate registers in
the frame above, and later uses that description to update the relevant
register.

In order to describe the "register merging" that the kernel does on
returning from a signal frame we need some new description mechanism.

Here we introduce a new enum value REG_SAVED_SET_ADDRESS to describe
this register merging behaviour.  The enum makes use of a new entry in
the _Unwind_FrameState `loc` union which records two offsets.  It
happens that for Pure Capability targets the offset is half the size of
a pointer, which means that we can record these two offsets in the `loc`
union without increasing the size of an _Unwind_FrameState.
libgcc/config/aarch64/linux-unwind.h
libgcc/unwind-dw2.c
libgcc/unwind-dw2.h
This page took 0.064277 seconds and 6 git commands to generate.