s390: Store SFrame CFA offset adjusted

In SFrame V2 the size of the offsets following an SFrame FRE can be
either signed 8-bit, 16-bit, or 32-bit integer, with the largest offset
determining their size:
  1. CFA offset from CFA base register
  2. RA (stack save slot) offset from CFA, usually -48 on s390x if saved
  3. FP (stack save slot) offset from CFA, usually -72 on s390x if saved
The FP and RA offsets from CFA, when FP/RA saved on the stack, usually
have fixed values that fit into signed 8-bit SFrame offsets.  Likewise
the DWARF register numbers on s390x of general registers (GR; 0-15) and
floating-point registers (FPR; 16-31), when FP/RA saved in registers.
With that the CFA offset from CFA base register has the greatest impact
on the signed SFrame offset size.

The s390x ELF ABI [1] defines the CFA as stack pointer (SP) at call
site +160. [2]  Therefore the minimum CFA offset from CFA base register
on s390x is 160.  This does not fit into a signed 8-bit integer and
therefore effectively prevents any use of signed 8-bit SFrame offsets
on s390x.

For s390x store the CFA offset from CFA base register adjusted by -160
to enable the use of signed 8-bit SFrame offsets.

[1]: s390x ELF ABI, https://github.com/IBM/s390x-abi/releases
[2]: s390x ELF ABI, commit 4e38ad9c8a88 ("Document the CFA"),
     https://github.com/IBM/s390x-abi/commit/4e38ad9c8a88

include/
	* sframe.h (SFRAME_S390X_CFA_OFFSET_ADJUSTMENT): Define
	s390x-specific CFA offset adjustment.
	(SFRAME_V2_S390X_CFA_OFFSET_ENCODE,
	SFRAME_V2_S390X_CFA_OFFSET_DECODE): New s390x-specific
	macros.  Use SFRAME_S390X_CFA_OFFSET_ADJUSTMENT to en-/decode
	CFA offset.

bfd/
	* elf64-s390.c (elf_s390x_sframe_plt_fre): Use
	SFRAME_V2_S390X_CFA_OFFSET_ENCODE on CFA offset to store it
	adjusted and switch to 8-bit offsets.

gas/
	* gen-sframe.c (sframe_fre_set_cfa_offset): For s390x use
	SFRAME_V2_S390X_CFA_OFFSET_ENCODE on CFA offset to store it
	adjusted.
	(sframe_fre_get_cfa_offset): New helper.  For s390x use
	SFRAME_V2_S390X_CFA_OFFSET_DECODE on CFA offset to undo its
	adjustment.
	(sframe_xlate_do_def_cfa_register): Use new helper
	sframe_fre_get_cfa_offset.

libsframe/
	* sframe.c (sframe_fre_get_cfa_offset): For s390x use
	SFRAME_V2_S390X_CFA_OFFSET_DECODE on CFA offset to undo its
	adjustment.
	* doc/sframe-spec.texi (s390x,
	SFRAME_S390X_CFA_OFFSET_ADJUSTMENT,
	SFRAME_V2_S390X_CFA_OFFSET_ENCODE,
	SFRAME_V2_S390X_CFA_OFFSET_DECODE): Document s390x-specific
	adjustment of CFA offset.

libsframe/testsuite/
	* libsframe.find/plt-findfre-2.c (add_plt0_fde, add_pltn_fde):
	Use SFRAME_V2_S390X_CFA_OFFSET_ENCODE to enable use of 1-byte
	SFrame offsets.

Suggested-by: Indu Bhagat <indu.bhagat@oracle.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
This commit is contained in:
Jens Remus
2025-07-11 10:29:40 +02:00
parent 0d4d5a2633
commit c1056133a3
6 changed files with 54 additions and 10 deletions

View File

@@ -135,10 +135,26 @@ sframe_fre_set_cfa_base_reg (struct sframe_row_entry *fre,
fre->merge_candidate = false;
}
static offsetT
sframe_fre_get_cfa_offset (const struct sframe_row_entry * fre)
{
offsetT offset = fre->cfa_offset;
/* For s390x undo adjustment of CFA offset (to enable 8-bit offsets). */
if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset);
return offset;
}
static void
sframe_fre_set_cfa_offset (struct sframe_row_entry *fre,
offsetT cfa_offset)
{
/* For s390x adjust CFA offset to enable 8-bit offsets. */
if (sframe_get_abi_arch () == SFRAME_ABI_S390X_ENDIAN_BIG)
cfa_offset = SFRAME_V2_S390X_CFA_OFFSET_ENCODE (cfa_offset);
fre->cfa_offset = cfa_offset;
fre->merge_candidate = false;
}
@@ -1043,7 +1059,7 @@ sframe_xlate_do_def_cfa_register (struct sframe_xlate_ctx *xlate_ctx,
}
sframe_fre_set_cfa_base_reg (cur_fre, cfi_insn->u.r);
if (last_fre)
sframe_fre_set_cfa_offset (cur_fre, last_fre->cfa_offset);
sframe_fre_set_cfa_offset (cur_fre, sframe_fre_get_cfa_offset (last_fre));
cur_fre->merge_candidate = false;