[LLVMdev] Adding function call in LLVM IR using IRBuilder causes assertion error

1,992 views
Skip to first unread message

Marc Claesen

unread,
Nov 11, 2009, 10:22:56 AM11/11/09
to llv...@cs.uiuc.edu
Hi,

I'm trying to add function calls in the LLVM IR using the IRBuilder
class. I've read both tutorials about functions but I still get
assertion errors. I allocate memory for all function arguments and pass
them as explained in the tutorial.

My code is (this function is supposed to add a call to f in bb at pos):
void addCallSite(Function *f, BasicBlock *bb, BasicBlock::iterator pos) {
std::vector<Value*> args;
IRBuilder<> builder(bb,pos);
for(Function::arg_iterator argit =
f->arg_begin();argit!=f->arg_end();argit++){
AllocaInst* allocInst = builder.CreateAlloca(argit->getType());
args.push_back(allocInst);
}
builder.CreateCall(f,args.begin(),args.end());
}

This seems to work for functions without parameters (eg. int foo()), but
once a function has a parameter I get the following assertion error:
<llvmpath>/lib/VMCore/Instructions.cpp:297: void
llvm::CallInst::init(llvm::Value*, llvm::Value* const*, unsigned int):
Assertion `(i >= FTy->getNumParams() || FTy->getParamType(i) ==
Params[i]->getType()) && "Calling a function with a bad signature!"' failed.

I've checked everything I can think of and it all seems correct to me
... Any help would be greatly appreciated!

Thanks in advance,

Marc Claesen
_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

Jeffrey Yasskin

unread,
Nov 11, 2009, 11:05:13 AM11/11/09
to Marc Claesen, llv...@cs.uiuc.edu
CreateAlloca(Type) returns an object of type Type*, the memory that
can hold an object of type Type. You probably don't want to be
creating allocas just before calling the function since 1) if that
call winds up in a loop they'll grow your stack frame without bound,
and 2) the memory they point to is initially uninitialized. Where did
the tutorial tell you to do that?

In general, when I hit one of those assertions, I gdb to it, use "p
f->dump()" to see the types of the function's arguments, and use "p
Params[i]->dump()" to see the parameter with the bad type.

Marc Claesen

unread,
Nov 11, 2009, 12:19:07 PM11/11/09
to Jeffrey Yasskin, llv...@cs.uiuc.edu
> CreateAlloca(Type) returns an object of type Type*, the memory that
> can hold an object of type Type. You probably don't want to be
> creating allocas just before calling the function since 1) if that
> call winds up in a loop they'll grow your stack frame without bound,
> and 2) the memory they point to is initially uninitialized. Where did
> the tutorial tell you to do that?

I used CreateAllocA(Type) because I assumed that was the correct way to
create a variable of a given type.

What I'm trying to do is create new variables of the types required by a
function and then call the function, so it's quite simple ... I just
don't know how to initialise correctly by the looks of it. What function
should I use if not CreateAllocA(Type)?

Thanks in advance,

Marc

Óscar Fuentes

unread,
Nov 11, 2009, 12:38:14 PM11/11/09
to llv...@cs.uiuc.edu
Marc Claesen <clae...@gmail.com> writes:

> I'm trying to add function calls in the LLVM IR using the IRBuilder
> class. I've read both tutorials about functions but I still get
> assertion errors. I allocate memory for all function arguments and pass
> them as explained in the tutorial.
>
> My code is (this function is supposed to add a call to f in bb at pos):
> void addCallSite(Function *f, BasicBlock *bb, BasicBlock::iterator pos) {
> std::vector<Value*> args;
> IRBuilder<> builder(bb,pos);
> for(Function::arg_iterator argit =
> f->arg_begin();argit!=f->arg_end();argit++){
> AllocaInst* allocInst = builder.CreateAlloca(argit->getType());
> args.push_back(allocInst);
> }
> builder.CreateCall(f,args.begin(),args.end());
> }
>
> This seems to work for functions without parameters (eg. int foo()), but
> once a function has a parameter I get the following assertion error:
> <llvmpath>/lib/VMCore/Instructions.cpp:297: void
> llvm::CallInst::init(llvm::Value*, llvm::Value* const*, unsigned int):
> Assertion `(i >= FTy->getNumParams() || FTy->getParamType(i) ==
> Params[i]->getType()) && "Calling a function with a bad signature!"' failed.

CreateAlloca(someType) returns an AllocaInst* which has type
someType*. So if your function takes a parameter of type int, with this
chunk of code

AllocaInst* allocInst = builder.CreateAlloca(argit->getType());
args.push_back(allocInst);

you are passing an int*. This triggers the assert.

For now, forget about the allocas.

Another issue is that I don't see in your code the _values_ you want to
pass to the called function. Apparently you already have the function
declaration (Function *f) but you are creating a call to that function,
and you need the actual arguments (not the argument types):

inf foo(int); // declaration. you already have this elsewhere.

foo(10); // call. you need the value (10) to pass to the function.

--
Óscar

Óscar Fuentes

unread,
Nov 11, 2009, 1:43:59 PM11/11/09
to Marc Claesen, llv...@cs.uiuc.edu
[Please use Reply to All for sending your message to the ml too]

Marc Claesen <clae...@gmail.com> writes:

>> Another issue is that I don't see in your code the _values_ you want to
>> pass to the called function. Apparently you already have the function
>> declaration (Function *f) but you are creating a call to that function,
>> and you need the actual arguments (not the argument types):
>

> That's exactly the problem. I'm trying to initialise values of the
> appropriate types as required by a given function and pass those. What
> I'm looking for is the appropriate instructions to initialise a
> variable of a given type to it's type's default value. I realise this
> program will generate useless function calls but it's part of a binary
> obfuscation chain.

In LLVM there is no such a thing as a type default value. Maybe that
concept exists on your language.

Creating allocas is not the solution, as the alloca is just
uninitialized space on the stack.

Suppossing that the function parameters simple enough, like integral or
floating point types, and the "default value" is zero, something like
this will do (untested):

std::vector<Value*> args;
IRBuilder<> builder(bb,pos);
for(Function::arg_iterator argit =
f->arg_begin();argit!=f->arg_end();
argit++)
{

Value *arg = Constant::getNullValue(argit->getType());
args.push_back(arg);
}
builder.CreateCall(f,args.begin(),args.end());

If your arguments are something more fancy, you have more work ahead
(for following the platform/language ABI, etc).

Reply all
Reply to author
Forward
0 new messages