Reputation: 537
I am writing a LLVM pass that need to get the values passed to the declared function and say print it out. Please note the declared function is getting invoked in LLVM IR.
I have written a module pass to iterate over all the instructions in the program. A snippet to get the arguments of the called function in the instruction is as follows:
for (auto &B: F){
for (auto &I: B){
if (auto *InvokeI = dyn_cast <InvokeInst>(&I)) {
if (InvokeI->getCalledFunction()->getName().str() == "function_name") {
errs() << "===\n";
errs() << *(InvokeI->getOperand(0)) <<"\n";
errs() << *(InvokeI->getOperand(1)) <<"\n";
errs() << *(InvokeI->getOperand(2)) <<"\n";
}
}
}
}
However if the LLVM IR for the function getting called looks something like this:
invoke void @function_name(i8* %4, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #5
to label %36 unwind label %6
then my above code snippet outputs:
%4 = call i8* @__cxa_allocate_exception(i64 4) #2
i8* bitcast (i8** @_ZTIi to i8*)
i8* null
Instead of outputing actual value that is being passed during the function call.
My question is how do we get the values that is being passed during the runtime. Is there a way we can add a function body to declared functions that returns nothing?
Any help on this is appreciated, Thanks
Upvotes: 5
Views: 1389
Reputation: 2329
Exceptions change the control flow of the program in order to provide their facilities during program execution. As a runtime construct that manipulates the program stack, performs cleanups, etc., it relies on a runtime system support to perform its duties. For that reason there is an ABI standard that standardizes aspects of how this is to be put to action across implementations.
Having said that, if you dig into that spec you'll see that the arguments to __cxa_throw
are what it is thrown. Have a look here. The above fragment contains the pointer to the location of the allocated exception along with type information. Indeed if you apply c++filt
on _ZTIi
, you get typeinfo for int
.
In other words, the integer 1
that was thrown by the statement throw 1
is wrapped into an exception object (i.e. memory location) to be accessed during runtime. Further specific details on where and how those values are stored are in the aforementioned spec. I don't see a straightforward way of accessing that specific values statically, since what exceptions might be active and with what exact contents relies on the state of the program during execution (e.g. call stack, etc).
Upvotes: 1