Skip to content

Commit 8aa19a8

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 084452a commit 8aa19a8

File tree

22 files changed

+511
-187
lines changed

22 files changed

+511
-187
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: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,9 +624,11 @@ impl ABIMachineSpec for AArch64MachineDeps {
624624
}
625625
}
626626

627-
fn gen_debug_frame_info(
627+
fn gen_prologue_start(
628+
_setup_frame: bool,
629+
_call_conv: isa::CallConv,
628630
flags: &settings::Flags,
629-
_isa_flags: &Vec<settings::Value>,
631+
isa_flags: &Vec<settings::Value>,
630632
) -> SmallInstVec<Inst> {
631633
let mut insts = SmallVec::new();
632634
if flags.unwind_info() {
@@ -636,6 +638,13 @@ impl ABIMachineSpec for AArch64MachineDeps {
636638
},
637639
});
638640
}
641+
642+
if has_bool_setting("use_bti", isa_flags) {
643+
insts.push(Inst::Bti {
644+
targets: BranchTargetType::C,
645+
});
646+
}
647+
639648
insts
640649
}
641650

@@ -1344,3 +1353,10 @@ fn is_reg_clobbered_by_call(call_conv_of_callee: isa::CallConv, r: RealReg) -> b
13441353
_ => panic!("Unexpected RegClass"),
13451354
}
13461355
}
1356+
1357+
fn has_bool_setting(name: &str, isa_flags: &Vec<settings::Value>) -> bool {
1358+
isa_flags
1359+
.iter()
1360+
.find(|&f| f.name == name)
1361+
.map_or(false, |f| f.as_bool().unwrap_or(false))
1362+
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,11 @@
747747
(rd WritableReg)
748748
(mem AMode))
749749

750+
;; Branch target identification; equivalent to a no-op if Branch Target
751+
;; Identification (FEAT_BTI) is not supported.
752+
(Bti
753+
(targets BranchTargetType))
754+
750755
;; Marker, no-op in generated code: SP "virtual offset" is adjusted. This
751756
;; controls how AMode::NominalSPOffset args are lowered.
752757
(VirtualSPOffsetAdj
@@ -1279,6 +1284,15 @@
12791284
(Umin)
12801285
))
12811286

1287+
;; Branch target types
1288+
(type BranchTargetType
1289+
(enum
1290+
(None)
1291+
(C)
1292+
(J)
1293+
(JC)
1294+
))
1295+
12821296
;; Extractor helpers for various immmediate constants ;;;;;;;;;;;;;;;;;;;;;;;;;;
12831297

12841298
(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
@@ -2763,6 +2763,16 @@ impl MachInstEmit for Inst {
27632763
add.emit(sink, emit_info, state);
27642764
}
27652765
}
2766+
&Inst::Bti { targets } => {
2767+
let targets = match targets {
2768+
BranchTargetType::None => 0b00,
2769+
BranchTargetType::C => 0b01,
2770+
BranchTargetType::J => 0b10,
2771+
BranchTargetType::JC => 0b11,
2772+
};
2773+
2774+
sink.put4(0xd503241f | targets << 6);
2775+
}
27662776
&Inst::VirtualSPOffsetAdj { offset } => {
27672777
log::trace!(
27682778
"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.
@@ -1033,6 +1033,7 @@ fn aarch64_get_regs(inst: &Inst, collector: &mut RegUsageCollector) {
10331033
collector.add_def(rd);
10341034
memarg_regs(mem, collector);
10351035
}
1036+
&Inst::Bti { .. } => {}
10361037
&Inst::VirtualSPOffsetAdj { .. } => {}
10371038
&Inst::ValueLabelMarker { reg, .. } => {
10381039
collector.add_use(reg);
@@ -1874,6 +1875,7 @@ pub fn aarch64_map_regs<RM: RegMapper>(inst: &mut Inst, mapper: &RM) {
18741875
mapper.map_def(rd);
18751876
map_mem(mapper, mem);
18761877
}
1878+
&mut Inst::Bti { .. } => {}
18771879
&mut Inst::VirtualSPOffsetAdj { .. } => {}
18781880
&mut Inst::EmitIsland { .. } => {}
18791881
&mut Inst::ElfTlsGetAddr { .. } => {}
@@ -3453,6 +3455,16 @@ impl Inst {
34533455
}
34543456
ret
34553457
}
3458+
&Inst::Bti { targets } => {
3459+
let targets = match targets {
3460+
BranchTargetType::None => "",
3461+
BranchTargetType::C => " c",
3462+
BranchTargetType::J => " j",
3463+
BranchTargetType::JC => " jc",
3464+
};
3465+
3466+
"bti".to_string() + targets
3467+
}
34563468
&Inst::VirtualSPOffsetAdj { offset } => {
34573469
state.virtual_sp_offset += offset;
34583470
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
@@ -1578,4 +1578,18 @@ impl LowerBackend for AArch64Backend {
15781578
fn maybe_pinned_reg(&self) -> Option<Reg> {
15791579
Some(xreg(PINNED_REG))
15801580
}
1581+
1582+
fn start_block<C: LowerCtx<I = Inst>>(
1583+
&self,
1584+
is_indirect_branch_target: bool,
1585+
ctx: &mut C,
1586+
) -> CodegenResult<()> {
1587+
if self.isa_flags.use_bti() && is_indirect_branch_target {
1588+
ctx.emit(Inst::Bti {
1589+
targets: BranchTargetType::J,
1590+
});
1591+
}
1592+
1593+
Ok(())
1594+
}
15811595
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
src/clif.isle 9ea75a6f790b5c03
22
src/prelude.isle 73285cd431346d53
3-
src/isa/aarch64/inst.isle 4c176462894836e5
3+
src/isa/aarch64/inst.isle aab18fa448473a4f
44
src/isa/aarch64/lower.isle aff657984bf30686

0 commit comments

Comments
 (0)