Value analysis module and extensions options - frama-c

I have some questions on options of value analysis module and some extensions options.
I use the command : frama-c-gui -val -slevel 100 -plevel 300 -absolute-valid-range 0x00000000-0xffffffff -metrics -metrics-value-cover -scope-def-interproc -main MYMAIN CODE/*.c
On a single file, -metrics give me 3 goto on a function without, how goto is compute ?
What is "Coverage estimation = 100.0%" with -metrics-value-cover I get a value between 80 and 100%, at the beginning I thought get <100% when I had dead code, but I had dead code when I get 100%, so I think get 100% if all functions in sources files are analysed ?
I suppose so 157 stmts in analyzed functions, 148 stmts analyzed (94.3%) that means I have dead code on my projet, it's that ?
With option -scope-def-interproc I get me 32 warning (62 without) but on website, we can read (in scope documentation)
The alarms emitted by the value analysis should therefore be examined carefully by the user.
So I need to verify all of 62 warning or just 32 got by this options ?

On a single file, -metrics [introduces] 3 goto on a function [that doesn't have any]
The C constructs &&, || and break; can be “normalized” into goto constructs.
I suppose so 157 stmts in analyzed functions, 148 stmts analyzed (94.3%) that means I have dead code on my projet, it's that ?
Yes. For the inputs visible to the value analysis, only 148 out of 157 statements are reachable. Note that if, for instance, main() has arguments argc and argv, the abstract values built for these arguments may not encompass all the values that should be considered. The best way to determine whether these 9 statements are really unreachable is to look at them (they are displayed in red in Frama-C's GUI).
With option -scope-def-interproc I get me 32 warning (62 without) but on website, we can read (in scope documentation)
It is not very clear what you are asking. It would help if you provided an example with full information (source code, commandline(s)) so that one can reproduce your steps and clarify the meaning of the emitted messages for you. Produce a small, reduced example if it is impossible to get the complete example out: it is also (nearly) impossible to answer you with the information provided so far.

What is "Coverage estimation = 100.0%" with -metrics-value-cover I get
a value between 80 and 100%, at the beginning I thought get <100% when
I had dead code, but I had dead code when I get 100%, so I think get
100% if all functions in sources files are analysed ?
Let's take an example.
[metrics] Value coverage statistics
=========================
Syntactically reachable functions = 3 (out of 3)
Semantically reached functions = 1
Coverage estimation = 33.3%
Unseen functions (2) =
<tests/metrics/reach.c>: baz; foo;
The first line, Syntactically reachable functions is an over-approximation of the number of functions of your program that may be eventually be called, starting from main. For example, a function whose address is never taken and which is never called directly won't be inside this set.
Semantically reached functions is the number of functions of your program indeed analyzed by the Value analysis.
Coverage estimation is the ratio between those two numbers. For small programs, in which all functions are reachable, it is usually 100%.
Unseen functions is the list of functions that were expected to be reached (syntactically), but were never analyzed by Value.
Notice that none of these numbers talk about instructions, so you may still get 100% with dead code.

Related

What’s the significance of the number “536870916” in computer science

I’ve noticed in many games there are a lot of errors regarding the number 536870916. For example, in one game that’s coded in Lua, the maximum number you can damage an enemy is 536870916, which is undocumented. I noticed other errors regarding this number when I googled it, for example:
“Random crash "Failed to allocate 536870916 bytes and will now terminate"”
Does anyone happen to know why this is?
There's nothing all that special about 536870916. It just happens to be very close to a power of 2: 229 = 536870912.
536870912 bytes is 512MiB, or 0.5GiB. It's a reasonable memory limit to configure for an application, so numbers going slightly above it are bound to appear in crash reports.
If you search numbers 536870912-536870916 on Google you'll see a diminishing number of results:
536870912: 47,500,000 results
536870913: 7,920,000 results
536870914: 36,300 results
536870915: 7,720 results
536870916: 8,380 results
Another source where you might see 536870916 is when numbers are used as bit sets to store flags. Sometimes error codes are stored like this. In binary, 536870916 has only 2 bits set, which makes it a union of two flags.

Product of range in Prolog

I need to write a program, which calculates product of product in range:
I written the following code:
mult(N,N,R,R).
mult(N,Nt,R,Rt):-N1=Nt+1,R1=Rt*(1/(log(Nt))),mult(N,N1,R,R1).
This should implement basic product from Nt to N of 1/ln(j). As far as I understand it's got to be stopped when Nt and N are equal. However, I can't get it working due to:
?- mult(10,2,R,1), write(R).
ERROR: Out of global stack
The following error. Is there any other way to implement loop not using default libraries of SWI-Prolog?
Your program never terminates! To see this consider the following failure-slice of your program:
mult(N,N,R,R) :- false.
mult(N,Nt,R,Rt):-
N1=Nt+1,
R1=Rt*(1/(log(Nt))),
mult(N,N1,R,R1), false.
This new program does never terminate, and thus the original program doesn't terminate. To see that this never terminates, consider the two (=)/2 goals. In the first, the new variable N1 is unified with something. This will always succeed. Similarly, the second goal with always succeed. There will never be a possibility for failure prior to the recursive goal. And thus, this program never terminates.
You need to add some goal, or to replace existing goals. in the visible part. Maybe add
N > Nt.
Further, it might be a good idea to replace the two (=)/2 goals by (is)/2. But this is not required for termination, strictly speaking.
Out of global stack means you entered a too-long chain of recursion, possibly an infinite one.
The problem stems from using = instead of is in your assignments.
mult(N,N,R,R).
mult(N,Nt,R,Rt):-N1 is Nt+1, R1 is Rt*(1/(log(Nt))), mult(N,N1,R,R1).
You might want to insert a cut in your first clause to avoid going on after getting an answer.
If you have a graphical debugger (like the one in SWI) try setting 'trace' and 'debug' on and running. You'll soon realize that performing N1 = Nt+1 giving Ntas 2 yields the term 2+1. Since 2+1+1+1+(...) will never unify with with 10, that's the problem right there.

Why is code unreachable in Frama-C Value Analysis?

When running Frama-C value analysis with some benchmarks, e.g. susan in http://www.eecs.umich.edu/mibench/automotive.tar.gz, we noticed that a lot of blocks are considered dead code or unreachable. However, in practice, these code is executed as we printed out some debug information from these blocks. Is there anybody noticed this issue? How can we solve this?
Your code has a peculiarity which is not in Pascal's list, and which explains some parts of the dead code. Quite a few functions are declared as such
f(int x, int y);
The return type is entirely missing. The C standard indicates that such functions should return int, and Frama-C follows this convention. When parsing those function, it indicates that they never return anything on some of their paths
Body of function f falls-through. Adding a return statement.
On top on the return statement, Frama-C also adds an /*# assert \false; annotation, to indicate that the execution paths of the functions that return nothing should be dead code. In your code, this annotation is always false: those functions are supposed to return void, and not int. You should correct your code with the good return type.
Occurrences of dead code in the results of Frama-C's value analysis boil down to two aspects, and even these two aspects are only a question of human intentions and are indistinguishable from the point of view of the analyzer.
Real bugs that occur with certainty everytime a particular statement is reached. For instance the code after y = 0; x = 100 / y; is unreachable because the program stops at the division everytime. Some bugs that should be run-time errors do not always stop execution, for instance, writing to an invalid address. Consider yourself lucky that they do in Frama-C's value analysis, not the other way round.
Lack of configuration of the analysis context, including not having provided an informative main() function that sets up variation ranges of the program's inputs with such built-in functions as Frama_C_interval(), missing library functions for which neither specifications nor replacement code are provided, assembly code inside the C program, missing option -absolute-valid-range when one would be appropriate, ...

arithmetic library for tracking worst case error

(edited)
Is there any library or tool that allows for knowing the maximum accumulated error in arithmetic operations?
For example if I make some iterative calculation ...
myVars = initialValues;
while (notEnded) {
myVars = updateMyVars(myVars)
}
... I want to know at the end not only the calculated values, but also the potential error (the range of posible values if results in each individual operations took the range limits for each operand).
I have already written a Java class called EADouble.java (EA for Error Accounting) which holds and updates the maximum positive and negative errors along with the calculated value, for some basic operations, but I'm afraid I might be reinventing an square wheel.
Any libraries/whatever in Java/whatever? Any suggestions?
Updated on July 11th: Examined existing libraries and added link to sample code.
As commented by fellows, there is the concept of Interval Arithmetic, and there was a previous question ( A good uncertainty (interval) arithmetic library? ) on the topic. There just a couple of small issues about my intent:
I care more about the "main" value than about the upper and lower bounds. However, to add that extra value to an open library should be straight-forward.
Accounting the error as an independent floating point might allow for a finer accuracy (e.g. for addition the upper bound would be incremented just half ULP instead of a whole ULP).
Libraries I had a look at:
ia_math (Java. Just would have to add the main value. My favourite so far)
Boost/numeric/Interval (C++, Very complex/complete)
ErrorProp (Java, accounts value, and error as standard deviation)
The sample code (TestEADouble.java) runs ok a ballistic simulation and a calculation of number e. However those are not very demanding scenarios.
probably way too late, but look at BIAS/Profil: http://www.ti3.tuhh.de/keil/profil/index_e.html
Pretty complete, simple, account for computer error, and if your errors are centered easy access to your nominal (through Mid(...)).

How do I detect circular logic or recursion in a custom expression evaluator?

I've written an experimental function evaluator that allows me to bind simple functions together such that when the variables change, all functions that rely on those variables (and the functions that rely on those functions, etc.) are updated simultaneously. The way I do this is instead of evaluating the function immediately as it's entered in, I store the function. Only when an output value is requested to I evaluate the function, and I evaluate it each and every time an output value is requested.
For example:
pi = 3.14159
rad = 5
area = pi * rad * rad
perim = 2 * pi * rad
I define 'pi' and 'rad' as variables (well, functions that return a constant), and 'area' and 'perim' as functions. Any time either 'pi' or 'rad' change, I expect the results of 'area' and 'perim' to change in kind. Likewise, if there were any functions depending on 'area' or 'perim', the results of those would change as well.
This is all working as expected. The problem here is when the user introduces recursion - either accidental or intentional. There is no logic in my grammar - it's simply an evaluator - so I can't provide the user with a way to 'break out' of recursion. I'd like to prevent it from happening at all, which means I need a way to detect it and declare the offending input as invalid.
For example:
a = b
b = c
c = a
Right now evaluating the last line results in a StackOverflowException (while the first two lines evaluate to '0' - an undeclared variable/function is equal to 0). What I would like to do is detect the circular logic situation and forbid the user from inputing such a statement. I want to do this regardless of how deep the circular logic is hidden, but I have no idea how to go about doing so.
Behind the scenes, by the way, input strings are converted to tokens via a simple scanner, then to an abstract syntax tree via a hand-written recursive descent parser, then the AST is evaluated. The language is C#, but I'm not looking for a code solution - logic alone will be fine.
Note: this is a personal project I'm using to learn about how parsers and compilers work, so it's not mission critical - however the knowledge I take away from this I do plan to put to work in real life at some point. Any help you guys can provide would be appreciated greatly. =)
Edit: In case anyone's curious, this post on my blog describes why I'm trying to learn this, and what I'm getting out of it.
I've had a similar problem to this in the past.
My solution was to push variable names onto a stack as I recursed through the expressions to check syntax, and pop them as I exited a recursion level.
Before I pushed each variable name onto the stack, I would check if it was already there.
If it was, then this was a circular reference.
I was even able to display the names of the variables in the circular reference chain (as they would be on the stack and could be popped off in sequence until I reached the offending name).
EDIT: Of course, this was for single formulae... For your problem, a cyclic graph of variable assignments would be the better way to go.
A solution (probably not the best) is to create a dependency graph.
Each time a function is added or changed, the dependency graph is checked for cylces.
This can be cut short. Each time a function is added, or changed, flag it. If the evaluation results in a call to the function that is flagged, you have a cycle.
Example:
a = b
flag a
eval b (not found)
unflag a
b = c
flag b
eval c (not found)
unflag b
c = a
flag c
eval a
eval b
eval c (flagged) -> Cycle, discard change to c!
unflag c
In reply to the comment on answer two:
(Sorry, just messed up my openid creation so I'll have to get the old stuff linked later...)
If you switch "flag" for "push" and "unflag" for "pop", it's pretty much the same thing :)
The only advantage of using the stack is the ease of which you can provide detailed information on the cycle, no matter what the depth. (Useful for error messages :) )
Andrew

Resources