Skip to content

Commit f5f2375

Browse files
committed
Initial forward-edge CFI implementation
Give the user the option to start all basic blocks that are targets of indirect branches with the BTI instruction introduced by the Branch Target Identification extension to the Arm instruction set architecture. Copyright (c) 2022, Arm Limited.
1 parent 71fc16b commit f5f2375

File tree

24 files changed

+522
-217
lines changed

24 files changed

+522
-217
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,19 @@ 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_lse = setting.add_bool(
9+
"has_lse",
10+
"Has Large System Extensions (FEAT_LSE) support.",
11+
"",
12+
false,
13+
);
14+
15+
setting.add_bool(
16+
"use_bti",
17+
"Use Branch Target Identification (FEAT_BTI) instructions.",
18+
"",
19+
false,
20+
);
921

1022
setting.add_predicate("use_lse", predicate!(has_lse));
1123
setting.build()

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,9 +622,9 @@ impl ABIMachineSpec for AArch64MachineDeps {
622622
}
623623
}
624624

625-
fn gen_debug_frame_info(
625+
fn gen_prologue_start(
626626
flags: &settings::Flags,
627-
_isa_flags: &Vec<settings::Value>,
627+
isa_flags: &Vec<settings::Value>,
628628
) -> SmallInstVec<Inst> {
629629
let mut insts = SmallVec::new();
630630
if flags.unwind_info() {
@@ -634,6 +634,13 @@ impl ABIMachineSpec for AArch64MachineDeps {
634634
},
635635
});
636636
}
637+
638+
if has_bool_setting("use_bti", isa_flags) {
639+
insts.push(Inst::Bti {
640+
targets: BranchTargetType::C,
641+
});
642+
}
643+
637644
insts
638645
}
639646

@@ -1323,3 +1330,10 @@ fn is_reg_clobbered_by_call(call_conv_of_callee: isa::CallConv, r: RealReg) -> b
13231330
}
13241331
}
13251332
}
1333+
1334+
fn has_bool_setting(name: &str, isa_flags: &Vec<settings::Value>) -> bool {
1335+
isa_flags
1336+
.iter()
1337+
.find(|&f| f.name == name)
1338+
.map_or(false, |f| f.as_bool().unwrap_or(false))
1339+
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,11 @@
730730
(rd WritableReg)
731731
(mem AMode))
732732

733+
;; Branch target identification; equivalent to a no-op if Branch Target
734+
;; Identification (FEAT_BTI) is not supported.
735+
(Bti
736+
(targets BranchTargetType))
737+
733738
;; Marker, no-op in generated code: SP "virtual offset" is adjusted. This
734739
;; controls how AMode::NominalSPOffset args are lowered.
735740
(VirtualSPOffsetAdj
@@ -1278,6 +1283,15 @@
12781283
(Xchg)
12791284
))
12801285

1286+
;; Branch target types
1287+
(type BranchTargetType
1288+
(enum
1289+
(None)
1290+
(C)
1291+
(J)
1292+
(JC)
1293+
))
1294+
12811295
;; Extractors for target features ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
12821296
(decl use_lse () Inst)
12831297
(extern extractor use_lse use_lse)

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3048,6 +3048,16 @@ impl MachInstEmit for Inst {
30483048
add.emit(&[], sink, emit_info, state);
30493049
}
30503050
}
3051+
&Inst::Bti { targets } => {
3052+
let targets = match targets {
3053+
BranchTargetType::None => 0b00,
3054+
BranchTargetType::C => 0b01,
3055+
BranchTargetType::J => 0b10,
3056+
BranchTargetType::JC => 0b11,
3057+
};
3058+
3059+
sink.put4(0xd503241f | targets << 6);
3060+
}
30513061
&Inst::VirtualSPOffsetAdj { offset } => {
30523062
log::trace!(
30533063
"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
@@ -38,6 +38,13 @@ fn test_aarch64_binemit() {
3838
//
3939
// $ echo "mov x1, x2" | aarch64inst.sh
4040
insns.push((Inst::Ret { rets: vec![] }, "C0035FD6", "ret"));
41+
insns.push((
42+
Inst::Bti {
43+
targets: BranchTargetType::J,
44+
},
45+
"9F2403D5",
46+
"bti j",
47+
));
4148
insns.push((Inst::Nop0, "", "nop-zero-len"));
4249
insns.push((Inst::Nop4, "1F2003D5", "nop"));
4350
insns.push((

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

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

3838
pub use crate::isa::aarch64::lower::isle::generated_code::{
39-
ALUOp, ALUOp3, AtomicRMWLoopOp, AtomicRMWOp, BitOp, FPUOp1, FPUOp2, FPUOp3, FpuRoundMode,
40-
FpuToIntOp, IntToFpuOp, MInst as Inst, MoveWideOp, VecALUOp, VecExtendOp, VecLanesOp, VecMisc2,
41-
VecPairOp, VecRRLongOp, VecRRNarrowOp, VecRRPairLongOp, VecRRRLongOp, VecShiftImmOp,
39+
ALUOp, ALUOp3, AtomicRMWLoopOp, AtomicRMWOp, BitOp, BranchTargetType, FPUOp1, FPUOp2, FPUOp3,
40+
FpuRoundMode, FpuToIntOp, IntToFpuOp, MInst as Inst, MoveWideOp, VecALUOp, VecExtendOp,
41+
VecLanesOp, VecMisc2, VecPairOp, VecRRLongOp, VecRRNarrowOp, VecRRPairLongOp, VecRRRLongOp,
42+
VecShiftImmOp,
4243
};
4344

4445
/// A floating-point unit (FPU) operation with two args, a register and an immediate.
@@ -1025,6 +1026,7 @@ fn aarch64_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut Operan
10251026
collector.reg_def(rd);
10261027
memarg_operands(mem, collector);
10271028
}
1029+
&Inst::Bti { .. } => {}
10281030
&Inst::VirtualSPOffsetAdj { .. } => {}
10291031

10301032
&Inst::ElfTlsGetAddr { .. } => {
@@ -2703,6 +2705,16 @@ impl Inst {
27032705
}
27042706
ret
27052707
}
2708+
&Inst::Bti { targets } => {
2709+
let targets = match targets {
2710+
BranchTargetType::None => "",
2711+
BranchTargetType::C => " c",
2712+
BranchTargetType::J => " j",
2713+
BranchTargetType::JC => " jc",
2714+
};
2715+
2716+
"bti".to_string() + targets
2717+
}
27062718
&Inst::VirtualSPOffsetAdj { offset } => {
27072719
state.virtual_sp_offset += offset;
27082720
format!("virtual_sp_offset_adjust {}", offset)

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,4 +1559,18 @@ impl LowerBackend for AArch64Backend {
15591559
fn maybe_pinned_reg(&self) -> Option<Reg> {
15601560
Some(xreg(PINNED_REG))
15611561
}
1562+
1563+
fn start_block<C: LowerCtx<I = Inst>>(
1564+
&self,
1565+
is_indirect_branch_target: bool,
1566+
ctx: &mut C,
1567+
) -> CodegenResult<()> {
1568+
if self.isa_flags.use_bti() && is_indirect_branch_target {
1569+
ctx.emit(Inst::Bti {
1570+
targets: BranchTargetType::J,
1571+
});
1572+
}
1573+
1574+
Ok(())
1575+
}
15621576
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
src/clif.isle 443b34b797fc8ace
22
src/prelude.isle 97c4b6eebbab9f05
3-
src/isa/aarch64/inst.isle 21a43af20be377d2
3+
src/isa/aarch64/inst.isle 542264a10347b8f1
44
src/isa/aarch64/lower.isle 75ad8450963e3829

0 commit comments

Comments
 (0)