[RFC 19/28] [SFrame-V3] sframe: gas: translate specific CFI directives for SFRAME_FDE_TYPE_FLEX_TOPMOST_FRAME
Jens Remus
jremus@linux.ibm.com
Fri Dec 19 08:17:42 GMT 2025
On 12/19/2025 9:12 AM, Jan Beulich wrote:
> On 09.12.2025 10:07, Indu Bhagat via Binutils wrote:
>> @@ -1574,6 +1614,98 @@ sframe_xlate_do_gnu_window_save (struct sframe_xlate_ctx *xlate_ctx,
>> return SFRAME_XLATE_ERR_NOTREPRESENTED; /* Not represented. */
>> }
>>
>> +/* Handle DW_CFA_def_cfa_expression in .cfi_escape.
>> +
>> + As with sframe_xlate_do_cfi_escape, the intent of this function is to detect
>> + only the simple-to-process but common cases. All other CFA escape
>> + expressions continue to be inadmissible (no SFrame FDE emitted).
>> +
>> + Sets CALLER_WARN_P for skipped cases (and returns SFRAME_XLATE_OK) where the
>> + caller must warn. The caller then must also set
>> + SFRAME_XLATE_ERR_NOTREPRESENTED for their callers. */
>> +
>> +static int
>> +sframe_xlate_do_escape_cfa_expr (struct sframe_xlate_ctx *xlate_ctx,
>> + const struct cfi_insn_data *cfi_insn,
>> + bool *caller_warn_p)
>> +{
>> + const struct cfi_escape_data *e = cfi_insn->u.esc;
>> + int err = SFRAME_XLATE_OK;
>> + unsigned int opcode1, opcode2;
>> + offsetT offset;
>> + unsigned int reg = SFRAME_FRE_REG_INVALID;
>> + unsigned int i = 0;
>> + bool x86_cfa_deref_p = false;
>> +
>> + /* Check roughly for an expression
>> + DW_CFA_def_cfa_expression (DW_OP_breg6 (rbp): -8; DW_OP_deref). */
>> +#define CFI_ESC_NUM_EXP 4
>> + offsetT items[CFI_ESC_NUM_EXP] = {0};
>> + while (e->next)
>> + {
>> + e = e->next;
>> + if ((i == 1 && (items[0] != 3)) /* Block length of 3 in DWARF expr. */
>> + /* We do not care for the exact values of items[2], items[3], and
>> + items[4], so an explicit check for O_constant isnt necessary
>> + either. */
>> + || 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;
>> + i++;
>> + }
>> +
>> + if (i <= CFI_ESC_NUM_EXP - 1)
>> + goto warn_and_exit;
>> +
>> + opcode1 = items[1];
>> + opcode2 = items[3];
>> + /* DW_OP_breg6 is rbp. FIXME - this stub can be enhanced to handle more
>> + regs. */
>> + if (sframe_get_abi_arch () == SFRAME_ABI_AMD64_ENDIAN_LITTLE
>> + && opcode1 == DW_OP_breg6 && opcode2 == DW_OP_deref)
>> + {
>> + x86_cfa_deref_p = true;
>> + reg = SFRAME_CFA_FP_REG;
>> + }
>> +
>> + /* Read the offset. */
>> + const unsigned char *buf_start = (const unsigned char *)&items[2];
>> + const unsigned char *buf_end = buf_start + sizeof (offsetT) - 1;
>> + size_t read = read_sleb128_to_int64 (buf_start, buf_end, &offset);
>> + gas_assert (read);
>> +#undef CFI_ESC_NUM_EXP
>
> Now that I finally understood where the already-encoded sleb128 is coming from
> (as per the 20/28 sub-thread), I'd like to clarify here that more checking will
> need adding: You also need to check items[0] to be DW_CFA_def_cfa_expression,
> and I think you also want to do the checking in order (i.e. check items[3] only
> after having checked items[2], to eliminate the risk of mistaking an item).
>
> And then, as already alluded to by Jens, I think you also want to permit other
> than CFI_ESC_byte in items[2] (in which case the ugly sleb128 decoding won't
> be needed). Whether in the CFI_ESC_byte case allowing only 1-byte sleb128 is
> going to be sufficient for a wide range of real-world uses I don't know.
The sleb128 decoding would still be required for items[2], if e->type in
(CFI_ESC_byte, CFI_ESC_data2, CFI_ESC_data4, CFI_ESC_data8), so that the
decoded offset can be stored in the SFrame FRE.
Regards,
Jens
--
Jens Remus
Linux on Z Development (D3303)
+49-7031-16-1128 Office
jremus@de.ibm.com
IBM
IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/
More information about the Binutils
mailing list