Как заставить область памяти быть действительной в ACSL?
Я определяю доступ к устройству следующим образом
volatile struct mydevice * const dev = (struct mydevice *)MY_DEVICE_ADDRESS;
Я смоделировал доступ с помощью
@ volatile dev->somereg reads somereg_read writes somereg_write;
Теперь проблема в том, что когда я включаю проверки RTE, сгенерированные проверки достоверности не могут быть доказаны
/*@ assert rte: mem_access: \valid(dev->somereg); */
Есть ли способ аннотировать мой код так, чтобы MY_DEVICE_ADDRESS вплоть до MY_DEVICE_ADDRESS+sizeof(struct mydevice) считался действительным?
РЕДАКТИРОВАТЬ: Вот попытка, которая не работает
#include <stdint.h>
#define MY_DEVICE_ADDRESS (0x80000000)
struct mydevice {
uint32_t somereg;
uint32_t someotherreg;
};
volatile struct mydevice * const dev = (struct mydevice *)MY_DEVICE_ADDRESS;
/*@ axiomatic Physical_Memory {
axiom Dev: \valid((struct mydevice*)MY_DEVICE_ADDRESS);
} */
int main(int argc, const char *argv[]) {
//@ assert \valid(dev);
//@ assert \false;
return 0;
}
Бежать с
frama-c-wp -wp-rte -wp-init-const -wp-model Typed test.c
2 ответа
Я думаю, что единственный способ доказать утверждение - это поставить аксиоматический блок вида
/*@ axiomatic Physical_Memory {
axiom Dev: \valid((struct mydevice*)MY_DEVICE_ADDRESS);
// add more if you have other physical memory accesses
} */
Есть опция в ядре -absolute-valid-range <min-max>
чтобы указать, что разыменование указателя в данном интервале - это нормально, но только EVA может воспользоваться этим (боюсь, это слишком низкий уровень для моделей памяти WP).
Обратите внимание, что вы можете передать опцию -wp-init-const
WP, чтобы указать, что он должен добавить в своем контексте тот факт, что глобальный const
переменные всегда равны их начальному значению.
редактировать
Как уже упоминалось в комментариях, предложенная аксиома действительно несовместима с моделью памяти WP. Основная проблема заключается в том, что в указанной модели числовой адрес 0xnnnn
по-видимому, определяется как shift(global(0),0xnnnn)
, Как видно на примере $FRAMAC_SHARE/wp/ergo/Memory.mlw
, global(0)
имеет base
из 0
и так shift
(который изменяет только offset
). Определение valid_rw
накладывает строго положительный base
отсюда и противоречие.
Это должно быть исправлено на уровне WP. Тем не менее, есть несколько обходных путей в ожидании новой версии Frama-C:
- если вам не нужно писать в физическое местоположение, вы можете заменить
\valid
от\valid_read
в аксиоматическом. Значение\valid_read
в модели нетbase>0
требование, следовательно, аксиома не приведет к противоречию. - если вы можете позволить себе изменение источников, сделайте
dev
extern
декларация (или определениеdev
как равныйextern
декларацияabstract_dev
), и используйте абстрактную константу в аксиоме: таким образом, у вас не будет равенстваdev.base==0
в логической модели, устраняя противоречие. - наконец, вы можете исправить модель памяти в
$FRAMAC_SHARE/wp/ergo/Memory.mlw
(а также$FRAMAC_SHARE/wp/why3/Memory.why
а также$FRAMAC_SHARE/wp/coq/Memory.v
в зависимости от вашего выбора пруверов). Самый простой способ сделать это, вероятно, сделатьglobal
полагаться на абстрактную базу, как в:
логика global_base: int функция global(b: int): addr = { base = global_base + b; смещение = 0}
(Обратите внимание, что этот ответ никоим образом не гарантирует, что это не приведет к появлению других проблем в модели).
Не то чтобы я знал (я тоже много пробовал).
Единственный обходной путь, который я нашел:
struct mydevice MY_DEVICE_STRUCT;
volatile struct mydevice * const dev = & MY_DEVICE_STRUCT;
Вам нужно "создать экземпляр" памяти, потому что именно этого ожидает базовый LLVM. Наверняка было бы неплохо форсировать это через нотацию ACSL.