aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elf64-s390.c4
-rw-r--r--gas/gen-sframe.c18
-rw-r--r--include/sframe.h8
-rw-r--r--libsframe/doc/sframe-spec.texi16
-rw-r--r--libsframe/sframe.c10
-rw-r--r--libsframe/testsuite/libsframe.find/plt-findfre-2.c8
6 files changed, 54 insertions, 10 deletions
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index 491070d..d801848 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -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. */
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c
index 547e693..806ef5f 100644
--- a/gas/gen-sframe.c
+++ b/gas/gen-sframe.c
@@ -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;
diff --git a/include/sframe.h b/include/sframe.h
index 28b625b..640d002 100644
--- a/include/sframe.h
+++ b/include/sframe.h
@@ -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)
diff --git a/libsframe/doc/sframe-spec.texi b/libsframe/doc/sframe-spec.texi
index 6ba6c13..af92022 100644
--- a/libsframe/doc/sframe-spec.texi
+++ b/libsframe/doc/sframe-spec.texi
@@ -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.
diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index d8d370d..d482d58 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -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.
diff --git a/libsframe/testsuite/libsframe.find/plt-findfre-2.c b/libsframe/testsuite/libsframe.find/plt-findfre-2.c
index 3ccc259..195a05b 100644
--- a/libsframe/testsuite/libsframe.find/plt-findfre-2.c
+++ b/libsframe/testsuite/libsframe.find/plt-findfre-2.c
@@ -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);