diff options
author | Jan Beulich <jbeulich@suse.com> | 2025-03-14 10:29:33 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2025-03-14 10:29:33 +0100 |
commit | 61a5adc314c7f0c14913c2300ce4cb7b3760d2a6 (patch) | |
tree | c40ce359ee22dc699e905574511dcf1192da02b1 | |
parent | a64e445f7a83e8b809c97610354b71125da8513e (diff) | |
download | binutils-61a5adc314c7f0c14913c2300ce4cb7b3760d2a6.zip binutils-61a5adc314c7f0c14913c2300ce4cb7b3760d2a6.tar.gz binutils-61a5adc314c7f0c14913c2300ce4cb7b3760d2a6.tar.bz2 |
gas: deal with the need for relocations from .cfi_{escape,fde_data}
Ignoring return values often isn't a good idea. The Sparc assembler in
particular would report an internal error if an expression with
relocation specifier is used with .cfi_escape, when the same works fine
with .byte. Propagate the relocation indicator up from
do_parse_cons_expression(), and eventually into emit_expr_with_reloc().
dot_cfi_fde_data(), only retaining the expression's X_add_number, would
require further work. Simply report the lack of support there. While
there, also check that what we were dealt is actually a constant.
-rw-r--r-- | gas/dw2gencfi.c | 9 | ||||
-rw-r--r-- | gas/dw2gencfi.h | 1 | ||||
-rw-r--r-- | gas/gen-sframe.c | 13 | ||||
-rw-r--r-- | gas/read.c | 5 | ||||
-rw-r--r-- | gas/read.h | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/cfi/cfi-sparc-2.d | 12 | ||||
-rw-r--r-- | gas/testsuite/gas/cfi/cfi-sparc-2.s | 16 | ||||
-rw-r--r-- | gas/testsuite/gas/cfi/cfi.exp | 1 |
8 files changed, 49 insertions, 10 deletions
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c index 41e15cd..4f5622d 100644 --- a/gas/dw2gencfi.c +++ b/gas/dw2gencfi.c @@ -947,7 +947,7 @@ dot_cfi_escape (int ignored ATTRIBUTE_UNUSED) do { e = notes_alloc (sizeof (*e)); - do_parse_cons_expression (&e->exp, 1); + e->reloc = do_parse_cons_expression (&e->exp, 1); *tail = e; tail = &e->next; } @@ -1419,7 +1419,10 @@ dot_cfi_fde_data (int ignored ATTRIBUTE_UNUSED) do { e = XNEW (struct cfi_escape_data); - do_parse_cons_expression (&e->exp, 1); + e->reloc = do_parse_cons_expression (&e->exp, 1); + if (e->reloc != TC_PARSE_CONS_RETURN_NONE + || e->exp.X_op != O_constant) + as_bad (_("only constants may be used with .cfi_fde_data")); *tail = e; tail = &e->next; num_ops++; @@ -1761,7 +1764,7 @@ output_cfi_insn (struct cfi_insn_data *insn) { struct cfi_escape_data *e; for (e = insn->u.esc; e ; e = e->next) - emit_expr (&e->exp, 1); + emit_expr_with_reloc (&e->exp, 1, e->reloc); break; } diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h index 9b0e597..a9bd7b8 100644 --- a/gas/dw2gencfi.h +++ b/gas/dw2gencfi.h @@ -97,6 +97,7 @@ struct cfi_escape_data { struct cfi_escape_data *next; expressionS exp; + TC_PARSE_CONS_RETURN_TYPE reloc; }; struct cfi_insn_data diff --git a/gas/gen-sframe.c b/gas/gen-sframe.c index dd5fb25..15133cb 100644 --- a/gas/gen-sframe.c +++ b/gas/gen-sframe.c @@ -1342,7 +1342,10 @@ sframe_xlate_do_escape_expr (const struct sframe_xlate_ctx *xlate_ctx, if ((i == 2 && (items[1] != 2)) /* Expected len of 2 in DWARF expr. */ /* We do not care for the exact values of items[2] and items[3], so an explicit check for O_constant isnt necessary either. */ - || i >= CFI_ESC_NUM_EXP || (i < 2 && e->exp.X_op != O_constant)) + || i >= CFI_ESC_NUM_EXP + || (i < 2 + && (e->exp.X_op != O_constant + || e->reloc != TC_PARSE_CONS_RETURN_NONE))) goto warn_and_exit; items[i] = e->exp.X_add_number; i++; @@ -1405,7 +1408,8 @@ sframe_xlate_do_escape_val_offset (const struct sframe_xlate_ctx *xlate_ctx, while (e->next) { e = e->next; - if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant) + if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant + || e->reloc != TC_PARSE_CONS_RETURN_NONE) goto warn_and_exit; items[i] = e->exp.X_add_number; i++; @@ -1479,7 +1483,7 @@ sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx, if (!e) return SFRAME_XLATE_ERR_INVAL; - if (e->exp.X_op != O_constant) + if (e->exp.X_op != O_constant || e->reloc != TC_PARSE_CONS_RETURN_NONE) return SFRAME_XLATE_ERR_NOTREPRESENTED; firstop = e->exp.X_add_number; @@ -1490,7 +1494,8 @@ sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx, while (e->next) { e = e->next; - if (e->exp.X_op != O_constant || e->exp.X_add_number != DW_CFA_nop) + if (e->exp.X_op != O_constant || e->exp.X_add_number != DW_CFA_nop + || e->reloc != TC_PARSE_CONS_RETURN_NONE) { warn_p = true; break; @@ -4182,14 +4182,15 @@ parse_mri_cons (expressionS *exp, unsigned int nbytes); /* This function is used by .cfi_* directive handling, and hence must not invoke parse_repeat_cons(). */ -void +TC_PARSE_CONS_RETURN_TYPE do_parse_cons_expression (expressionS *exp, int nbytes ATTRIBUTE_UNUSED) { #ifdef TC_PARSE_CONS_EXPRESSION - (void) TC_PARSE_CONS_EXPRESSION (exp, nbytes); + return TC_PARSE_CONS_EXPRESSION (exp, nbytes); #else expression (exp); + return TC_PARSE_CONS_RETURN_NONE; #endif } @@ -159,7 +159,7 @@ extern void stabs_begin (void); extern void stabs_end (void); extern void do_repeat (size_t, const char *, const char *, const char *); extern void end_repeat (int); -extern void do_parse_cons_expression (expressionS *, int); +extern TC_PARSE_CONS_RETURN_TYPE do_parse_cons_expression (expressionS *, int); extern void generate_lineno_debug (void); extern void do_align (unsigned int align, char *fill, unsigned int length, unsigned int max); diff --git a/gas/testsuite/gas/cfi/cfi-sparc-2.d b/gas/testsuite/gas/cfi/cfi-sparc-2.d new file mode 100644 index 0000000..3a425d7 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-sparc-2.d @@ -0,0 +1,12 @@ +#readelf: -r +#name: .cfi_escape on SPARC w/ reloc specifier +#as: -32 + +Relocation section '.rela.data' at offset 0x[0-9a-f]+ contains 1 entry: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +[0-9a-f]+ +[0-9a-f]+ R_SPARC_DISP8 +[0-9a-f]+ +\.data \+ 1 + +Relocation section '.rela.eh_frame' at offset 0x[0-9a-f]+ contains 2 entries: + Offset Info Type Sym\.Value Sym\. Name \+ Addend +[0-9a-f]+ +[0-9a-f]+ R_SPARC_DISP32 +[0-9a-f]+ +\.text \+ 0 +[0-9a-f]+ +[0-9a-f]+ R_SPARC_DISP8 +[0-9a-f]+ +\.eh_frame \+ [0-9a-f]+ diff --git a/gas/testsuite/gas/cfi/cfi-sparc-2.s b/gas/testsuite/gas/cfi/cfi-sparc-2.s new file mode 100644 index 0000000..9df6da2 --- /dev/null +++ b/gas/testsuite/gas/cfi/cfi-sparc-2.s @@ -0,0 +1,16 @@ + .data + .byte %r_disp8(1f-1) + .byte 0x50 +1: + + .text +func: + .cfi_startproc + nop + .cfi_escape 0x10 ! DW_CFA_expression + .cfi_escape 0 ! reg0 + .cfi_escape %r_disp8(.Lend-1) + .cfi_escape 0x50 ! DW_OP_reg0 + .cfi_label .Lend + ret + .cfi_endproc diff --git a/gas/testsuite/gas/cfi/cfi.exp b/gas/testsuite/gas/cfi/cfi.exp index 8d730a2..d8bbf0d 100644 --- a/gas/testsuite/gas/cfi/cfi.exp +++ b/gas/testsuite/gas/cfi/cfi.exp @@ -105,6 +105,7 @@ if { [istarget "i*86-*-*"] || [istarget "x86_64-*-*"] } then { set nm_status [gas_host_run "$NM $NMFLAGS --help" ""] run_dump_test "cfi-sparc-1" + run_dump_test "cfi-sparc-2" if { [regexp "elf64\[_-\]sparc" [lindex $nm_status 1]] } then { run_dump_test "cfi-sparc64-1" } |