Return Value of the CallInst - llvm

I need help with the llvm code to find the return value of the Call instruction and pass it as a parameter to another function.
I tried iterating the instruction to find the isa and callinst being the value itself i tried mapping it directly as a parameter but i am getting an error.
the following code of mine fails during runtime.
if(isa<CallInst>(I))
{
CallInst *ci = dyn_cast<CallInst>(&I);
IRBuilder<> builder(ci);
builder.SetInsertPoint(&B, builder.GetInsertPoint());
const DebugLoc Debug = I.getDebugLoc();
int x = Debug.getLine();
int y = Debug.getCol();
Value * rhs = ConstantInt::get(Type::getInt32Ty(F.getContext()),x, true);
Value * lhs = ConstantInt::get(Type::getInt32Ty(F.getContext()),y, true);;
Value *args1[3] = {rhs,lhs,ci};
builder.CreateCall(hook1, args1); //hook1 is the function in a runtime c program which accepts 3 parametes all int.
}
Error Message:
0x135eef8
Stack dump:
0. Program arguments: opt -load ../build/CBIInstrumentPass.so -CBIInstrument -S fuzz2.instrumented.ll -o fuzz2.cbi.instrumented.ll
1. Running pass 'Function Pass Manager' on module 'fuzz2.instrumented.ll'.
2. Running pass 'Instrumentations for CBI' on function '#xval'
/usr/lib/x86_64-linux-gnu/libLLVM-8.so.1(_ZN4llvm3sys15PrintStackTraceERNS_11raw_ostreamE+0x1f)[0x7f274917c4bf]
/usr/lib/x86_64-linux-gnu/libLLVM-8.so.1(_ZN4llvm3sys17RunSignalHandlersEv+0x50)[0x7f274917a910]
/usr/lib/x86_64-linux-gnu/libLLVM-8.so.1(+0x9728c8)[0x7f274917c8c8]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x128a0)[0x7f274c4698a0]
/usr/lib/x86_64-linux-gnu/libLLVM-8.so.1(_ZNK4llvm8DebugLoc7getLineEv+0x3)[0x7f2749219d43]
../build/CBIInstrumentPass.so(_ZN10instrument13CBIInstrument13runOnFunctionERN4llvm8FunctionE+0x66e)[0x7f2746c3fcaa]
/usr/lib/x86_64-linux-gnu/libLLVM-8.so.1(_ZN4llvm13FPPassManager13runOnFunctionERNS_8FunctionE+0x3f0)[0x7f274926f7f0]
/usr/lib/x86_64-linux-gnu/libLLVM-8.so.1(_ZN4llvm13FPPassManager11runOnModuleERNS_6ModuleE+0x33)[0x7f274926fa63]
/usr/lib/x86_64-linux-gnu/libLLVM-8.so.1(_ZN4llvm6legacy15PassManagerImpl3runERNS_6ModuleE+0x2ee)[0x7f274926fe2e]
opt(main+0x2cf8)[0x4bb7e8]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7f2747afbb97]
opt(_start+0x2a)[0x4a5efa]
Segmentation fault (core dumped)

Related

LLVM KaleidoscopeJIT: How to view errors?

I've been following the LLVM tutorial and I'm now trying to tweak & try extending things but I keep running into an error where code won't JIT & the compiler (the one I've made with LLVM) will abort with:
piler: /usr/lib/llvm-9/include/llvm/Support/Error.h:626: llvm::Expected<T>::storage_type* llvm::Expected<T>::getStorage() [with T = long unsigned int; llvm::Expected<T>::storage_type = long unsigned int]: Assertion `!HasError && "Cannot get value when an error exists!"' failed.
The assert is raised just after trying to get the address of the JIT-ted function:
reinterpret_cast<double (*)()>(expr_symbol.getAddress().get());
I really need to see what the error is to attempt to fix it but I can't figure out how to get or view it.
Solved this.
.getAddress() returns an llvm::Expected which wraps around the address, it can contain an error or the address if found.
To handle/log the error you must 'take' the error and log it with llvm::logAllUnhandledErrors
auto address = expr_symbol.getAddress();
if (auto err = address.takeError()) {
llvm::logAllUnhandledErrors(std::move(err), llvm::errs(), "[JIT Error] ");
return -1;
}

How to pass arguments to a function while GDB

I'm trying to use GDB to debug my C++ program.
I'm thinking if it's possible to pass arguments to a function while using GDB.
For example, I have such a program as below:
#include <iostream>
void func(int a)
{
std::cout << a << std::endl;
}
int main(int argc, char **argv)
{
func(2222);
return EXIT_SUCCESS;
}
I set a breakpoint at the line func(2222) in the function main. My question is: is it possible to set another argument to the function func, instead of 2222, while using GDB on this program?
You can change the value a inside the function func()).
For that you can use:
assign a = $value_you_want
Example
b func # set breakpoint
c # continue
assign a = 2 # breakpoint gets hit, change value from a = 222 to a = 2
Yes. You can evaluate expressions while debugging. You can use either call <expr> or print <expr>, but the expression must be known at the time of breakpoint.
In your example, you could do:
gdb ./test
(gdb) b main
...
(gdb) r
...
(gdb) call func(11)
11
More info about call/print: https://sourceware.org/gdb/onlinedocs/gdb/Calling.html
I don't think it's possible to change the value passed to the function before the call of func(2222). However, you are able to modify the values of the parameter after GDB has stepped into the function, before another code execution.
My favorite way to debug with GDB is within Visual Studio Code, it provides a GUI on top of all the GDB commands, and makes using advanced GDB debugging much easier. And you can set a new value for the variable simply by clicking on it. You can see an example below.

Workflow of LLVM and clang

I am just a beginner in LLVM, and (https://www.cs.cornell.edu/~asampson/blog/llvm.html) webpage along with the stack overflow, and my fellow researcher has helped me a lot.
I would first like to illustrate what I am trying to work on (the problem) and then I will describe the approach that I have taken to work on the problem.
Then, I need your advice and guidance if I am missing anything.
Work Problem
My input is a C program and output is its SSA form in prefix representation printed in an output File.
For eg, if the C code segment is :
x=4;
x++;
z=x+7;
The output SSA form in prefix representation is :
( = x0 4)
( = x1 (+ x0 1) )
( = z (x1 + 7) )
Please ignore the actual IR instruction for now, just assume that I am able to read the IR and convert it to this form, with some extra statements (which I am not presenting here for readability).
My ignorant Approach of using LLVM (Please find the complete program below)
using namespace llvm;
namespace {
struct TestPass: public ModulePass {
IRssa::ptr ir_ssa = IRssa::ptr(new IRssa());
static char ID;
typedef std::list<std::pair<std::string, std::list<Instruction *> > > funcDump;
TestPass() : ModulePass(ID) { }
std::map<std::string, funcDump> workingList;
bool runOnModule(Module &M) {
std::string funcName, bkName;
for (Function &F : M) { //Found a new Function
if (isa<Function>(F) && !(F.getName().startswith("llvm."))) {
funcName = F.getName();
std::pair<std::string, std::list<Instruction *> > funcBlockList;
std::list<std::pair<std::string, std::list<Instruction *> > > wholeFuncBlocks;
for (BasicBlock &B : F) { //Blocks of the Function
if (isa<BasicBlock>(B)) {
bkName = B.getName();
}
std::list<Instruction *> listInst;
for (auto &I : B) {
Instruction *ins;
ins = &I;
listInst.push_back(ins);
}
funcBlockList.first = bkName;
funcBlockList.second = listInst;
wholeFuncBlocks.push_back(funcBlockList);
}
workingList[funcName] = wholeFuncBlocks;//Mapping of the functions
}
}
ir_ssa->setFunctionDump(workingList);
funcDump funcData;
funcData = workingList["start_program"]; //Starting from the start_program function
convertFunctionToSSA(funcData, ir_ssa);
std::ofstream outFile;
outFile.open("Out.ssa");
printSSA_toFile(outFile, ir_ssa);
return false;
}
};
}
char TestPass::ID = 0;
static RegisterPass<TestPass> X("testPass", "Testing A Pass");
static void registerTestPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) {
PM.add(new TestPass());
}
static RegisterStandardPasses RegisterMyPass(PassManagerBuilder::EP_ModuleOptimizerEarly, registerTestPass);
static RegisterStandardPasses RegisterMyPass0(PassManagerBuilder::EP_EnabledOnOptLevel0, registerTestPass);
//Automatically enable the pass (http://adriansampson.net/blog/clangpass.html)
Description:
As shown above I am calling a runOnModule() and collecting all the IR Instructions of all the blocks for each function in the program into a workingList data structure (a std::map in this case). After all the functions in the given program is finished reading, I then do my required task of reading IR instructions one at a time, function by function and block by block (in the user defined function convertFunctionToSSA(funcData, ir_ssa) taking the whole function IR as argument and the result of processing these IR is returned in the argument ir_ssa). I am also printing the resulted value from ir_ssa onto the output file outFile.
Now How do I Run (I type the following)
clang -O1 -g -Xclang -emit-llvm -c someProgram.c -o test.bc
opt -O1 -instnamer -mem2reg -simplifycfg -loops -lcssa -loop-simplify -loop-rotate -loop-unroll -unroll-count=15 -unroll-allow-partial -load src/libTestPass.so -testPass test.bc -o test
My Expectation
I assume (as per my understanding) that the above two commands does the following.
First clang takes the program someProgram.c and generates IR as an output file "test.bc".
The next command opt, takes the file "test.bc" and then applies all the above passes one by one till the last pass "-unroll-allow-partial" and it also links my library libTestPass.so (this .so file is generated on compiling the above ModulePass program) then, finally the pass "-testPass" which I think is the pass where I am doing my process (of converting to SSA prefix representation).
Your Advice and Comments
I am not sure if LLVM is actually running in the sequence as I am assuming (My Expectation). Kindly comment if I am missing anything or if my assumption is not correct. Also please feel free to ask more details if necessary.
Current Problem Faced
I am able to successfully convert most of the C programs but on a specific program I stuck with some error. Debugging this error lead me to think that I am missing somethink or my assumption about this working of LLVM in regards to the calling order of clang and opt is not correct.
Your help is highly appreciated.

Memory corruption while setting value inside GMock Wrap function

I have a requirement wherein I need to mock a non-virtual function using GTest/GMock. So, I have wrapped that function and linked the same in the test suite "tst_def" file. For the wrapped function, an integer is passed by reference and when I set any value inside the wrapped function to this integer, the test suite "Crashes with memory corruption" during execution (Segmentation fault).
Important observation:
This crash doesn't occur when I set the same default value for that integer inside wrapped function as its assigned during its creation but crashes only when i assign any other value.
Edit:
Consider, value1 passed to this wrapper function has initial value of 0.
extern "C" {
int __wrap_function(int &value1)
{
value1 = 3; //crashes
value1 = 0; //didnt crash
return 0;
}
}

Replacing instructions in LLVM

I want to replace the call to malloc with call to cumemhostalloc function.
float *h_A=(float *)malloc(size);
should be replaced with
cuMemHostAlloc((void **)&h_A,size,2);
I use the following code for this,
*if (dyn_cast<CallInst> (j))
{
Ip=cast<Instruction>(j);
CastInst* ci_hp = new BitCastInst(ptr_h_A, PointerTy_23, "" );
BB->getInstList().insert(Ip,ci_hp);
errs()<<"\n Cast instruction is inserted"<<*ci_hp;
li_size = new LoadInst(al_size, "", false);
li_size->setAlignment(4);
BB->getInstList().insert(Ip,li_size);
errs()<<"\n Load instruction is inserted"<<*li_size;
ConstantInt* const_int32_34 = ConstantInt::get(M->getContext(), APInt(32, StringRef("2"), 10));
std::vector<Value*> cumemhaparams;
cumemhaparams.push_back(ci_hp);
cumemhaparams.push_back(li_size);
cumemhaparams.push_back(const_int32_34);
CallInst* cumemha = CallInst::Create(func_cuMemHostAlloc, cumemhaparams, "");
cumemha->setCallingConv(CallingConv::C);
cumemha->setTailCall(false);
AttrListPtr cumemha_PAL;
cumemha->setAttributes(cumemha_PAL);
ReplaceInstWithInst(callinst->getParent()->getInstList(), j,cumemha);*
}
But I get the following error,
/home/project/llvmfin/llvm-3.0.src/lib/VMCore/Value.cpp:287: void llvm::Value::replaceAllUsesWith(llvm::Value*): Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!"' failed.
Is it because the call to malloc is replaced with a function that has a different signature?
Almost. Call to malloc produce a value, your function - does not. So, you have to replace call with a load, not with another call
Also, looking into your code:
Do not play with instlists directly. Use IRBuilder + iterators instead
You can check for CallInst and declare var at the same time, no need to additional cast to Instruction.