mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
s390: Represent FP without RA saved in SFrame
If an architecture uses both SFrame RA and FP tracking SFrame assumes that the RA offset is the 2nd offset and the FP offset is the 3rd offset following a SFrame FRE. An architecture does not necessarily need to save both on the stack (or in register) at the same time or even at all. SFrame cannot represent FP without RA saved on stack (or in a register), since it cannot distinguish whether the 2nd offset is the RA or FP offset. For s390x use an invalid SFrame RA offset from CFA value of zero as padding to represent the FP being saved when the RA is not saved. This aligns with the existing invalid SFrame fixed RA offset from CFA value of zero. In a stack tracer this then also naturally falls into place, as it can skip restoring the RA in the topmost frame, if both the fixed RA offset (from SFrame header) and the RA offset (from FDE) are zero, without any need to test architecture-specific flags. include/ * sframe.h (SFRAME_FRE_RA_OFFSET_INVALID): New define. Used as padding offset. * sframe-api.h (sframe_fre_get_ra_offset): Add comment that for s390x an offset value of SFRAME_FRE_RA_OFFSET_INVALID indicates that the RA is not saved. gas/ * gen-sframe.c (get_fre_num_offsets): For s390x account padding RA offset, if FP without RA saved. (sframe_get_fre_offset_size): Likewise. (output_sframe_row_entry): For s390x write a padding RA offset, if FP without RA needs to be represented. (sframe_do_fde): Enable FP without RA saved to be represented on s390x. libsframe/ * sframe.c (sframe_fre_get_ra_offset): Add comment that for s390x an offset value of SFRAME_FRE_RA_OFFSET_INVALID indicates that the RA is not saved. * sframe-dump.c (dump_sframe_func_with_fres): Treat invalid RA offsets as if they were undefined. Display them as "U" to distinguish them. * doc/sframe-spec.texi (s390x): Document s390x-specific use of SFRAME_FRE_RA_OFFSET_INVALID to represent FP without RA saved. gas/testsuite/ * gas/cfi-sframe/cfi-sframe.exp: Rename s390x-specific tests. * gas/cfi-sframe/cfi-sframe-s390x-fpra-offset-err-1.s: Rename to ... * cfi-sframe/cfi-sframe-s390x-fpra-offset-err-1.d: Likewise. * gas/cfi-sframe/cfi-sframe-s390x-fpra-offset-2.s: This. * gas/cfi-sframe/cfi-sframe-s390x-fpra-offset-2.d: Likewise. Update test verification pattern accordingly. * cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.s: Rename to ... * cfi-sframe/cfi-sframe-s390x-fpra-register-err-1.d: Likewise. * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.s: This. * gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.d: Likewise. Update test verification pattern accordingly. Signed-off-by: Jens Remus <jremus@linux.ibm.com>
This commit is contained in:
@@ -152,6 +152,9 @@ DWARF register number.
|
||||
FP/RA offset.
|
||||
@item SFRAME_V2_S390X_OFFSET_DECODE_REGNUM: Decode a DWARF register number from
|
||||
an FP/RA offset.
|
||||
@item SFRAME_FRE_RA_OFFSET_INVALID: Invalid RA offset value (like
|
||||
SFRAME_CFA_FIXED_RA_INVALID). Used on s390x as padding offset to represent
|
||||
FP without RA saved.
|
||||
@end itemize
|
||||
@end itemize
|
||||
|
||||
@@ -890,12 +893,13 @@ The (64-bit) s390x ELF ABI does not mandate the precise location in a function
|
||||
where the return address (RA) and frame pointer (FP) are saved, if at all.
|
||||
Hence the need to track RA in the SFrame stack trace format. As RA is being
|
||||
tracked in this ABI, the second stack offset is always used to locate the RA
|
||||
stack slot, by interpreting it as: RA = CFA + offset2. RA remains unchanged,
|
||||
if the offset is not available. Stack tracers are recommended to validate that
|
||||
the "unchanged RA" pattern, when present, is seen only for the topmost stack
|
||||
frame. The third stack offset is used to locate the FP stack slot, by
|
||||
interpreting it as: FP = CFA + offset3. FP remains unchanged, if the offset is
|
||||
not available.
|
||||
stack slot, by interpreting it as: RA = CFA + offset2, unless the offset has a
|
||||
value of @code{SFRAME_FRE_RA_OFFSET_INVALID}. RA remains unchanged, if the
|
||||
offset is not available or has a value of @code{SFRAME_FRE_RA_OFFSET_INVALID}.
|
||||
Stack tracers are recommended to validate that the "unchanged RA" pattern, when
|
||||
present, is seen only for the topmost stack frame. The third stack offset is
|
||||
used to locate the FP stack slot, by interpreting it as: FP = CFA + offset3.
|
||||
FP remains unchanged, if the offset is not available.
|
||||
|
||||
In leaf functions the RA and FP may be saved in other registers, such as
|
||||
floating-point registers (FPRs), instead of on the stack. To represent this
|
||||
@@ -919,6 +923,7 @@ Hence, in summary:
|
||||
@item 1 @tab CFA = @code{BASE_REG} + offset1
|
||||
@item 2 @tab RA stack slot = CFA + offset2, if (offset2 & 1 == 0)
|
||||
@*RA register number = offset2 >> 1, if (offset2 & 1 == 1)
|
||||
@*RA not saved if (offset2 == @code{SFRAME_FRE_RA_OFFSET_INVALID})
|
||||
@item 3 @tab FP stack slot = CFA + offset3, if (offset3 & 1 == 0)
|
||||
@*FP register number = offset3 >> 1, if (offset3 & 1 == 1)
|
||||
@end multitable
|
||||
|
||||
@@ -211,6 +211,10 @@ dump_sframe_func_with_fres (sframe_decoder_ctx *sfd_ctx,
|
||||
if (sframe_decoder_get_fixed_ra_offset (sfd_ctx)
|
||||
!= SFRAME_CFA_FIXED_RA_INVALID)
|
||||
strcpy (temp, "f");
|
||||
/* If an ABI does track RA offset, e.g. s390x, it can be a padding
|
||||
to represent FP without RA being saved on stack. */
|
||||
else if (err[2] == 0 && ra_offset == SFRAME_FRE_RA_OFFSET_INVALID)
|
||||
sprintf (temp, "U");
|
||||
else if (err[2] == 0)
|
||||
{
|
||||
if (is_sframe_abi_arch_s390x (sfd_ctx)
|
||||
|
||||
@@ -733,6 +733,8 @@ sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx,
|
||||
|
||||
/* Get the RA offset from the FRE. If the offset is invalid, sets errp.
|
||||
|
||||
For s390x an RA offset value of SFRAME_FRE_RA_OFFSET_INVALID indicates
|
||||
that the RA is not saved, which is only valid in the topmost frame.
|
||||
For s390x the offset may be an encoded register number, indicated by
|
||||
LSB set to one, which is only valid in the topmost frame. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user