mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 02:24:18 +00:00
Merge "backtrace: Strip PAC field when PAUTH is enabled" into integration
This commit is contained in:
commit
7871fff2a2
1 changed files with 59 additions and 0 deletions
|
@ -37,6 +37,47 @@ struct frame_record {
|
||||||
uintptr_t return_addr;
|
uintptr_t return_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip the Pointer Authentication Code (PAC) from the address to retrieve the
|
||||||
|
* original one.
|
||||||
|
*
|
||||||
|
* The PAC field is stored on the high bits of the address and defined as:
|
||||||
|
* - PAC field = Xn[54:bottom_PAC_bit], when address tagging is used.
|
||||||
|
* - PAC field = Xn[63:56, 54:bottom_PAC_bit], without address tagging.
|
||||||
|
*
|
||||||
|
* With bottom_PAC_bit = 64 - TCR_ELx.TnSZ
|
||||||
|
*/
|
||||||
|
#if ENABLE_PAUTH
|
||||||
|
static uintptr_t demangle_address(uintptr_t addr)
|
||||||
|
{
|
||||||
|
unsigned int el, t0sz, bottom_pac_bit;
|
||||||
|
uint64_t tcr, pac_mask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Different virtual address space size can be defined for each EL.
|
||||||
|
* Ensure that we use the proper one by reading the corresponding
|
||||||
|
* TCR_ELx register.
|
||||||
|
*/
|
||||||
|
el = get_current_el();
|
||||||
|
|
||||||
|
if (el == 3U) {
|
||||||
|
tcr = read_tcr_el3();
|
||||||
|
} else if (el == 2U) {
|
||||||
|
tcr = read_tcr_el2();
|
||||||
|
} else {
|
||||||
|
tcr = read_tcr_el1();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* T0SZ = TCR_ELx[5:0] */
|
||||||
|
t0sz = tcr & 0x1f;
|
||||||
|
bottom_pac_bit = 64 - t0sz;
|
||||||
|
pac_mask = (1ULL << bottom_pac_bit) - 1;
|
||||||
|
|
||||||
|
/* demangle the address with the computed mask */
|
||||||
|
return (addr & pac_mask);
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_PAUTH */
|
||||||
|
|
||||||
static const char *get_el_str(unsigned int el)
|
static const char *get_el_str(unsigned int el)
|
||||||
{
|
{
|
||||||
if (el == 3U) {
|
if (el == 3U) {
|
||||||
|
@ -57,6 +98,15 @@ static bool is_address_readable(uintptr_t addr)
|
||||||
{
|
{
|
||||||
unsigned int el = get_current_el();
|
unsigned int el = get_current_el();
|
||||||
|
|
||||||
|
#if ENABLE_PAUTH
|
||||||
|
/*
|
||||||
|
* When pointer authentication is enabled, the LR value saved on the
|
||||||
|
* stack contains a PAC. It must be stripped to retrieve the return
|
||||||
|
* address.
|
||||||
|
*/
|
||||||
|
addr = demangle_address(addr);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (el == 3U) {
|
if (el == 3U) {
|
||||||
ats1e3r(addr);
|
ats1e3r(addr);
|
||||||
} else if (el == 2U) {
|
} else if (el == 2U) {
|
||||||
|
@ -201,6 +251,15 @@ static void unwind_stack(struct frame_record *fr, uintptr_t current_pc,
|
||||||
*/
|
*/
|
||||||
call_site = fr->return_addr - 4U;
|
call_site = fr->return_addr - 4U;
|
||||||
|
|
||||||
|
#if ENABLE_PAUTH
|
||||||
|
/*
|
||||||
|
* When pointer authentication is enabled, the LR value saved on
|
||||||
|
* the stack contains a PAC. It must be stripped to retrieve the
|
||||||
|
* return address.
|
||||||
|
*/
|
||||||
|
call_site = demangle_address(call_site);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the address is invalid it means that the frame record is
|
* If the address is invalid it means that the frame record is
|
||||||
* probably corrupted.
|
* probably corrupted.
|
||||||
|
|
Loading…
Add table
Reference in a new issue