mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 15:15:42 +00:00
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:
@@ -621,8 +621,8 @@ struct elf_s390x_sframe_plt
|
||||
static const sframe_frame_row_entry elf_s390x_sframe_plt_fre =
|
||||
{
|
||||
0, /* SFrame FRE start address. */
|
||||
{0, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
|
||||
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_2B) /* FRE info. */
|
||||
{ SFRAME_V2_S390X_CFA_OFFSET_ENCODE (160), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* Offset bytes. */
|
||||
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
|
||||
};
|
||||
|
||||
/* SFrame helper object for PLT. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -376,6 +376,14 @@ typedef struct sframe_frame_row_entry_addr4
|
||||
#define SFRAME_FRE_TYPE_ADDR4_LIMIT \
|
||||
(1ULL << ((SFRAME_FRE_TYPE_ADDR4 * 2) * 8))
|
||||
|
||||
/* On s390x, the CFA offset from CFA base register is by definition a minimum
|
||||
of 160. Store it adjusted by -160 to enable use of 8-bit SFrame offsets. */
|
||||
#define SFRAME_S390X_CFA_OFFSET_ADJUSTMENT SFRAME_S390X_SP_VAL_OFFSET
|
||||
#define SFRAME_V2_S390X_CFA_OFFSET_ENCODE(offset) \
|
||||
((offset) + SFRAME_S390X_CFA_OFFSET_ADJUSTMENT)
|
||||
#define SFRAME_V2_S390X_CFA_OFFSET_DECODE(offset) \
|
||||
((offset) - SFRAME_S390X_CFA_OFFSET_ADJUSTMENT)
|
||||
|
||||
/* On s390x, the CFA is defined as SP at call site + 160. Therefore the
|
||||
SP value offset from CFA is -160. */
|
||||
#define SFRAME_S390X_SP_VAL_OFFSET (-160)
|
||||
|
||||
@@ -155,6 +155,12 @@ 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.
|
||||
@item SFRAME_S390X_CFA_OFFSET_ADJUSTMENT: CFA offset (from CFA base register)
|
||||
adjustment value. Used to enable use of 8-bit SFrame offsets on s390x.
|
||||
@item SFRAME_V2_S390X_CFA_OFFSET_ENCODE: Encode CFA offset (i.e., apply
|
||||
CFA offset adjustment).
|
||||
@item SFRAME_V2_S390X_CFA_OFFSET_DECODE: Decode CFA offset (i.e., revert
|
||||
CFA offset adjustment).
|
||||
@end itemize
|
||||
@end itemize
|
||||
|
||||
@@ -885,7 +891,15 @@ case in the topmost stack frame of the callchain. For FP this may be the case
|
||||
in any stack frame.
|
||||
|
||||
Irrespective of the ABI, the first stack offset is always used to locate the
|
||||
CFA, by interpreting it as: CFA = @code{BASE_REG} + offset1.
|
||||
CFA. On s390x the value of the offset is stored adjusted by the s390x-specific
|
||||
@code{SFRAME_S390X_CFA_OFFSET_ADJUSTMENT} to enable the use of signed 8-bit
|
||||
offsets on s390x.
|
||||
s390x-specific helpers @code{SFRAME_V2_S390X_CFA_OFFSET_ENCODE} and
|
||||
@code{SFRAME_V2_S390X_CFA_OFFSET_DECODE} are provided to perform and undo
|
||||
the adjustment. The CFA offset can therefore be interpreted as:
|
||||
CFA = @code{BASE_REG} + @code{SFRAME_V2_S390X_CFA_OFFSET_DECODE(offset1)}
|
||||
or
|
||||
CFA = @code{BASE_REG} + offset1 - @code{SFRAME_S390X_CFA_OFFSET_ADJUSTMENT}.
|
||||
The identification of the @code{BASE_REG} is done by using the
|
||||
@code{fre_cfa_base_reg_id} field in the SFrame FRE info word.
|
||||
|
||||
|
||||
@@ -695,10 +695,16 @@ sframe_fre_get_base_reg_id (sframe_frame_row_entry *fre, int *errp)
|
||||
/* Get the CFA offset from the FRE. If the offset is invalid, sets errp. */
|
||||
|
||||
int32_t
|
||||
sframe_fre_get_cfa_offset (sframe_decoder_ctx *dctx ATTRIBUTE_UNUSED,
|
||||
sframe_fre_get_cfa_offset (sframe_decoder_ctx *dctx,
|
||||
sframe_frame_row_entry *fre, int *errp)
|
||||
{
|
||||
return sframe_get_fre_offset (fre, SFRAME_FRE_CFA_OFFSET_IDX, errp);
|
||||
int32_t offset = sframe_get_fre_offset (fre, SFRAME_FRE_CFA_OFFSET_IDX, errp);
|
||||
|
||||
/* For s390x undo adjustment of CFA offset (to enable 8-bit offsets). */
|
||||
if (sframe_decoder_get_abi_arch (dctx) == SFRAME_ABI_S390X_ENDIAN_BIG)
|
||||
offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Get the FP offset from the FRE. If the offset is invalid, sets errp.
|
||||
|
||||
@@ -43,8 +43,8 @@ add_plt0_fde (sframe_encoder_ctx *ectx, uint32_t plt_vaddr,
|
||||
/* 1 single FRE. */
|
||||
sframe_frame_row_entry fre
|
||||
= { 0x0,
|
||||
{ 0, 160 + PLT0_CFA_OFFSET_MAGIC },
|
||||
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_2B) };
|
||||
{ SFRAME_V2_S390X_CFA_OFFSET_ENCODE (160 + PLT0_CFA_OFFSET_MAGIC) },
|
||||
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) };
|
||||
|
||||
unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1,
|
||||
SFRAME_FDE_TYPE_PCINC);
|
||||
@@ -72,8 +72,8 @@ add_pltn_fde (sframe_encoder_ctx *ectx, uint32_t plt_vaddr,
|
||||
/* 1 single FRE. */
|
||||
sframe_frame_row_entry fre
|
||||
= { 0x0,
|
||||
{ 0, 160 + PLTN_CFA_OFFSET_MAGIC },
|
||||
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_2B) };
|
||||
{ SFRAME_V2_S390X_CFA_OFFSET_ENCODE (160 + PLTN_CFA_OFFSET_MAGIC) },
|
||||
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) };
|
||||
|
||||
unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1,
|
||||
SFRAME_FDE_TYPE_PCMASK);
|
||||
|
||||
Reference in New Issue
Block a user