From df8eaa8c24d84a3e77594faa9218cd250504d286 Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Wed, 1 Jan 2020 12:50:04 +0100 Subject: [PATCH] examples --- Cargo.toml | 3 +- examples/klee_cortex_m_rt_test.rs | 26 ++--- examples/klee_cortex_m_test_stable.rs | 135 ++++++++++++++++++++++++++ examples/vcell_test.rs | 2 +- 4 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 examples/klee_cortex_m_test_stable.rs diff --git a/Cargo.toml b/Cargo.toml index ad052c6..9cb2a14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,8 @@ optional = true [patch.crates-io] vcell = { git = "https://github.com/perlindgren/vcell.git", branch = "trustit" } cortex-m = { git = "https://github.com/perlindgren/cortex-m.git", branch = "trustit" } -cortex-m-rt = { git = "https://github.com/perlindgren/cortex-m-rt.git", branch = "trustit" } +#cortex-m-rt = { git = "https://github.com/perlindgren/cortex-m-rt.git", branch = "trustit" } +cortex-m-rt = { path = "../cortex-m-rt" } [features] klee-analysis = [ "vcell/klee-analysis", "cortex-m/klee-analysis", "cortex-m-rt/klee-analysis" ] diff --git a/examples/klee_cortex_m_rt_test.rs b/examples/klee_cortex_m_rt_test.rs index be547e7..d18f52a 100644 --- a/examples/klee_cortex_m_rt_test.rs +++ b/examples/klee_cortex_m_rt_test.rs @@ -7,20 +7,20 @@ use panic_klee as _; use klee_sys::klee_abort; -use cortex_m::peripheral::Peripherals; +// use cortex_m::peripheral::Peripherals; -// #[entry] -// unsafe fn main() -> ! { -// let peripherals = Peripherals::take().unwrap(); -// // let peripherals = Peripherals::take().unwrap(); -// let mut dwt = peripherals.DWT; -// dwt.enable_cycle_counter(); -// let a = dwt.cyccnt.read(); -// if a == 100 { -// klee_abort!(); -// } -// klee_abort!(); -// } +#[entry] +unsafe fn main() -> ! { + // let peripherals = Peripherals::take().unwrap(); + // // let peripherals = Peripherals::take().unwrap(); + // let mut dwt = peripherals.DWT; + // dwt.enable_cycle_counter(); + // let a = dwt.cyccnt.read(); + // if a == 100 { + // klee_abort!(); + // } + klee_abort!(); +} #[pre_init] unsafe fn pre_init() {} diff --git a/examples/klee_cortex_m_test_stable.rs b/examples/klee_cortex_m_test_stable.rs new file mode 100644 index 0000000..f72afdc --- /dev/null +++ b/examples/klee_cortex_m_test_stable.rs @@ -0,0 +1,135 @@ +// > cargo klee --example klee_cortex_m_test -r -k -g -v --release +// ... +// KLEE: done: total instructions = 33 +// KLEE: done: completed paths = 1 +// KLEE: done: generated tests = 1 +// +// The example, has just one path, leading up to an abort. +// The reason is that the progam unconditionally will panic, as +// taking the peripheral is only only allowed once (for soundness). +// (Internally this in tracked by a state variable.) +// +// This is very good news, that KLEE will detect the error at compile time. +// +// Let's remove the error to see if the example code is correct. +// (comment out the second `take`) +// +// > cargo klee --example klee_cortex_m_test -r -k -g -v +// ... +// KLEE: ERROR: examples/klee_cortex_m_test.rs:120: divide by zero +// KLEE: NOTE: now ignoring this error at this location +// KLEE: ERROR: /home/pln/.cargo/git/checkouts/panic-klee-aa8d015442188497/3b0c897/src/lib.rs:8: abort failure +// KLEE: NOTE: now ignoring this error at this location +// +// KLEE: done: total instructions = 1454 +// KLEE: done: completed paths = 6 +// KLEE: done: generated tests = 4 +// .. +//(gdb) shell ls klee-last +// assembly.ll info messages.txt run.istats run.stats test000001.div.err test000001.kquery test000001.ktest test000002.ktest warnings.txt +// +// So we see that test000001.ktest was causing a division error, +// the other test case passed +// +// (gdb) set env KTEST_FILE=klee-last/test000001.ktest +// (gdb) run +// Starting program: /home/pln/rust/grepit/klee-examples/target/debug/examples/klee_cortex_m_test.replay +// Program received signal SIGFPE, Arithmetic exception. +// 0x0000555555555528 in main () at examples/klee_cortex_m_test.rs:133 +// 133 let some_time_quota = unchecked_div(a, c - (b - 100)); +// +// Let's look at the actual test +// (gdb) shell ktest-tool klee-last/test000001.ktest +// ktest file : 'klee-last/test000001.ktest' +// args : ['/home/pln/rust/grepit/klee-examples/target/debug/examples/klee_cortex_m_test-d9038188a1e4d0b0.ll'] +// num objects: 5 +// object 0: name: 'PRIMASK' +// object 0: size: 4 +// object 0: data: b'\x01\x01\x01\x01' +// object 0: hex : 0x01010101 +// object 0: int : 16843009 +// object 0: uint: 16843009 +// object 0: text: .... +// object 1: name: 'vcell' +// object 1: size: 4 +// object 1: data: b'\x00\x00\x00\x00' +// object 1: hex : 0x00000000 +// object 1: int : 0 +// object 1: uint: 0 +// object 1: text: .... +// object 2: name: 'vcell' +// object 2: size: 4 +// object 2: data: b'\x00\x00\x00\x00' +// object 2: hex : 0x00000000 +// object 2: int : 0 +// object 2: uint: 0 +// object 2: text: .... +// object 3: name: 'vcell' +// object 3: size: 4 +// object 3: data: b'd\x00\x00\x00' +// object 3: hex : 0x64000000 +// object 3: int : 100 +// object 3: uint: 100 +// object 3: text: d... +// object 4: name: 'vcell' +// object 4: size: 4 +// object 4: data: b'\x00\x00\x00\x00' +// object 4: hex : 0x00000000 +// object 4: int : 0 +// object 4: uint: 0 +// object 4: text: .... +// +// (gdb) backtrace +// #0 0x0000555555555528 in main () at examples/klee_cortex_m_test.rs:133 +// (gdb) print a +// $1 = 0 +// (gdb) print b +// $2 = 100 +// (gdb) print c +// $3 = 0 +// +// In order to analyze hardware dependent code, hardware access are treated +// as a new symbolic value. In `cortex-m` we give symbolic names to core peripherals. +// The svd2rust generated PAC is currently given the symbolic name `vcell`. This +// might in the future change to giving the address to the register instead. +// +// A breakdown of the example: +// Behind the scenes the PRIMASK register is accessed, and given concrete value. +// (Under the hood, `Peripherals.take` executes in a global critical section.) +// +// This access is along the "happy path" towards the error, so any value would +// suffice (in this case 0x00000000 was selected by KLEE). +// +// The first `vcell` access: was done when enabling the cycle counter. +// The rest of accesses stem from reading `a`, `b`, and `c`. +// Critical here is that KLEE spots that `(c - (b - 100)) = 0`, leading up to a division +// by zero error (satisfied by `c == 0` and `b == 100`) +// +// Notice here, that this error is spotted EVEN while we are telling +// Rust to use the primitive (intrinsic) division for "unchecked_div" performance. +// +#![no_std] +#![no_main] + +// extern crate klee_sys; +extern crate cortex_m; +extern crate panic_klee; + +use cortex_m::peripheral::Peripherals; + +use core::ptr::read_volatile; + +#[no_mangle] +fn main() { + let peripherals = Peripherals::take().unwrap(); + // let peripherals = Peripherals::take().unwrap(); + let mut dwt = peripherals.DWT; + dwt.enable_cycle_counter(); + let a = dwt.cyccnt.read(); + let b = dwt.cyccnt.read(); + let c = dwt.cyccnt.read(); + unsafe { + let some_time_quota = a / (c - (b - 100)); + read_volatile(&some_time_quota); // prevent optimization + } +} diff --git a/examples/vcell_test.rs b/examples/vcell_test.rs index 236e748..b0b637e 100644 --- a/examples/vcell_test.rs +++ b/examples/vcell_test.rs @@ -1,7 +1,7 @@ #![no_std] #![no_main] -use klee_sys::{klee_abort, klee_assert, klee_assert_eq, klee_make_symbolic}; +use klee_sys::klee_abort; use panic_klee as _; use vcell; -- GitLab