Skip to content

Commit 9a5aaf2

Browse files
committed
Initial forward-edge CFI implementation
If the target platform supports the Branch Target Identification extension to the Arm instruction set architecture, then start all basic blocks that are targets of indirect branches with the BTI instruction. Note that in order to simplify the implementation, the BTI instructions are inserted at the beginning of all basic blocks, irrespetive of whether they are indirect branch targets or not. Copyright (c) 2022, Arm Limited.
1 parent 89919f4 commit 9a5aaf2

15 files changed

Lines changed: 425 additions & 203 deletions

File tree

cranelift/codegen/meta/src/isa/arm64.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,20 @@ use crate::shared::Definitions as SharedDefinitions;
55

66
fn define_settings(_shared: &SettingGroup) -> SettingGroup {
77
let mut setting = SettingGroupBuilder::new("arm64");
8-
let has_lse = setting.add_bool("has_lse", "Has Large System Extensions support.", "", false);
8+
let has_bti = setting.add_bool(
9+
"has_bti",
10+
"Has Branch Target Identification (FEAT_BTI) support.",
11+
"",
12+
false,
13+
);
14+
let has_lse = setting.add_bool(
15+
"has_lse",
16+
"Has Large System Extensions (FEAT_LSE) support.",
17+
"",
18+
false,
19+
);
920

21+
setting.add_predicate("use_bti", predicate!(has_bti));
1022
setting.add_predicate("use_lse", predicate!(has_lse));
1123
setting.build()
1224
}

cranelift/codegen/src/isa/aarch64/abi.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,9 +619,11 @@ impl ABIMachineSpec for AArch64MachineDeps {
619619
}
620620
}
621621

622-
fn gen_debug_frame_info(
622+
fn gen_prologue_start(
623+
_call_conv: isa::CallConv,
624+
_setup_frame: bool,
623625
flags: &settings::Flags,
624-
_isa_flags: &Vec<settings::Value>,
626+
isa_flags: &Vec<settings::Value>,
625627
) -> SmallInstVec<Inst> {
626628
let mut insts = SmallVec::new();
627629
if flags.unwind_info() {
@@ -631,6 +633,13 @@ impl ABIMachineSpec for AArch64MachineDeps {
631633
},
632634
});
633635
}
636+
637+
if has_bti(isa_flags) {
638+
insts.push(Inst::Bti {
639+
targets: BranchTargetType::C,
640+
});
641+
}
642+
634643
insts
635644
}
636645

@@ -1338,3 +1347,10 @@ fn is_reg_clobbered_by_call(call_conv_of_callee: isa::CallConv, r: RealReg) -> b
13381347
_ => panic!("Unexpected RegClass"),
13391348
}
13401349
}
1350+
1351+
fn has_bti(isa_flags: &Vec<settings::Value>) -> bool {
1352+
isa_flags
1353+
.iter()
1354+
.find(|&f| f.name == "has_bti")
1355+
.map_or(false, |f| f.as_bool().unwrap_or(false))
1356+
}

cranelift/codegen/src/isa/aarch64/inst.isle

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,11 @@
735735
(rd WritableReg)
736736
(mem AMode))
737737

738+
;; Branch target identification; equivalent to a no-op if Branch Target
739+
;; Identification (FEAT_BTI) is not supported.
740+
(Bti
741+
(targets BranchTargetType))
742+
738743
;; Marker, no-op in generated code: SP "virtual offset" is adjusted. This
739744
;; controls how AMode::NominalSPOffset args are lowered.
740745
(VirtualSPOffsetAdj
@@ -1290,6 +1295,15 @@
12901295
(Umin)
12911296
))
12921297

1298+
;; Branch target types
1299+
(type BranchTargetType
1300+
(enum
1301+
(None)
1302+
(C)
1303+
(J)
1304+
(JC)
1305+
))
1306+
12931307
;; Extractor helpers for various immmediate constants ;;;;;;;;;;;;;;;;;;;;;;;;;;
12941308

12951309
(decl move_wide_const_from_u64 (MoveWideConst) u64)

cranelift/codegen/src/isa/aarch64/inst/emit.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2769,6 +2769,16 @@ impl MachInstEmit for Inst {
27692769
add.emit(sink, emit_info, state);
27702770
}
27712771
}
2772+
&Inst::Bti { targets } => {
2773+
let targets = match targets {
2774+
BranchTargetType::None => 0b00,
2775+
BranchTargetType::C => 0b01,
2776+
BranchTargetType::J => 0b10,
2777+
BranchTargetType::JC => 0b11,
2778+
};
2779+
2780+
sink.put4(0xd503241f | targets << 6);
2781+
}
27722782
&Inst::VirtualSPOffsetAdj { offset } => {
27732783
log::trace!(
27742784
"virtual sp offset adjusted by {} -> {}",

cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ fn test_aarch64_binemit() {
2828
//
2929
// $ echo "mov x1, x2" | aarch64inst.sh
3030
insns.push((Inst::Ret, "C0035FD6", "ret"));
31+
insns.push((
32+
Inst::Bti {
33+
targets: BranchTargetType::J,
34+
},
35+
"9F2403D5",
36+
"bti j",
37+
));
3138
insns.push((Inst::Nop0, "", "nop-zero-len"));
3239
insns.push((Inst::Nop4, "1F2003D5", "nop"));
3340
insns.push((

cranelift/codegen/src/isa/aarch64/inst/mod.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ mod emit_tests;
3939
// Instructions (top level): definition
4040

4141
pub use crate::isa::aarch64::lower::isle::generated_code::{
42-
ALUOp, ALUOp3, AtomicRMWOp, BitOp, FPUOp1, FPUOp2, FPUOp3, FpuRoundMode, FpuToIntOp,
43-
IntToFpuOp, MInst as Inst, VecALUOp, VecExtendOp, VecLanesOp, VecMisc2, VecPairOp, VecRRLongOp,
44-
VecRRNarrowOp, VecRRPairLongOp, VecRRRLongOp, VecShiftImmOp,
42+
ALUOp, ALUOp3, AtomicRMWOp, BitOp, BranchTargetType, FPUOp1, FPUOp2, FPUOp3, FpuRoundMode,
43+
FpuToIntOp, IntToFpuOp, MInst as Inst, VecALUOp, VecExtendOp, VecLanesOp, VecMisc2, VecPairOp,
44+
VecRRLongOp, VecRRNarrowOp, VecRRPairLongOp, VecRRRLongOp, VecShiftImmOp,
4545
};
4646

4747
/// A floating-point unit (FPU) operation with two args, a register and an immediate.
@@ -1011,6 +1011,7 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
10111011
collector.add_def(rd);
10121012
memarg_regs(mem, collector);
10131013
}
1014+
&Inst::Bti { .. } => {}
10141015
&Inst::VirtualSPOffsetAdj { .. } => {}
10151016
&Inst::ValueLabelMarker { reg, .. } => {
10161017
collector.add_use(reg);
@@ -1849,6 +1850,7 @@ pub fn aarch64_map_regs<RM: RegMapper>(inst: &mut Inst, mapper: &RM) {
18491850
mapper.map_def(rd);
18501851
map_mem(mapper, mem);
18511852
}
1853+
&mut Inst::Bti { .. } => {}
18521854
&mut Inst::VirtualSPOffsetAdj { .. } => {}
18531855
&mut Inst::EmitIsland { .. } => {}
18541856
&mut Inst::ElfTlsGetAddr { .. } => {}
@@ -3431,6 +3433,16 @@ impl Inst {
34313433
}
34323434
ret
34333435
}
3436+
&Inst::Bti { targets } => {
3437+
let targets = match targets {
3438+
BranchTargetType::None => "",
3439+
BranchTargetType::C => " c",
3440+
BranchTargetType::J => " j",
3441+
BranchTargetType::JC => " jc",
3442+
};
3443+
3444+
"bti".to_string() + targets
3445+
}
34343446
&Inst::VirtualSPOffsetAdj { offset } => {
34353447
state.virtual_sp_offset += offset;
34363448
format!("virtual_sp_offset_adjust {}", offset)

cranelift/codegen/src/isa/aarch64/lower.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,4 +1555,14 @@ impl LowerBackend for AArch64Backend {
15551555
fn maybe_pinned_reg(&self) -> Option<Reg> {
15561556
Some(xreg(PINNED_REG))
15571557
}
1558+
1559+
fn start_block<C: LowerCtx<I = Inst>>(&self, ctx: &mut C) -> CodegenResult<()> {
1560+
if self.isa_flags.use_bti() {
1561+
ctx.emit(Inst::Bti {
1562+
targets: BranchTargetType::J,
1563+
});
1564+
}
1565+
1566+
Ok(())
1567+
}
15581568
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
src/clif.isle f176ef3bba99365
22
src/prelude.isle 22dd5ff133398960
3-
src/isa/aarch64/inst.isle 5fa80451697b084f
3+
src/isa/aarch64/inst.isle 6d7c700c2a79d842
44
src/isa/aarch64/lower.isle 2d2e1e076a0c8a23

0 commit comments

Comments
 (0)