[2/8] gas: deal with the need for relocations from .cfi_{escape,fde_data}

Message ID 72076c11-cfcd-4b13-b601-eaa8f868b8cd@suse.com
State New
Headers
Series gas: CFI directive and listing adjustments |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

Jan Beulich Feb. 26, 2025, 3:15 p.m. UTC
  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.
  

Patch

--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -372,6 +372,7 @@  struct cfi_escape_data
 {
   struct cfi_escape_data *next;
   expressionS exp;
+  TC_PARSE_CONS_RETURN_TYPE reloc;
 };
 
 struct cie_entry
@@ -953,7 +954,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;
     }
@@ -1425,7 +1426,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++;
@@ -1767,7 +1771,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;
       }
 
--- a/gas/read.c
+++ b/gas/read.c
@@ -4187,14 +4187,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
 }
 
--- a/gas/read.h
+++ b/gas/read.h
@@ -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);
--- a/gas/testsuite/gas/cfi/cfi.exp
+++ b/gas/testsuite/gas/cfi/cfi.exp
@@ -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"
     }
--- /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]+
--- /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