diff options
author | Indu Bhagat <indu.bhagat@oracle.com> | 2024-07-18 20:24:38 -0700 |
---|---|---|
committer | Indu Bhagat <indu.bhagat@oracle.com> | 2024-07-18 20:54:14 -0700 |
commit | 29085f7243e415db0e1617173eb80c441671ba0e (patch) | |
tree | 64725bccbb0327be82f51ffa32a27cca326e8a1a /gas/config/tc-aarch64.c | |
parent | 002ac0590221a01463a1eb92e2f0d81f616a4959 (diff) | |
download | gdb-29085f7243e415db0e1617173eb80c441671ba0e.zip gdb-29085f7243e415db0e1617173eb80c441671ba0e.tar.gz gdb-29085f7243e415db0e1617173eb80c441671ba0e.tar.bz2 |
gas: aarch64: add experimental support for SCFI
For synthesizing CFI (SCFI) for hand-written asm, the SCFI machinery in
GAS works on the generic GAS insns (ginsns). This patch adds support in
the aarch64 backend to create ginsns for a subset of the supported
machine instructions. The subset includes the minimal necessary
instructions to ensure SCFI correctness:
- Any potential register saves and unsaves. Hence, process instructions
belonging to a variety of iclasses involving str, ldr, stp, ldp.
- Any change of flow instructions. This includes all conditional and
unconditional branches, call (bl, blr, etc.) and return.
- Most importantly, any instruction that could affect the two registers
of interest: REG_SP, REG_FP. This set includes all pre-indexed and
post-indexed memory operations, with writeback, on the stack. This
set must also include other instructions (e.g., arithmetic insns)
where the destination register is one of the afore-mentioned registers.
With respect to callee-saved registers in Aarch64, FP/Advanced SIMD
registers D8-D15 are included along with the relevant GPRs. Calculating
offsets for loads and stores especially for Q registers needs special
attention here.
As an example,
str q8, [sp, #16]
On big-endian:
STR Qn stores as a 128-bit integer (MSB first), hence, should record
D8 as being saved at sp+24 rather than sp+16.
On little-endian:
should record D8 as being saved at sp+16
D8-D15 are the low 64 bits of Q8-Q15, and of Z8-Z15 if SVE is used;
hence, they remain "interesting" for SCFI purposes in such cases. A CFI
save slot always represents the low 64 bits, regardless of whether a
save occurs on D, Q or Z registers. Currently, the ginsn creation
machinery can handle D and Q registers on little-endian and big-endian.
Apart from creating ginsn, another key responsibility of the backend is
to make sure there are safeguards in place to detect and alert if an
instruction of interest may have been skipped. This is done via
aarch64_ginsn_unhandled () (similar to the x86 backend). This function
, hence, is also intended to alert when future ISA changes may otherwise
render SCFI results incorrect, because of missing ginsns for the newly
added machine instructions.
At this time, becuase of the complexities wrt endianness in handling Z
register usage, skip sve_misc opclass altogether for now. The SCFI
machinery will error out (using the aarch64_ginsn_unhandled () code
path) though if Z register usage affects correctness.
The current SCFI machinery does not currently synthesize the
PAC-related, aarch64-specific CFI directives: .cfi_b_key_frame. The
support for this is planned for near future.
SCFI is enabled for ELF targets only.
gas/
* config/tc-aarch64-ginsn.c: New file.
* config/tc-aarch64.c (md_assemble): Include tc-aarch64-ginsn.c
file. Invoke aarch64_ginsn_new.
* config/tc-aarch64.h (TARGET_USE_GINSN): Define for SCFI
enablement.
(TARGET_USE_SCFI): Likewise.
(SCFI_MAX_REG_ID): New definition.
(REG_FP): Likewise.
(REG_LR): Likewise.
(REG_SP): Likewise.
(SCFI_INIT_CFA_OFFSET): Likewise.
(SCFI_CALLEE_SAVED_REG_P): Likewise.
(aarch64_scfi_callee_saved_p): New declaration.
Diffstat (limited to 'gas/config/tc-aarch64.c')
-rw-r--r-- | gas/config/tc-aarch64.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index ceb0f34..e94a0cf 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -33,6 +33,7 @@ #include "dw2gencfi.h" #include "sframe.h" #include "gen-sframe.h" +#include "scfi.h" #endif #include "dw2gencfi.h" @@ -8614,6 +8615,10 @@ dump_opcode_operands (const aarch64_opcode *opcode) } #endif /* DEBUG_AARCH64 */ +#ifdef OBJ_ELF +# include "tc-aarch64-ginsn.c" +#endif + /* This is the guts of the machine-dependent assembler. STR points to a machine dependent instruction. This function is supposed to emit the frags/bytes it assembles to. */ @@ -8751,6 +8756,16 @@ md_assemble (char *str) output_inst (copy); } +#ifdef OBJ_ELF + if (flag_synth_cfi) + { + ginsnS *ginsn; + ginsn = aarch64_ginsn_new (symbol_temp_new_now (), + frch_ginsn_gen_mode ()); + frch_ginsn_data_append (ginsn); + } +#endif + /* Issue non-fatal messages if any. */ output_operand_error_report (str, true); return; |