I'm trying to write a function pass in LLVM that replaces
read(file_descriptor, buffer, size) with
klee_make_symbolic(buffer, size, name_of_symbol)
However, I'm running into some trouble while trying to re-use the arguments of the old function.
Running my function pass breaks the newly inserted function. Returning with an error:
Referring to an argument in another function!
call void #klee_make_symbolic(i8* %1, i64 %2, i8* getelementptr inbounds ([5 x i8], [5 x i8]* #0, i32 0, i32 0)), !dbg !27
LLVM ERROR: Broken function found, compilation aborted!
Here is the relevant part of my code:
llvm::CallInst *CI = llvm::dyn_cast<llvm::CallInst>(&*I);
llvm::Function *func(CI->getCalledFunction());
llvm::StringRef func_name(func->getName());
for(std::string s : mksym_func_list){
if(func_name.equals(s)){
tmp = I;
flag = true;
llvm::errs() << *I << "\n";
I++;
llvm::errs() << *I << "\n";
llvm::IRBuilder<> builder(&*I);
std::vector<llvm::Value*> args(3, NULL);
if(func_name == "read"){
int counter = 0;
for(auto arg = func->arg_begin(); arg != func->arg_end(); arg++){
if(counter == 1){
//args[0] = builder.CreateAdd(llvm::dyn_cast<llvm::Value>(arg), llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), 0, true));
args[0] = arg;
}else if(counter == 2){
//args[1] = builder.CreateAdd(llvm::dyn_cast<llvm::Value>(arg), llvm::ConstantInt::get(llvm::Type::getInt64Ty(context), 0, true));
args[1] = arg;
}
counter++;
}
llvm::Value *sym = builder.CreateGlobalStringPtr("test");
args[2] = sym;
llvm::errs() << "foge\n";
builder.CreateCall(func_mksym, args);
llvm::errs() << "unge\n";
llvm::errs() << "hage\n";
llvm::errs() << *I << "\n";
}
break;
}
}
}
if(!flag) I++; else flag = false;
}
I expect the read function to be replaced with klee_make_symbolic, but LLVM opt tool is returning with an error.
EDIT:
I have changed the code so that it iterates through operands instead of arguments. Now I am able to instrument the code but now the program itself crashes when the new function gets called.
The program works if I replace read with klee_make_symbolic by hand. But it still fails when I use a LLVM pass to do it.
I even checked the .ll files to confirm that there isn't anything wrong with it.
debug.ll:
store i8** %1, i8*** %5, align 8
call void #llvm.dbg.declare(metadata i8*** %5, metadata !16, metadata !DIExpression()), !dbg !17
call void #llvm.dbg.declare(metadata [4 x i8]* %6, metadata !18, metadata !DIExpression()), !dbg !22
%11 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i32 0, i32 0, !dbg !23
%12 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i32 0, i32 0, !dbg !24
%13 = call i64 #strlen(i8* %12) #4, !dbg !25
%14 = call i64 #read(i32 0, i8* %11, i64 %13), !dbg !26
call void #llvm.dbg.declare(metadata i32* %7, metadata !27, metadata !DIExpression()), !dbg !28
%15 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i64 0, i64 0, !dbg !29
debug_mksym.ll:
store i8** %1, i8*** %5, align 8
call void #llvm.dbg.declare(metadata i8*** %5, metadata !16, metadata !DIExpression()), !dbg !17
call void #llvm.dbg.declare(metadata [4 x i8]* %6, metadata !18, metadata !DIExpression()), !dbg !22
%11 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i32 0, i32 0, !dbg !23
call void #klee_make_symbolic(i8* %11, i64 4, i8* getelementptr inbounds ([5 x i8], [5 x i8]* #0, i32 0, i32 0)), !dbg !24
call void #llvm.dbg.declare(metadata i32* %7, metadata !25, metadata !DIExpression()), !dbg !24
%12 = getelementptr inbounds [4 x i8], [4 x i8]* %6, i64 0, i64 0, !dbg !26
output of klee:
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee -replay-path tests/debug/fprclap/debug-000.path tests/debug/obj/debug_symbolic.bc > tests/debug/fprclap/debug.out
KLEE: output directory is "/home/shinjitumala/E_DRIVE/TiTech/2019/undergraduate_research/CLAP/tests/debug/obj/klee-out-0"
KLEE: Using Z3 solver backend
KLEE: WARNING: undefined reference to function: printf
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x2a)[0x5634b57be61a]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4llvm3sys17RunSignalHandlersEv+0x3e)[0x5634b57bc70e]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(+0x145a859)[0x5634b57bc859]
/usr/lib/libpthread.so.0(+0x13d00)[0x7fa2ab2d7d00]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor4forkERNS_14ExecutionStateENS_3refINS_4ExprEEEb+0x1ce2)[0x5634b468e6a2]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor18executeInstructionERNS_14ExecutionStateEPNS_12KInstructionE+0x4867)[0x5634b4699317]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor3runERNS_14ExecutionStateE+0x9fe)[0x5634b46a180e]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_ZN4klee8Executor17runFunctionAsMainEPN4llvm8FunctionEiPPcS5_+0xa7a)[0x5634b46a25fa]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(main+0x2d0f)[0x5634b463b52f]
/usr/lib/libc.so.6(__libc_start_main+0xf3)[0x7fa2aac77ee3]
/home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee(_start+0x2e)[0x5634b467875e]
/bin/sh: 1 行: 20587 Segmentation fault (コアダンプ) /home/shinjitumala/E_DRIVE/TiTech/tools/klee/build-FPR/bin/klee -replay-path tests/debug/fprclap/debug-000.path tests/debug/obj/debug_symbolic.bc > tests/debug/fprclap/debug.out
make: *** [Makefile:46: fprclap] エラー 139
arg_* iterators iterate over Functions formal arguments. You actually want to iterate over CallInsts operands with value_op_begin()/value_op_end().
I want to use llvm.returnaddress.i8 in a pass for getting return value of a function.
After I execute ../llvm/bin/lli test_re.bc, I get
LLVM ERROR: Program used external function 'llvm.returnaddress.i8' which could not be resolved!
I don't know how to solve it. Is there any suggestion? Thanks!
The intrinsic is called llvm.returnaddress, not llvm.returnaddress.i8.
declare i8* #llvm.returnaddress(i32)
declare i32 #printf(i8*, ...)
#fmt = constant [20 x i8] c"Return address: %p\0a\00"
define i32 #main() {
%fmt = getelementptr [20 x i8], [20 x i8]* #fmt, i32 0, i32 0
%ra = call i8* #llvm.returnaddress(i32 0)
call i32 (i8*, ...) #printf(i8* %fmt, i8* %ra)
ret i32 0
}
(1) #str = private constant [13 x i8] c"Hello World\0A\00"
(2) define i32 #main(){
(3) %r2 = getelementptr [13 x i8]* #str, i32 0, i32 0
(4) ret i32 0
(5) }
I've got an error error in the line 3: expected comma after getelementptr's type. How to deal with it?
getelemtptr expects the type that you are indexing (without the pointer) as it's first argument. In your case that would be [13 x i8], so you probably want to do something like this:
%r2 = getelementptr [13 x i8], [13 x i8]* #str, i32 0, i32 0
Why does the LLVM pure interpreter performs differently from the JIT-enabled interpreter with respect of array constants? (LLVM 3.8.1)
I have the following code:
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128 :128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-macosx10.9.0"
%MyType = type { i8* }
define i32 #main(i32 %argc, i8** %argv) nounwind uwtable {
%const.arr = alloca [8 x i8], align 8
store [8 x i8] c"\D0\CFT\15\01\00\00\00", [8 x i8]* %const.arr
%1 = bitcast [8 x i8]* %const.arr to %MyType*
ret i32 0
}
If I compile this with llvm-as test.llvm and lli test.llvm.bc, I get no error.
On the other hand, If I hit lli -force-interpreter test.llvm.bc I get the following error:
LLVM ERROR: ERROR: Constant unimplemented for type: [8 x i8]
Inspecting the code, I don't see anything wrong with it. Why does it perform differently when I force the interpreter?
I'm trying to generate code to box and unbox values in my untyped language. For evaluating a simple integer literal 3, I generate:
define i64 #0() {
entry:
%value = alloca { i64, [10 x i8], <10 x i64> }
%boxptr = getelementptr inbounds { i64, [10 x i8], <10 x i64> }* %value, i32 0, i32 0
store i64 3, i64* %boxptr
%boxptr1 = getelementptr inbounds { i64, [10 x i8], <10 x i64> }* %value, i32 0, i32 0
%load = load i64* %boxptr1
ret i64 %load
}
Seems right, and lli evaluates it to 3, but Llvm_executionengine evaluates the function to 216172782113783808 (junk value). The code from my toplevel.ml looks like:
open Llvm_executionengine
let the_execution_engine = ExecutionEngine.create_interpreter the_module
let print_and_jit se =
let f = sexpr_matcher se in
let result = ExecutionEngine.run_function f [||] the_execution_engine in
print_string "Evaluated to ";
print_int (GenericValue.as_int result);
What's wrong with my interpreter?