Заставить Frama-c показывать зависимости даже от "мертвых веток"

Я использую версию frama-c Aluminium-20160502 и хочу выяснить зависимости в большой программе. При использовании опции -deps в командной строке я обнаружил, что некоторые зависимости отсутствуют. В частности, когда несколько условий объединяются в одно условие if, анализ зависимостей останавливается всякий раз, когда одно условие ложно. В этом примере здесь:

#include<stdio.h>
#include<stdbool.h>

/*Global variable definitions*/
bool A = true;
bool B = false;
bool C = true;
bool X;
bool Y;

bool res;


void main(){

        if (A && B && C) {
                res = X;
        }else res = Y;
}

когда я пытаюсь: frama-c -deps program.c

frama показывает следующие зависимости:

[из] ====== Зависимости вычислены ======

Эти зависимости сохраняются при завершении для выполнений, которые заканчиваются:

[from] Функция main: res ОТ A; B; Y

[из] ====== КОНЕЦ ЗАВИСИМОСТИ ======

поэтому он не достигает условия C, потому что уже B ложно.

Интересно, есть ли способ сказать frama для вычисления всех зависимостей, даже если условие не выполняется. Я попытался с опцией -slevel, но безрезультатно. Я знаю, что есть способ использовать интервал Frama_C_interval(0,1), но когда я использую его, переменная, использующая эту функцию, не отображается в зависимостях. Я хотел бы, чтобы X и Y зависели от A,B,C и res зависели от A,B,C,X,Y

Есть идеи?

1 ответ

Решение

Плагин From использует результаты плагина анализа значений. В вашем примере значения A а также B достаточно точны, что Значение может сделать вывод, что условие полностью определено (так как && оператор лениво оценивается, слева направо) до достижения C, следовательно C никогда не влияет на результат и, следовательно, не является зависимостью с точки зрения От.

К несчастью, Frama_C_interval нельзя использовать напрямую в глобальных инициализаторах:

user error: Call to Frama_C_interval in constant.

Вы можете, однако, использовать "хак" (не всегда лучшее решение, но работает здесь):

volatile bool nondet;
bool A = nondet;
bool B = nondet;
bool C = nondet;
...

Обратите внимание, что, потому что nondet является volatileкаждая переменная A, B а также C назначается другое недетерминированное значение.

В этом случае Value должен учитывать обе ветви условных выражений, и поэтому C становится зависимостью в вашем примере, так как возможно, что C будет прочитано во время исполнения main, Вы тогда будете иметь:

       These dependencies hold at termination for the executions that terminate:
[from] Function main:
  res FROM A; B; C; X; Y

Обратите внимание, что некоторые плагины требуют особой обработки при работе с переменными переменными, поэтому это не всегда лучшее решение.

Это, однако, имеет дело только с некоторыми видами зависимостей. Как упомянуто в главе 6 руководства пользователя Value Analysis, плагин From вычисляет функциональные, императивные и эксплуатационные зависимости. Они не включают косвенные зависимости управления, такие как X from A, B, C, как вы упоминаете. Для этого вам понадобится плагин PDG (График зависимостей программы), но в настоящее время он не имеет текстового вывода зависимостей. Ты можешь использовать -pdg вычислить это, а затем -pdg-dot <file> экспортировать граф зависимостей в формате dot (graphviz). Вот что я получу за ваш main функция (используя изменчивый хак, как упоминалось ранее):

PDG для основной функции

Наконец, в качестве примечания: -slevel в основном используется для повышения точности, но в вашем примере у вас уже есть слишком высокая точность (т. е. Value уже может сделать вывод, что C никогда не читается внутри main).

Другие вопросы по тегам