Issue in generating paths in KLEE
karthiv opened this issue · comments
The program given here should generate 3 paths - it does so in klee web(http://klee.doc.ic.ac.uk/) but in klee installation (llvm-3.8 as well as current docker image) it generates only 2 paths and 2 testcases.
On analysing the path where k=10 is not being explored by klee.
However, if I uncomment the lines - printf-1,2,3 - It generates 3 paths.
Why the path k=10 not being explored in klee installation and docker image?
Program under test:
#include <klee/klee.h>
#include <stdio.h>
int main () {
int a,b;
klee_make_symbolic(&a, sizeof(a),"a");
klee_make_symbolic(&b, sizeof(b),"b");
int k=0;
if(a==b){
k=5;
//printf("%s","a==b"); //printf-1
if(a>5){
k=10;
//printf("%s","a>5"); // printf-2
}
}
//printf("%s","return"); //printf-3
printf("%d",k);
return 0;
}
When you comment out the printf
calls, the bitcode gets optimised and you end up with a different code structure.
In the optimised case the store to k
is handled solely via a select
instruction (single path in KLEE) without a br
anch:
if.then:
store i32 5, i32* %k
%7 = load i32, i32* %a
%cmp1 = icmp sgt i32 %7, 5
%spec.store.select = select i1 %cmp1, i32 10, i32 5 <--- here
store i32 %spec.store.select, i32* %k, align 4
br label %if.end3
whereas in the unoptimised case you get the expected br
anch and the assignment in two basic blocks:
if.then:
store i32 5, i32* %k, align 4 <--- here
%call = call i32 (i8*, ...) @printf(...)
%7 = load i32, i32* %a, align 4
%cmp1 = icmp sgt i32 %7, 5
br i1 %cmp1, label %if.then2, label %if.end4
if.then2:
store i32 10, i32* %k, align 4 <--- here
...
When you comment out the
printf
calls, the bitcode gets optimised and you end up with a different code structure.In the optimised case the store to
k
is handled solely via aselect
instruction (single path in KLEE) without abr
anch:if.then: store i32 5, i32* %k %7 = load i32, i32* %a %cmp1 = icmp sgt i32 %7, 5 %spec.store.select = select i1 %cmp1, i32 10, i32 5 <--- here store i32 %spec.store.select, i32* %k, align 4 br label %if.end3whereas in the unoptimised case you get the expected
br
anch and the assignment in two basic blocks:if.then: store i32 5, i32* %k, align 4 <--- here %call = call i32 (i8*, ...) @printf(...) %7 = load i32, i32* %a, align 4 %cmp1 = icmp sgt i32 %7, 5 br i1 %cmp1, label %if.then2, label %if.end4 if.then2: store i32 10, i32* %k, align 4 <--- here ...
Thank you for the answer. How to remove optimization in klee installed version and docker?
I printed the CFG, it does not optimize the code as you have mentioned . The assembly code generates is
`define i32 @main() #0 !dbg !4 {
%1 = alloca i32, align 4
%a = alloca i32, align 4
%b = alloca i32, align 4
%k = alloca i32, align 4
store i32 0, i32* %1, align 4
call void @llvm.dbg.declare(metadata i32* %a, metadata !11, metadata !12), !dbg !13
call void @llvm.dbg.declare(metadata i32* %b, metadata !14, metadata !12), !dbg !15
%2 = bitcast i32* %a to i8*, !dbg !16
call void @klee_make_symbolic(i8* %2, i64 4, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str, i32 0, i32 0)), !dbg !17
%3 = bitcast i32* %b to i8*, !dbg !18
call void @klee_make_symbolic(i8* %3, i64 4, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0)), !dbg !19
call void @llvm.dbg.declare(metadata i32* %k, metadata !20, metadata !12), !dbg !21
store i32 0, i32* %k, align 4, !dbg !21
%4 = load i32, i32* %a, align 4, !dbg !22
%5 = load i32, i32* %b, align 4, !dbg !24
%6 = icmp eq i32 %4, %5, !dbg !25
br i1 %6, label %7, label %10, !dbg !26
; :7 ; preds = %0
store i32 5, i32* %k, align 4, !dbg !27
%8 = load i32, i32* %a, align 4, !dbg !29
%9 = icmp sgt i32 %8, 5, !dbg !31
%. = select i1 %9, i32 10, i32 5, !dbg !32
store i32 %., i32* %k, align 4, !dbg !33
br label %10, !dbg !35
; :10 ; preds = %7, %0
ret i32 0, !dbg !36
}`
- I have attached screenshot here
I'm afraid you have to remove that line and recompile KLEE. KLEE runs some passes on the bitcode before execution. The final bitcode file can be found in klee-last/assembly.ll
and should show the differences I described above.
Edit: When you're using newer LLVM versions, it should be sufficient to compile your bitcode file with -O0
to annotate the functions with optnone
.
I'm afraid you have to remove that line and recompile KLEE. KLEE runs some passes on the bitcode before execution. The final bitcode file can be found in
klee-last/assembly.ll
and should show the differences I described above.Edit: When you're using newer LLVM versions, it should be sufficient to compile your bitcode file with
-O0
to annotate the functions withoptnone
.
Thank you! The issue is resolved
I added the following statement into the program under test and the results matched with klee web
#pragma clang optimize off
My LLVM version is 3.8 and Klee version is 2.1-pre
My LLVM version is 3.8 and Klee version is 2.1-pre
That LLVM version is almost 7 years old and even your KLEE version is really outdated. You might want to consider updating.