[v2,1/5] gas: deal with the need for relocations from .cfi_{escape,fde_data}
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Test passed
|
Commit Message
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.
---
Really value truncation better would also be reported for .cfi_fde_data.
Question is whether dot_cfi_fde_data() wouldn't better share parsing
code with dot_cfi_escape(), for data to then be emitted for both via
emit_expr_with_reloc(). Problem is I know nothing about EH_COMPACT_*,
and hence I'd be at risk of breaking stuff if I blindly did such a
conversion.
---
v2: Re-base.
@@ -947,7 +947,7 @@ dot_cfi_escape (int ignored ATTRIBUTE_UN
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_
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 *i
{
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
@@ -1345,7 +1345,10 @@ sframe_xlate_do_escape_expr (const struc
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++;
@@ -1408,7 +1411,8 @@ sframe_xlate_do_escape_val_offset (const
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++;
@@ -1482,7 +1486,7 @@ sframe_xlate_do_cfi_escape (const struct
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;
@@ -1493,7 +1497,8 @@ sframe_xlate_do_cfi_escape (const struct
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;
@@ -4186,14 +4186,15 @@ parse_mri_cons (expressionS *exp, unsign
/* 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);
@@ -105,6 +105,7 @@ if { [istarget "i*86-*-*"] || [istarget
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"
}
@@ -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]+
@@ -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