我找到的最接近答案可能与Eva插件的-absolute-valid-range
有关,是吗?我是否必须提出读/写ACSL谓词才能进行虚拟读/写?
示例代码:
#include <stdint.h>
#define BASE_ADDR 0x0e000000
#define BASE_LIMIT 0x0e001000
#define TEST_REG 0x10
/*@ requires BASE_ADDR <= addr < BASE_LIMIT;
@ assigns \nothing;
*/
static inline uint32_t mmio_read32(volatile uintptr_t addr)
{
volatile uint32_t *ptr = (volatile uint32_t *)addr;
return *ptr;
}
/*@
@ requires 0 <= offset <= 0x1000;
@ assigns \nothing;
*/
static inline uint32_t read32(uintptr_t offset)
{
return mmio_read32((uintptr_t)BASE_ADDR + offset);
}
void main(){
uint32_t test;
test = read32(TEST_REG);
return;
}
Frama-c命令和输出:
[frama -absolute-valid-range 0x0e000000-0x0e001000 -wp mmio2.c
[kernel] Parsing mmio2.c (with preprocessing)
[wp] Warning: Missing RTE guards
[wp] 6 goals scheduled
[wp] [Alt-Ergo] Goal typed_read32_call_mmio_read32_pre : Unknown (Qed:4ms) (51ms)
[wp] Proved goals: 5 / 6
Qed: 5
Alt-Ergo: 0 (unknown: 1)][1]
如何实现目标“ typed_read32_call_mmio_read32_pre”?或者是预期的?
答案 0 :(得分:1)
证明失败的事实与两个独立的问题有关,但它们都与使用绝对地址无关。
首先,由于mmio_read32
的参数被标记为volatile
,因此WP认为其值可以是任何值。特别是,在评估offset
时,对addr
进行的假设均不成立。通过查看生成的目标,您可以在GUI中看到这一点(在底部的WP Goals标签中,双击Script
冒号和失败的证明尝试行):
Goal Instance of 'Pre-condition'
(call 'mmio_read32'):
Assume {
Type: is_uint32(offset_0).
(* Pre-condition *)
Have: (0 <= offset_0) /\ (offset_0 <= 4095).
}
Prove: (234881024 <= w) /\ (w_1 <= 234885119).
w
和w_1
对应于对addr
易失内容的两次读取访问。我不确定您是否真的打算将addr
参数设置为volatile
(而不是指向volatile
位置的非volatile
指针),因为这将需要一个非常奇怪的执行环境。
假设volatile
的声明中不应该包含addr
限定词,剩下的问题是offset
中对read32
的约束太弱了:应该以严格的不等式阅读offset < 0x1000
(或将mmio_read32
的先决条件设为非严格条件,但这再次很少见)。
关于ACSL中有关物理地址和易失性的最初问题(请参见the manual的2.12.1节),您具有一个特定的volatile
子句,可用于指定(C,通常为幻影)函数代表对volatile
位置的读写访问。不幸的是,目前只能通过非公开发行的插件来访问这些条款。
恐怕如果您想在具有物理地址的代码上使用WP,则确实确实需要使用编码(例如,使用适当大小的Ghost数组)和/或使用适当功能对易失性访问进行建模。