diff options
author | Jens Remus <jremus@linux.ibm.com> | 2024-04-09 15:59:12 +0200 |
---|---|---|
committer | Jens Remus <jremus@linux.ibm.com> | 2024-05-16 13:32:22 +0200 |
commit | 4e3cdaa9746d323edc54f87f7b9f3a219735ff6b (patch) | |
tree | ff645b74894d1693355e3181d91a55060185163e /libsframe/sframe-dump.c | |
parent | 135ff0670c7dcd839acb9d49551742d4365a0edf (diff) | |
download | gdb-4e3cdaa9746d323edc54f87f7b9f3a219735ff6b.zip gdb-4e3cdaa9746d323edc54f87f7b9f3a219735ff6b.tar.gz gdb-4e3cdaa9746d323edc54f87f7b9f3a219735ff6b.tar.bz2 |
s390: SFrame track FP/RA saved in register
GCC on s390x, when in a leaf function, can be observed to save the
frame pointer (FP) and/or return address (RA) register in a floating-
point registers (FPR) instead of on the stack. This is declared using
the following CFI directive:
.cfi_register <fp/ra-regno>, <fpr-regno>
SFrame cannot represent the FP and/or RA being saved in another
register. It does only track the CFA base register (SP/FP), CFA offset
from CFA base register, and FP and RA save area offsets from CFA.
On s390x the FP and/or RA are only saved in another FPR when in a leaf
function. That is a function that does not call any other functions.
Therefore it can ever only be the topmost function in a call chain.
During function return, if the RA would be restored into a non-default
RA register, the function would also only ever be the topmost function
on the call stack.
An unwinder by default has access to all registers of the function that
if the topmost on the call stack. Therefore no further information would
be required for those registers.
Represent the FP/RA in another register on s390, by encoding the
register number shifted by one to the left with the least-significant
bit set in the offset as follows:
offset = (regno << 1) | 1
Add s390-specific SFrame (error) test cases for FP/RA being saved in
FPRs in leaf-function.
gas/
* gen-sframe.c (s390_sframe_xlate_do_register): New s390-
specific function to represent FP/RA in another register on
s390.
(sframe_xlate_do_register): Invoke s390_sframe_xlate_do_register
on s390.
libsframe/
* sframe-dump.c (is_sframe_abi_arch_s390): New helper to test
whether ABI/arch is s390.
(dump_sframe_func_with_fres): Dump FP/RA in another register on
s390.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: Update s390-specific SFrame
(error) test cases.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.s: Rename
to ...
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-2.d:
Likewise.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.s: This. Test
case no longer triggers a warning, as SFrame can represent FP
and RA saved in registers.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-1.d: Likewise.
* gas/cfi-sframe/cfi-sframe-s390-fpra-register-err-1.d: Test
case now triggers a different warning, as SFrame can represent
FP and RA saved in registers, but not FP without RA saved in
register.
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Diffstat (limited to 'libsframe/sframe-dump.c')
-rw-r--r-- | libsframe/sframe-dump.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c index 69633d5..40ea531 100644 --- a/libsframe/sframe-dump.c +++ b/libsframe/sframe-dump.c @@ -40,6 +40,14 @@ is_sframe_abi_arch_aarch64 (sframe_decoder_ctx *sfd_ctx) return aarch64_p; } +/* Return TRUE if the SFrame section is associated with the s390 ABIs. */ + +static bool +is_sframe_abi_arch_s390 (sframe_decoder_ctx *sfd_ctx) +{ + return sframe_decoder_get_abi_arch (sfd_ctx) == SFRAME_ABI_S390_ENDIAN_BIG; +} + static void dump_sframe_header (sframe_decoder_ctx *sfd_ctx) { @@ -175,7 +183,12 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx, /* Dump SP/FP info. */ if (err[1] == 0) - sprintf (temp, "c%+d", fp_offset); + { + if (is_sframe_abi_arch_s390 (sfd_ctx) && (fp_offset & 1)) + sprintf (temp, "r%d", fp_offset >> 1); + else + sprintf (temp, "c%+d", fp_offset); + } else strcpy (temp, "u"); printf ("%-10s", temp); @@ -187,7 +200,12 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx, != SFRAME_CFA_FIXED_RA_INVALID) strcpy (temp, "f"); else if (err[2] == 0) - sprintf (temp, "c%+d", ra_offset); + { + if (is_sframe_abi_arch_s390 (sfd_ctx) && (ra_offset & 1)) + sprintf (temp, "r%d", ra_offset >> 1); + else + sprintf (temp, "c%+d", ra_offset); + } else strcpy (temp, "u"); |