]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: permit LEB128 operands for .cfi_escape
authorJan Beulich <jbeulich@suse.com>
Fri, 14 Mar 2025 09:32:20 +0000 (10:32 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 14 Mar 2025 09:32:20 +0000 (10:32 +0100)
Many DW_CFA_* and DW_OP_* take 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/gen-sframe.c
gas/testsuite/gas/cfi/listing.l
gas/testsuite/gas/cfi/listing.s

index afe1737f4cee41481d2b942a19af9143cf6160b7..edb498ac2f34d6c6c2dd5ac535c0937e2795ac18 100644 (file)
@@ -5176,7 +5176,18 @@ SPARC register window has been saved.
 @subsection @code{.cfi_escape} @var{expression}[, @dots{}]
 Allows the user to add arbitrary bytes to the unwind info.  One
 might use this to add OS-specific CFI opcodes, or generic CFI
-opcodes that GAS does not yet support.
+opcodes that GAS does not yet support.  To emit multi-byte data one may
+also use extended kind-of-expression forms:
+
+@itemize @bullet
+
+@item @code{sleb128(@var{expression})}
+to emit a SLEB128 item,
+
+@item @code{uleb128(@var{expression})}
+to emit a ULEB128 item.
+
+@end itemize
 
 @subsection @code{.cfi_val_encoded_addr @var{register}, @var{encoding}, @var{label}}
 The current value of @var{register} is @var{label}.  The value of @var{label}
index 310cb56a34e4d70ff59a3fa17f79aa2b17f9b388..45d2830f3db8fbd62cb7aab560c36c82d14ab655 100644 (file)
@@ -941,7 +941,7 @@ dot_cfi (int arg)
 static void
 dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
 {
-  struct cfi_escape_data *head, **tail, *e;
+  struct cfi_escape_data *head, **tail;
   struct cfi_insn_data *insn;
 
   if (frchain_now->frch_cfi_data == NULL)
@@ -960,8 +960,39 @@ dot_cfi_escape (int ignored ATTRIBUTE_UNUSED)
   tail = &head;
   do
     {
-      e = notes_alloc (sizeof (*e));
-      e->reloc = do_parse_cons_expression (&e->exp, 1);
+      struct cfi_escape_data *e = notes_alloc (sizeof (*e));
+      char *id, *ilp_save = input_line_pointer;
+      char c = get_symbol_name (&id);
+
+      if (strcmp (id, "sleb128") == 0)
+       e->type = CFI_ESC_sleb128;
+      else if (strcmp (id, "uleb128") == 0)
+       e->type = CFI_ESC_uleb128;
+      else
+       e->type = CFI_ESC_byte;
+
+      c = restore_line_pointer (c);
+
+      if (e->type != CFI_ESC_byte)
+       {
+         if (is_whitespace (c))
+           c = *++input_line_pointer;
+         if (c != '(')
+           {
+             input_line_pointer = ilp_save;
+             e->type = CFI_ESC_byte;
+           }
+       }
+
+      if (e->type == CFI_ESC_sleb128 || e->type == CFI_ESC_uleb128)
+       {
+         /* We're still at the opening parenthesis.  Leave it to expression()
+            to parse it and find the matching closing one.  */
+         expression (&e->exp);
+       }
+      else
+       e->reloc = do_parse_cons_expression (&e->exp, 1);
+
       *tail = e;
       tail = &e->next;
     }
@@ -1778,7 +1809,12 @@ output_cfi_insn (struct cfi_insn_data *insn)
       {
        struct cfi_escape_data *e;
        for (e = insn->u.esc; e ; e = e->next)
-         emit_expr_with_reloc (&e->exp, 1, e->reloc);
+         {
+           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);
+         }
        break;
       }
 
index e9eec43457325b498186a9b6071c2ecfe681d6fb..c741f8f33efd5ef45531ff6ccf90114b28ae4764 100644 (file)
@@ -97,6 +97,11 @@ struct cfi_escape_data
 {
   struct cfi_escape_data *next;
   expressionS exp;
+  enum {
+    CFI_ESC_byte,
+    CFI_ESC_sleb128,
+    CFI_ESC_uleb128,
+  } type;
   TC_PARSE_CONS_RETURN_TYPE reloc;
 };
 
index 15133cb698e57026e360236f33cba470bc0e5359..5b5e7b14b3ab1af8161856a833958dae24eed525 100644 (file)
@@ -1345,6 +1345,7 @@ sframe_xlate_do_escape_expr (const struct sframe_xlate_ctx *xlate_ctx,
          || i >= CFI_ESC_NUM_EXP
          || (i < 2
              && (e->exp.X_op != O_constant
+                 || e->type != CFI_ESC_byte
                  || e->reloc != TC_PARSE_CONS_RETURN_NONE)))
        goto warn_and_exit;
       items[i] = e->exp.X_add_number;
@@ -1409,6 +1410,7 @@ sframe_xlate_do_escape_val_offset (const struct sframe_xlate_ctx *xlate_ctx,
     {
       e = e->next;
       if (i >= CFI_ESC_NUM_EXP || e->exp.X_op != O_constant
+         || e->type != CFI_ESC_byte
          || e->reloc != TC_PARSE_CONS_RETURN_NONE)
        goto warn_and_exit;
       items[i] = e->exp.X_add_number;
@@ -1483,7 +1485,9 @@ 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 || e->reloc != TC_PARSE_CONS_RETURN_NONE)
+  if (e->exp.X_op != O_constant
+      || e->type != CFI_ESC_byte
+      || e->reloc != TC_PARSE_CONS_RETURN_NONE)
     return SFRAME_XLATE_ERR_NOTREPRESENTED;
 
   firstop = e->exp.X_add_number;
@@ -1495,6 +1499,7 @@ sframe_xlate_do_cfi_escape (const struct sframe_xlate_ctx *xlate_ctx,
        {
          e = e->next;
          if (e->exp.X_op != O_constant || e->exp.X_add_number != DW_CFA_nop
+             || e->type != CFI_ESC_byte
              || e->reloc != TC_PARSE_CONS_RETURN_NONE)
            {
              warn_p = true;
index b15c6ca605c9712e8b2df1f4d3b8c0e3a0762023..b30f1143020992fcf7037decd2c4e8b375717299 100644 (file)
 [      ]*[0-9]*[       ]+([0-9a-f]{4} [0       ]+)?\.cfi_endproc
 [      ]*[0-9]*[       ]*
 [      ]*[0-9]*[       ]+func2:
-[      ]*[0-9]*[       ]+[0-9a-f]{4} (1[048]00 ?0000|0000 ?001[048])[  ]+\.cfi_startproc
+[      ]*[0-9]*[       ]+[0-9a-f]{4} ((1C|2[048])00 ?0000|0000 ?00(1C|2[048]))[        ]+\.cfi_startproc
 [      ]*[0-9]*[       ]+(4[048]00 ?0000|0000 ?004[048]) *
 [      ]*[0-9]*[       ]+[0-9a-f]{4} .*[       ]\.nop
+[      ]*[0-9]*[       ]+/\* DW_CFA_register reg127, reg129.  \*/
+[      ]*[0-9]*[       ]+[0-9a-f]{4} 4.09 ?7F81[       ]+\.cfi_escape 0x09, uleb128\(127\), uleb128\(129\)
+[      ]*[0-9]*[       ]+01
+[      ]*[0-9]*[       ]+/\* DW_CFA_val_expression reg250, ...  \*/
+[      ]*[0-9]*[       ]+[0-9a-f]{4} 16FA ?01[         ]+\.cfi_escape 0x16, uleb128\(250\)
+[      ]*[0-9]*[       ]+/\* ... <len>.  \*/
+[      ]*[0-9]*[       ]+[0-9a-f]{4} 03[       ]+\.cfi_escape uleb128\(.LE0e - .LE0s\)
+[      ]*[0-9]*[       ]+\.cfi_label .LE0s
+[      ]*[0-9]*[       ]+/\* DW_OP_breg3.  \*/
+[      ]*[0-9]*[       ]+[0-9a-f]{4} 7380 ?78[         ]+\.cfi_escape 0x73, sleb128\(-1024\)
+[      ]*[0-9]*[       ]+\.cfi_label .LE0e
+[      ]*[0-9]*[       ]+[0-9a-f]{4} .*[       ]\.nop
 [      ]*[0-9]*[       ]+([0-9a-f]{4} [0       ]+)?\.cfi_endproc
 #pass
index e091c54fa56460eea66f679c6898f7c406ad099b..449ac8970efa7ba85607247a261ddabf42946eb8 100644 (file)
@@ -19,4 +19,15 @@ func:
 func2:
        .cfi_startproc
        .nop
+       /* DW_CFA_register reg127, reg129.  */
+       .cfi_escape 0x09, uleb128(127), uleb128(129)
+       /* DW_CFA_val_expression reg250, ...  */
+       .cfi_escape 0x16, uleb128(250)
+       /* ... <len>.  */
+       .cfi_escape uleb128(.LE0e - .LE0s)
+       .cfi_label .LE0s
+       /* DW_OP_breg3.  */
+       .cfi_escape 0x73, sleb128(-1024)
+       .cfi_label .LE0e
+       .nop
        .cfi_endproc