]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: permit wider-than-byte operands for .cfi_escape
authorJan Beulich <jbeulich@suse.com>
Fri, 14 Mar 2025 09:32:42 +0000 (10:32 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 14 Mar 2025 09:32:42 +0000 (10:32 +0100)
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.

gas/doc/as.texi
gas/dw2gencfi.c
gas/dw2gencfi.h
gas/testsuite/gas/cfi/listing.l
gas/testsuite/gas/cfi/listing.s

index edb498ac2f34d6c6c2dd5ac535c0937e2795ac18..d68a9bc7c73361d2bc48484b1b5ae092511fb49b 100644 (file)
@@ -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,
 
index 45d2830f3db8fbd62cb7aab560c36c82d14ab655..a21ae322488f067a566ef61ace333c90262501a1 100644 (file)
@@ -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;
       }
index c741f8f33efd5ef45531ff6ccf90114b28ae4764..fb1342ac4a47ef1de71ff2ef7ce8f2b4ed264c8c 100644 (file)
@@ -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;
index b30f1143020992fcf7037decd2c4e8b375717299..3290fb664a240d5c3068b604b20dc5003223677f 100644 (file)
@@ -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
index 449ac8970efa7ba85607247a261ddabf42946eb8..6794f8a5db1cfe0a98eae283cc3c144cd78ce7e6 100644 (file)
@@ -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