Search code examples
frama-c

Multiple function call, dependencies mix up


While working with Frama-C, i encountered some strange dependencies. These occur when functions are called multiple times and pointers are passed as parameters. The following code shows the problem broken down to the minimum:

int sourceA = 1, sourceB = 1;
int targetA, targetB;

int deref_ptr(int* ptr){
    return *ptr;
}

int main(int argc, char* argv[]){

    targetA = deref_ptr(&sourceA);
    targetB = deref_ptr(&sourceB);

    return 0;
}

Frama-C computes the following dependencies using the EVA plugin.

[kernel] Parsing test.c (with preprocessing)
[eva] Analyzing a complete application starting at main
[eva] Computing initial state
[eva] Initial state computed
[eva:initial-state] Values of globals at initialization
  sourceA ∈ {1}
  sourceB ∈ {1}
  targetA ∈ {0}
  targetB ∈ {0}
[eva] done for function main
[eva:summary] ====== ANALYSIS SUMMARY ======
  ----------------------------------------------------------------------------
  2 functions analyzed (out of 2): 100% coverage.
  In these functions, 6 statements reached (out of 6): 100% coverage.
  ----------------------------------------------------------------------------
  No errors or warnings raised during the analysis.
  ----------------------------------------------------------------------------
  0 alarms generated by the analysis.
  ----------------------------------------------------------------------------
  No logical properties have been reached by the analysis.
  ----------------------------------------------------------------------------
[from] Computing for function deref_ptr
[from] Done for function deref_ptr
[from] Computing for function main
[from] Done for function main
[from] ====== DEPENDENCIES COMPUTED ======
  These dependencies hold at termination for the executions that terminate:
[from] Function deref_ptr:
  \result FROM sourceA; sourceB; ptr
[from] Function main:
  targetA FROM sourceA; sourceB
  targetB FROM sourceA; sourceB
  \result FROM \nothing
[from] ====== END OF DEPENDENCIES ======

The dependencies of the main function are of interest here. The expectation was that targetA depends on sourceA and targetB depends on sourceB. But in addition Frama-C computes dependencies from the respective other call of the deref_ptr function. Can this behavior be influenced so that targetA only depends on sourceA (same for targetB and sourceB)?


Solution

  • It would have helped to have the exact command line with which you launched Frama-C. Judging from the result, this is probably frama-c -deps example.c, but please note that details on the options you used usually matter a lot.

    That said, -deps indeed merges information from all the calls of each function. If you look at frama-c -from-help, though, you'll notice that there is another option for computing dependencies: -calldeps, whose description is:

    force callsite-wise dependencies (opposite option is -no-calldeps)

    And indeed, frama-c -calldeps example.c gives you the desired result:

    [from] ====== DISPLAYING CALLWISE DEPENDENCIES ======
    [from] call to deref_ptr at example.c:10 (by main):
      \result FROM sourceA; ptr
    [from] call to deref_ptr at example.c:11 (by main):
      \result FROM sourceB; ptr
    [from] entry point:
      targetA FROM sourceA
      targetB FROM sourceB
      \result FROM \nothing
    [from] ====== END OF CALLWISE DEPENDENCIES ======