mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 04:24:43 +00:00
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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
12
gas/testsuite/gas/cfi/cfi-sparc-2.d
Normal file
12
gas/testsuite/gas/cfi/cfi-sparc-2.d
Normal file
@@ -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]+
|
||||
16
gas/testsuite/gas/cfi/cfi-sparc-2.s
Normal file
16
gas/testsuite/gas/cfi/cfi-sparc-2.s
Normal file
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user