[binutils-gdb] gas: permit wider-than-byte operands for .cfi_escape

Jan Beulich jbeulich@sourceware.org
Fri Mar 14 09:34:17 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ebe00173e32ce714bbc8e0fb877dc6eb5033ad6f

commit ebe00173e32ce714bbc8e0fb877dc6eb5033ad6f
Author: Jan Beulich <jbeulich@suse.com>
Date:   Fri Mar 14 10:32:42 2025 +0100

    gas: permit wider-than-byte operands for .cfi_escape
    
    Some DW_CFA_* and DW_OP_* take wider than byte, but non-LEB128 operands.
    Having to hand-encode such when needing to resort to .cfi_escape isn't
    very helpful.

Diff:
---
 gas/doc/as.texi                 | 12 ++++++++++++
 gas/dw2gencfi.c                 | 31 +++++++++++++++++++++++++++++--
 gas/dw2gencfi.h                 |  9 ++++++++-
 gas/testsuite/gas/cfi/listing.l |  4 ++--
 gas/testsuite/gas/cfi/listing.s |  4 ++--
 5 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index edb498ac2f3..d68a9bc7c73 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -5181,6 +5181,18 @@ also use extended kind-of-expression forms:
 
 @itemize @bullet
 
+@item @code{data2(@var{expression})}
+to emit a 2-byte item,
+
+@item @code{data4(@var{expression})}
+to emit a 4-byte item (provided address size is at least 32 bits),
+
+@item @code{data8(@var{expression})}
+to emit an 8-byte item (provided address size is at least 64 bits),
+
+@item @code{addr(@var{expression})}
+to emit an address-sized item,
+
 @item @code{sleb128(@var{expression})}
 to emit a SLEB128 item,
 
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index 45d2830f3db..a21ae322488 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -938,6 +938,21 @@ dot_cfi (int arg)
   demand_empty_rest_of_line ();
 }
 
+#ifndef TC_ADDRESS_BYTES
+#define TC_ADDRESS_BYTES address_bytes
+
+static inline unsigned int
+address_bytes (void)
+{
+  /* Choose smallest of 1, 2, 4, 8 bytes that is large enough to
+     contain an address.  */
+  unsigned int n = (stdoutput->arch_info->bits_per_address - 1) / 8;
+  n |= n >> 1;
+  n |= n >> 2;
+  return n + 1;
+}
+#endif
+
 static void
 dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
 {
@@ -968,6 +983,14 @@ dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
 	e->type = CFI_ESC_sleb128;
       else if (strcmp (id, "uleb128") == 0)
 	e->type = CFI_ESC_uleb128;
+      else if (strcmp (id, "data2") == 0)
+	e->type = 2;
+      else if (TC_ADDRESS_BYTES () >= 4 && strcmp (id, "data4") == 0)
+	e->type = 4;
+      else if (TC_ADDRESS_BYTES () >= 8 && strcmp (id, "data8") == 0)
+	e->type = 8;
+      else if (strcmp (id, "addr") == 0)
+	e->type = TC_ADDRESS_BYTES ();
       else
 	e->type = CFI_ESC_byte;
 
@@ -991,7 +1014,11 @@ dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
 	  expression (&e->exp);
 	}
       else
-	e->reloc = do_parse_cons_expression (&e->exp, 1);
+	{
+	  /* We may still be at the opening parenthesis.  Leave it to expression()
+	     to parse it and find the matching closing one.  */
+	  e->reloc = do_parse_cons_expression (&e->exp, e->type);
+	}
 
       *tail = e;
       tail = &e->next;
@@ -1813,7 +1840,7 @@ output_cfi_insn (struct cfi_insn_data *insn)
 	    if (e->type == CFI_ESC_sleb128 || e->type == CFI_ESC_uleb128)
 	      emit_leb128_expr (&e->exp, e->type == CFI_ESC_sleb128);
 	    else
-	      emit_expr_with_reloc (&e->exp, 1, e->reloc);
+	      emit_expr_with_reloc (&e->exp, e->type, e->reloc);
 	  }
 	break;
       }
diff --git a/gas/dw2gencfi.h b/gas/dw2gencfi.h
index c741f8f33ef..fb1342ac4a4 100644
--- a/gas/dw2gencfi.h
+++ b/gas/dw2gencfi.h
@@ -98,7 +98,14 @@ struct cfi_escape_data
   struct cfi_escape_data *next;
   expressionS exp;
   enum {
-    CFI_ESC_byte,
+    /* "Plain" data is indicated just by their size, such that values can be
+       easily passed to other functions.  The CFI_ESC_data<N> enumerators exist
+       here only as placeholders.  */
+    CFI_ESC_byte = 1,
+    CFI_ESC_data2 = 2,
+    CFI_ESC_data4 = 4,
+    CFI_ESC_data8 = 8,
+    /* LEB128 data needs dedicated enumerators.  */
     CFI_ESC_sleb128,
     CFI_ESC_uleb128,
   } type;
diff --git a/gas/testsuite/gas/cfi/listing.l b/gas/testsuite/gas/cfi/listing.l
index b30f1143020..3290fb664a2 100644
--- a/gas/testsuite/gas/cfi/listing.l
+++ b/gas/testsuite/gas/cfi/listing.l
@@ -9,8 +9,8 @@
 [ 	]*[0-9]*[ 	]+[0-9a-f]{4} 4.02 ?0002[ 	]+\.cfi_escape 0x02, 0x00, 0x02, 0x00
 [ 	]*[0-9]*[ 	]+00
 [ 	]*[0-9]*[ 	]+[0-9a-f]{4} .*[ 	]\.nop
-[ 	]*[0-9]*[ 	]+[0-9a-f]{4} 4.03 ?0000[ 	]+\.cfi_escape 0x03; .cfi_escape 0x00, 0x00
-[ 	]*[0-9]*[ 	]+[0-9a-f]{4} 0400 ?0000[ 	]+\.cfi_escape 0x04; .cfi_escape 0x00, 0x00, 0x00, 0x00
+[ 	]*[0-9]*[ 	]+[0-9a-f]{4} 4.03 ?0000[ 	]+\.cfi_escape 0x03; .cfi_escape data2\(0\)
+[ 	]*[0-9]*[ 	]+[0-9a-f]{4} 0400 ?0000[ 	]+\.cfi_escape 0x04; .cfi_escape data4\(0\)
 [ 	]*[0-9]*[ 	]+00
 [ 	]*[0-9]*[ 	]+[0-9a-f]{4} .*[ 	]\.nop
 [ 	]*[0-9]*[ 	]+[0-9a-f]{4} 4.0B[ 	]+\.cfi_escape 0x0b
diff --git a/gas/testsuite/gas/cfi/listing.s b/gas/testsuite/gas/cfi/listing.s
index 449ac8970ef..6794f8a5db1 100644
--- a/gas/testsuite/gas/cfi/listing.s
+++ b/gas/testsuite/gas/cfi/listing.s
@@ -7,8 +7,8 @@ func:
 	.nop
 	.cfi_escape 0x02, 0x00, 0x02, 0x00
 	.nop
-	.cfi_escape 0x03; .cfi_escape 0x00, 0x00
-	.cfi_escape 0x04; .cfi_escape 0x00, 0x00, 0x00, 0x00
+	.cfi_escape 0x03; .cfi_escape data2(0)
+	.cfi_escape 0x04; .cfi_escape data4(0)
 	.nop
 	.cfi_escape 0x0b
 	.nop


More information about the Binutils-cvs mailing list