diff options
-rw-r--r-- | gas/gen-sframe.c | 50 | ||||
-rw-r--r-- | include/sframe.h | 9 | ||||
-rw-r--r-- | libsframe/sframe-dump.c | 4 |
3 files changed, 34 insertions, 29 deletions
diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c index 0bb7afb..0d7dcc7 100644 --- a/gas/gen-sframe.c +++ b/gas/gen-sframe.c @@ -347,7 +347,9 @@ get_fre_num_offsets (struct sframe_row_entry *sframe_fre) fre_num_offsets++; #ifdef SFRAME_FRE_RA_TRACKING if (sframe_ra_tracking_p () - && sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) + && (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK + /* Accommodate for padding RA offset if FP without RA on stack. */ + || sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK)) fre_num_offsets++; #endif return fre_num_offsets; @@ -371,9 +373,14 @@ sframe_get_fre_offset_size (struct sframe_row_entry *sframe_fre) if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) bp_offset_size = get_offset_size_in_bytes (sframe_fre->bp_offset); #ifdef SFRAME_FRE_RA_TRACKING - if (sframe_ra_tracking_p () - && sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) - ra_offset_size = get_offset_size_in_bytes (sframe_fre->ra_offset); + if (sframe_ra_tracking_p ()) + { + if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) + ra_offset_size = get_offset_size_in_bytes (sframe_fre->ra_offset); + /* Accommodate for padding RA offset if FP without RA on stack. */ + else if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) + ra_offset_size = get_offset_size_in_bytes (SFRAME_FRE_RA_OFFSET_INVALID); + } #endif /* Get the maximum size needed to represent the offsets. */ @@ -537,11 +544,19 @@ output_sframe_row_entry (symbolS *fde_start_addr, fre_write_offsets++; #ifdef SFRAME_FRE_RA_TRACKING - if (sframe_ra_tracking_p () - && sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) + if (sframe_ra_tracking_p ()) { - fre_offset_func_map[idx].out_func (sframe_fre->ra_offset); - fre_write_offsets++; + if (sframe_fre->ra_loc == SFRAME_FRE_ELEM_LOC_STACK) + { + fre_offset_func_map[idx].out_func (sframe_fre->ra_offset); + fre_write_offsets++; + } + /* Write padding RA offset if FP without RA on stack. */ + else if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) + { + fre_offset_func_map[idx].out_func (SFRAME_FRE_RA_OFFSET_INVALID); + fre_write_offsets++; + } } #endif if (sframe_fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) @@ -1499,25 +1514,6 @@ sframe_do_fde (struct sframe_xlate_ctx *xlate_ctx, = get_dw_fde_end_addrS (xlate_ctx->dw_fde); } -#ifdef SFRAME_FRE_RA_TRACKING - if (sframe_ra_tracking_p ()) - { - struct sframe_row_entry *fre; - - /* Iterate over the scratchpad FREs and validate them. */ - for (fre = xlate_ctx->first_fre; fre; fre = fre->next) - { - /* SFrame format cannot represent FP on stack without RA on stack. */ - if (fre->ra_loc != SFRAME_FRE_ELEM_LOC_STACK - && fre->bp_loc == SFRAME_FRE_ELEM_LOC_STACK) - { - as_warn (_("skipping SFrame FDE due to FP without RA on stack")); - return SFRAME_XLATE_ERR_NOTREPRESENTED; - } - } - } -#endif /* SFRAME_FRE_RA_TRACKING */ - return SFRAME_XLATE_OK; } diff --git a/include/sframe.h b/include/sframe.h index 90bc92a..d1a2687 100644 --- a/include/sframe.h +++ b/include/sframe.h @@ -237,6 +237,9 @@ typedef struct sframe_func_desc_entry may or may not be tracked. */ #define SFRAME_FRE_FP_OFFSET_IDX 2 +/* Invalid RA offset. Used as padding to represent FP without RA on stack. */ +#define SFRAME_FRE_RA_OFFSET_INVALID 0 + typedef struct sframe_fre_info { /* Information about @@ -288,9 +291,11 @@ typedef struct sframe_fre_info offset1 (interpreted as CFA = BASE_REG + offset1) if RA is being tracked - offset2 (interpreted as RA = CFA + offset2) + offset2 (interpreted as RA = CFA + offset2; an offset value of + SFRAME_FRE_RA_OFFSET_INVALID indicates a dummy padding RA offset + to represent FP without RA saved on stack) if FP is being tracked - offset3 (intrepreted as FP = CFA + offset2) + offset3 (intrepreted as FP = CFA + offset3) fi else if FP is being tracked diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c index 40ea531..3ea4bc3 100644 --- a/libsframe/sframe-dump.c +++ b/libsframe/sframe-dump.c @@ -199,6 +199,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. AArch64 and S390, it can be a + dummy as 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_s390 (sfd_ctx) && (ra_offset & 1)) |