Initial forward-edge CFI implementation (#3693)
* 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. * Refactor `from_artifacts` to avoid second `make_executable` (#1) This involves "parsing" twice but this is parsing just the header of an ELF file so it's not a very intensive operation and should be ok to do twice. * Address the code review feedback Copyright (c) 2022, Arm Limited. Co-authored-by: Alex Crichton <alex@alexcrichton.com>
This commit is contained in:
@@ -129,8 +129,15 @@ pub fn has_memory_fence_semantics(op: Opcode) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Visit all successors of a block with a given visitor closure.
|
||||
pub(crate) fn visit_block_succs<F: FnMut(Inst, Block)>(f: &Function, block: Block, mut visit: F) {
|
||||
/// Visit all successors of a block with a given visitor closure. The closure
|
||||
/// arguments are the branch instruction that is used to reach the successor,
|
||||
/// the successor block itself, and a flag indicating whether the block is
|
||||
/// branched to via a table entry.
|
||||
pub(crate) fn visit_block_succs<F: FnMut(Inst, Block, bool)>(
|
||||
f: &Function,
|
||||
block: Block,
|
||||
mut visit: F,
|
||||
) {
|
||||
for inst in f.layout.block_likely_branches(block) {
|
||||
if f.dfg[inst].opcode().is_branch() {
|
||||
visit_branch_targets(f, inst, &mut visit);
|
||||
@@ -138,18 +145,20 @@ pub(crate) fn visit_block_succs<F: FnMut(Inst, Block)>(f: &Function, block: Bloc
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_branch_targets<F: FnMut(Inst, Block)>(f: &Function, inst: Inst, visit: &mut F) {
|
||||
fn visit_branch_targets<F: FnMut(Inst, Block, bool)>(f: &Function, inst: Inst, visit: &mut F) {
|
||||
match f.dfg[inst].analyze_branch(&f.dfg.value_lists) {
|
||||
BranchInfo::NotABranch => {}
|
||||
BranchInfo::SingleDest(dest, _) => {
|
||||
visit(inst, dest);
|
||||
visit(inst, dest, false);
|
||||
}
|
||||
BranchInfo::Table(table, maybe_dest) => {
|
||||
if let Some(dest) = maybe_dest {
|
||||
visit(inst, dest);
|
||||
// The default block is reached via a direct conditional branch,
|
||||
// so it is not part of the table.
|
||||
visit(inst, dest, false);
|
||||
}
|
||||
for &dest in f.jump_tables[table].as_slice() {
|
||||
visit(inst, dest);
|
||||
visit(inst, dest, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user