Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions definitions/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,16 @@ macro_rules! __for_each_inst_inner {
(JALR_VERSION1, 0xa9),
(FAR_JUMP_REL, 0xaa),
(FAR_JUMP_ABS, 0xab),
(CUSTOM_ASM_TRACE_JUMP, 0xac),
(CUSTOM_TRACE_END, 0xad)
// CFI
(LPAD, 0xac),
(SSPUSH, 0xad),
(SSPOPCHK, 0xae),
(SSRDP, 0xaf),
(SSAMOSWAP_W, 0xb0),
(SSAMOSWAP_D, 0xb1),
// CUSTOM
(CUSTOM_ASM_TRACE_JUMP, 0xb2),
(CUSTOM_TRACE_END, 0xb3)
);
};
}
Expand Down
2 changes: 2 additions & 0 deletions definitions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ pub const MEMORY_FRAMESIZE: usize = 1 << MEMORY_FRAME_SHIFTS; // 256 KB
pub const MEMORY_FRAME_PAGE_SHIFTS: usize = MEMORY_FRAME_SHIFTS - RISCV_PAGE_SHIFTS;

pub const DEFAULT_MEMORY_SIZE: usize = 4 << 20; // 4 MB
pub const DEFAULT_SHADOW_STACK_SIZE: usize = 64 << 10; // 64 KB

pub const ISA_IMC: u8 = 0b0000_0000;
pub const ISA_B: u8 = 0b0000_0001;
pub const ISA_MOP: u8 = 0b0000_0010;
// Extension ISA_A is not enabled in ckb 2nd hardfork(aka, meepo hardfork)
pub const ISA_A: u8 = 0b0000_0100;
pub const ISA_CFI: u8 = 0b0000_1000;
16 changes: 16 additions & 0 deletions examples/cfi_detector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/// Example: Testing CFI Feature Detection
use bytes::Bytes;
use ckb_vm::elf::parse_elf;
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
let elf_path = &args[1];
let program_data = fs::read(elf_path)?;
let program = Bytes::from(program_data);
let program_metadata = parse_elf::<u64>(&program, 3)?;
println!("CFI_LP_UNLABELED: {}", program_metadata.cfi.lp_unlabeled);
println!("CFI_SS: {}", program_metadata.cfi.ss);
println!("CFI_LP_FUNC_SIG: {}", program_metadata.cfi.lp_func_sig);
Ok(())
}
12 changes: 6 additions & 6 deletions examples/ckb_vm_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ impl<Mac: SupportMachine> Syscalls<Mac> for DebugSyscall {
#[cfg(has_asm)]
fn main_asm64(code: Bytes, args: Vec<Bytes>) -> Result<(), Box<dyn std::error::Error>> {
let asm_core = <ckb_vm::machine::asm::AsmCoreMachine as SupportMachine>::new(
ckb_vm::ISA_IMC | ckb_vm::ISA_B | ckb_vm::ISA_A | ckb_vm::ISA_MOP,
ckb_vm::machine::VERSION2,
ckb_vm::ISA_IMC | ckb_vm::ISA_B | ckb_vm::ISA_A | ckb_vm::ISA_MOP | ckb_vm::ISA_CFI,
ckb_vm::machine::VERSION3,
u64::MAX,
);
let core = ckb_vm::machine::asm::AsmDefaultMachineBuilder::new(asm_core)
Expand All @@ -70,8 +70,8 @@ fn main_asm64(_: Bytes, _: Vec<Bytes>) -> Result<(), Box<dyn std::error::Error>>

fn main_interpreter32(code: Bytes, args: Vec<Bytes>) -> Result<(), Box<dyn std::error::Error>> {
let core_machine = ckb_vm::DefaultCoreMachine::<u32, ckb_vm::SparseMemory<u32>>::new(
ckb_vm::ISA_IMC | ckb_vm::ISA_B | ckb_vm::ISA_A | ckb_vm::ISA_MOP,
ckb_vm::machine::VERSION2,
ckb_vm::ISA_IMC | ckb_vm::ISA_B | ckb_vm::ISA_A | ckb_vm::ISA_MOP | ckb_vm::ISA_CFI,
ckb_vm::machine::VERSION3,
u64::MAX,
);
let machine_builder = ckb_vm::RustDefaultMachineBuilder::new(core_machine)
Expand All @@ -91,8 +91,8 @@ fn main_interpreter32(code: Bytes, args: Vec<Bytes>) -> Result<(), Box<dyn std::

fn main_interpreter64(code: Bytes, args: Vec<Bytes>) -> Result<(), Box<dyn std::error::Error>> {
let core_machine = ckb_vm::DefaultCoreMachine::<u64, ckb_vm::SparseMemory<u64>>::new(
ckb_vm::ISA_IMC | ckb_vm::ISA_B | ckb_vm::ISA_A | ckb_vm::ISA_MOP,
ckb_vm::machine::VERSION2,
ckb_vm::ISA_IMC | ckb_vm::ISA_B | ckb_vm::ISA_A | ckb_vm::ISA_MOP | ckb_vm::ISA_CFI,
ckb_vm::machine::VERSION3,
u64::MAX,
);
let machine_builder = ckb_vm::RustDefaultMachineBuilder::new(core_machine)
Expand Down
17 changes: 12 additions & 5 deletions src/decoder.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use ckb_vm_definitions::instructions::{self as insts};
use ckb_vm_definitions::registers::{RA, ZERO};

use crate::elf::CFI;
use crate::error::OutOfBoundKind;
use crate::instructions::{
Instruction, InstructionFactory, Itype, R4type, R5type, Register, Rtype, Utype, a, b,
Instruction, InstructionFactory, Itype, R4type, R5type, Register, Rtype, Utype, a, b, cfi,
extract_opcode, i, instruction_length, m, rvc, set_instruction_length_n,
};
use crate::machine::VERSION2;
use crate::memory::Memory;
use crate::{Error, ISA_A, ISA_B, ISA_MOP, RISCV_PAGESIZE};
use crate::{Error, ISA_A, ISA_B, ISA_CFI, ISA_MOP, RISCV_PAGESIZE};

const RISCV_PAGESIZE_MASK: u64 = RISCV_PAGESIZE as u64 - 1;
const INSTRUCTION_CACHE_SIZE: usize = 4096;

pub trait InstDecoder {
fn new<R: Register>(isa: u8, version: u32) -> Self;
fn new<R: Register>(isa: u8, version: u32, cfi: CFI) -> Self;
fn decode<M: Memory>(&mut self, memory: &mut M, pc: u64) -> Result<Instruction, Error>;
fn reset_instructions_cache(&mut self) -> Result<(), Error>;
}
Expand All @@ -23,6 +24,7 @@ pub struct DefaultDecoder {
factories: Vec<InstructionFactory>,
mop: bool,
version: u32,
cfi: CFI,
// use a cache of instructions to avoid decoding the same instruction twice, pc is the key and the instruction is the value
instructions_cache: [(u64, u64); INSTRUCTION_CACHE_SIZE],
}
Expand All @@ -34,6 +36,7 @@ impl DefaultDecoder {
factories: vec![],
mop,
version,
cfi: CFI::default(),
instructions_cache: [(u64::MAX, 0); INSTRUCTION_CACHE_SIZE],
}
}
Expand Down Expand Up @@ -118,7 +121,7 @@ impl DefaultDecoder {
}
let instruction_bits = self.decode_bits(memory, pc)?;
for factory in &self.factories {
if let Some(instruction) = factory(instruction_bits, self.version) {
if let Some(instruction) = factory(instruction_bits, self.version, self.cfi) {
self.instructions_cache[instruction_cache_key] = (pc, instruction);
return Ok(instruction);
}
Expand Down Expand Up @@ -859,8 +862,12 @@ impl DefaultDecoder {
}

impl InstDecoder for DefaultDecoder {
fn new<R: Register>(isa: u8, version: u32) -> Self {
fn new<R: Register>(isa: u8, version: u32, cfi: CFI) -> Self {
let mut decoder = Self::empty(isa & ISA_MOP != 0, version);
decoder.cfi = cfi;
if isa & ISA_CFI != 0 {
decoder.add_instruction_factory(cfi::factory::<R>);
}
decoder.add_instruction_factory(rvc::factory::<R>);
decoder.add_instruction_factory(i::factory::<R>);
decoder.add_instruction_factory(m::factory::<R>);
Expand Down
Loading
Loading