Skip to content

Commit 11b4782

Browse files
committed
Refactor cfi decoder
1 parent 78b2588 commit 11b4782

File tree

15 files changed

+101
-22
lines changed

15 files changed

+101
-22
lines changed

examples/fib

-2.22 KB
Binary file not shown.

src/decoder.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use ckb_vm_definitions::instructions::{self as insts};
22
use ckb_vm_definitions::registers::{RA, ZERO};
33

4+
use crate::elf::CFI;
45
use crate::error::OutOfBoundKind;
56
use crate::instructions::{
67
Instruction, InstructionFactory, Itype, R4type, R5type, Register, Rtype, Utype, a, b, cfi,
@@ -14,7 +15,7 @@ const RISCV_PAGESIZE_MASK: u64 = RISCV_PAGESIZE as u64 - 1;
1415
const INSTRUCTION_CACHE_SIZE: usize = 4096;
1516

1617
pub trait InstDecoder {
17-
fn new<R: Register>(isa: u8, version: u32) -> Self;
18+
fn new<R: Register>(isa: u8, version: u32, cfi: CFI) -> Self;
1819
fn decode<M: Memory>(&mut self, memory: &mut M, pc: u64) -> Result<Instruction, Error>;
1920
fn reset_instructions_cache(&mut self) -> Result<(), Error>;
2021
}
@@ -23,6 +24,7 @@ pub struct DefaultDecoder {
2324
factories: Vec<InstructionFactory>,
2425
mop: bool,
2526
version: u32,
27+
cfi: CFI,
2628
// use a cache of instructions to avoid decoding the same instruction twice, pc is the key and the instruction is the value
2729
instructions_cache: [(u64, u64); INSTRUCTION_CACHE_SIZE],
2830
}
@@ -34,6 +36,7 @@ impl DefaultDecoder {
3436
factories: vec![],
3537
mop,
3638
version,
39+
cfi: CFI::default(),
3740
instructions_cache: [(u64::MAX, 0); INSTRUCTION_CACHE_SIZE],
3841
}
3942
}
@@ -118,7 +121,7 @@ impl DefaultDecoder {
118121
}
119122
let instruction_bits = self.decode_bits(memory, pc)?;
120123
for factory in &self.factories {
121-
if let Some(instruction) = factory(instruction_bits, self.version) {
124+
if let Some(instruction) = factory(instruction_bits, self.version, self.cfi) {
122125
self.instructions_cache[instruction_cache_key] = (pc, instruction);
123126
return Ok(instruction);
124127
}
@@ -859,8 +862,9 @@ impl DefaultDecoder {
859862
}
860863

861864
impl InstDecoder for DefaultDecoder {
862-
fn new<R: Register>(isa: u8, version: u32) -> Self {
865+
fn new<R: Register>(isa: u8, version: u32, cfi: CFI) -> Self {
863866
let mut decoder = Self::empty(isa & ISA_MOP != 0, version);
867+
decoder.cfi = cfi;
864868
if isa & ISA_CFI != 0 {
865869
decoder.add_instruction_factory(cfi::factory::<R>);
866870
}

src/elf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub struct LoadingAction {
136136
pub offset_from_addr: u64,
137137
}
138138

139-
#[derive(Clone, Debug, Default, Eq, PartialEq)]
139+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
140140
pub struct CFI {
141141
pub lp_unlabeled: bool,
142142
pub ss: bool,

src/instructions/a.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use ckb_vm_definitions::instructions as insts;
22

33
use super::utils::{funct3, funct7, opcode, rd, rs1, rs2};
44
use super::{Instruction, Register, Rtype, set_instruction_length_4};
5+
use crate::elf::CFI;
56

6-
pub fn factory<R: Register>(instruction_bits: u32, _: u32) -> Option<Instruction> {
7+
pub fn factory<R: Register>(instruction_bits: u32, _: u32, _: CFI) -> Option<Instruction> {
78
let bit_length = R::BITS;
89
if bit_length != 32 && bit_length != 64 {
910
return None;

src/instructions/b.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use ckb_vm_definitions::instructions as insts;
55

66
use super::utils::{self, funct3, funct7, opcode, rd, rs1, rs2};
77
use super::{Instruction, Itype, Register, Rtype, set_instruction_length_4};
8+
use crate::elf::CFI;
89

9-
pub fn factory<R: Register>(instruction_bits: u32, _: u32) -> Option<Instruction> {
10+
pub fn factory<R: Register>(instruction_bits: u32, _: u32, _: CFI) -> Option<Instruction> {
1011
let bit_length = R::BITS;
1112
if bit_length != 32 && bit_length != 64 {
1213
return None;

src/instructions/cfi.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
11
use super::utils::{funct3, funct7, opcode, rd, rs1, rs2};
22
use super::{Instruction, Register, set_instruction_length_2, set_instruction_length_4};
3-
use crate::instructions::{Itype, Rtype, Utype};
3+
use crate::elf::CFI;
4+
use crate::instructions::i::nop;
5+
use crate::instructions::{Itype, Rtype, Utype, extract_opcode, instruction_length};
46
use ckb_vm_definitions::instructions as insts;
57

6-
pub fn factory<R: Register>(instruction_bits: u32, _: u32) -> Option<Instruction> {
8+
pub fn factory<R: Register>(instruction_bits: u32, _: u32, cfi: CFI) -> Option<Instruction> {
9+
let inst = factory_bare::<R>(instruction_bits, 0, cfi);
10+
if let Some(i) = inst {
11+
if extract_opcode(i) == insts::OP_LPAD && cfi.lp_unlabeled {
12+
return Some(i);
13+
}
14+
if cfi.ss {
15+
return Some(i);
16+
}
17+
match instruction_length(i) {
18+
2 => return Some(set_instruction_length_4(nop())),
19+
4 => return Some(set_instruction_length_2(nop())),
20+
_ => return None, // Should not happen.
21+
}
22+
}
23+
None
24+
}
25+
26+
pub fn factory_bare<R: Register>(instruction_bits: u32, _: u32, _: CFI) -> Option<Instruction> {
727
match opcode(instruction_bits) {
828
0b_0010111 => {
929
if rd(instruction_bits) == 0 {

src/instructions/execute.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,10 @@ pub fn handle_jalr_version1<Mac: Machine>(
555555
next_pc = next_pc & (!Mac::REG::one());
556556
update_register(machine, i.rd(), link);
557557
machine.update_pc(next_pc);
558-
if i.rs1() != RA && i.rs1() != T0 && i.rs1() != T2 {
559-
machine.set_elp(1);
558+
if machine.cfi().lp_unlabeled {
559+
if i.rs1() != RA && i.rs1() != T0 && i.rs1() != T2 {
560+
machine.set_elp(1);
561+
}
560562
}
561563
Ok(())
562564
}
@@ -1510,7 +1512,6 @@ pub fn handle_lpad<Mac: Machine>(machine: &mut Mac, inst: Instruction) -> Result
15101512
if machine.elp() == 0 {
15111513
return Ok(());
15121514
}
1513-
println!("Handling LPAD instruction");
15141515
// If PC not 4-byte aligned then software-check exception.
15151516
if machine.pc().to_u64() % 4 != 0 {
15161517
return Err(Error::ShadowStackSoftwareCheckException);

src/instructions/i.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::utils::{
77
use super::{
88
Instruction, Itype, Register, Rtype, Stype, Utype, blank_instruction, set_instruction_length_4,
99
};
10+
use crate::elf::CFI;
1011

1112
// The FENCE instruction is used to order device I/O and memory accesses
1213
// as viewed by other RISC- V harts and external devices or coprocessors.
@@ -31,7 +32,7 @@ impl FenceType {
3132
}
3233
}
3334

34-
pub fn factory<R: Register>(instruction_bits: u32, version: u32) -> Option<Instruction> {
35+
pub fn factory<R: Register>(instruction_bits: u32, version: u32, _: CFI) -> Option<Instruction> {
3536
let bit_length = R::BITS;
3637
if bit_length != 32 && bit_length != 64 {
3738
return None;

src/instructions/m.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use ckb_vm_definitions::instructions as insts;
22

33
use super::utils::{funct3, funct7, opcode, rd, rs1, rs2};
44
use super::{Instruction, Register, Rtype, set_instruction_length_4};
5+
use crate::elf::CFI;
56

6-
pub fn factory<R: Register>(instruction_bits: u32, _: u32) -> Option<Instruction> {
7+
pub fn factory<R: Register>(instruction_bits: u32, _: u32, _: CFI) -> Option<Instruction> {
78
let bit_length = R::BITS;
89
if bit_length != 32 && bit_length != 64 {
910
return None;

src/instructions/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub mod tagged;
1414

1515
pub use self::register::Register;
1616
use super::Error;
17+
use super::elf::CFI;
1718
pub use ckb_vm_definitions::{
1819
instructions::{
1920
self as insts, Instruction, InstructionOpcode, MAXIMUM_BASIC_BLOCK_END_OPCODE,
@@ -35,7 +36,8 @@ pub fn extract_opcode(i: Instruction) -> InstructionOpcode {
3536
(((i >> 8) & 0xff00) | (i & 0x00ff)) as u16
3637
}
3738

38-
pub type InstructionFactory = fn(instruction_bits: u32, version: u32) -> Option<Instruction>;
39+
pub type InstructionFactory =
40+
fn(instruction_bits: u32, version: u32, cfi: CFI) -> Option<Instruction>;
3941

4042
// Blank instructions need no register indices nor immediates, they only have opcode
4143
// and module bit set.
@@ -458,14 +460,14 @@ mod tests {
458460
fn test_stype_display() {
459461
// This is "sd a5,568(sp)"
460462
let sd_inst = 0x22f13c23;
461-
let decoded = factory::<u64>(sd_inst, u32::MAX).expect("decoding");
463+
let decoded = factory::<u64>(sd_inst, u32::MAX, CFI::default()).expect("decoding");
462464
let stype = Stype(decoded);
463465

464466
assert_eq!("sd a5,568(sp)", format!("{}", stype));
465467

466468
// This is "beq a0,a5,1012e"
467469
let sd_inst = 0xf4f500e3;
468-
let decoded = factory::<u64>(sd_inst, u32::MAX).expect("decoding");
470+
let decoded = factory::<u64>(sd_inst, u32::MAX, CFI::default()).expect("decoding");
469471
let stype = Stype(decoded);
470472

471473
assert_eq!("beq a0,a5,-192", format!("{}", stype));

0 commit comments

Comments
 (0)