From: Jan Beulich Date: Fri, 14 Mar 2025 09:32:42 +0000 (+0100) Subject: gas: permit wider-than-byte operands for .cfi_escape X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ebe00173e32ce714bbc8e0fb877dc6eb5033ad6f;p=thirdparty%2Fbinutils-gdb.git 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 --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 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