LLVM:如何修复“引用另一个函数中的参数”

时间:2019-07-19 12:45:07

标签: c++ function arguments llvm

我正在尝试在LLVM中编写一个替换函数的函数

read(file_descriptor, buffer, size)

klee_make_symbolic(buffer, size, name_of_symbol)

但是,在尝试重用旧函数的参数时遇到了麻烦。

运行我的函数传递会中断新插入的函数。返回错误:

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!

这是我的代码的相关部分:

                    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;
            }

我希望将read函数替换为klee_make_symbolic,但是LLVM opt工具返回错误。

编辑:

我更改了代码,以使其遍历操作数而不是参数。现在,我可以检测代码了,但是现在当调用新函数时,程序本身崩溃了。

如果我用手将read替换为klee_make_symbolic,该程序将起作用。但是当我使用LLVM传递来完成它时,它仍然失败。

我什至检查了.ll文件以确认它没有任何问题。

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

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

1 个答案:

答案 0 :(得分:1)

arg_*迭代器迭代Function的形式参数。实际上,您实际上想使用CallInst / value_op_begin()value_op_end()的操作数进行迭代。