I am trying to build a simple version of a code analysis tool with LLVM.
I have a few .ll files which contain the intermediate LLVM representation of certain programs.
How can I get the list of function calls that are performed in each function of a program, from the intermediate representation of LLVM?
The input parameter I have is an instance of the LLVM: Module class which represents the program. Then, I get the list of functions present in the program with the function getFunctionList ().
void getFunctionCalls(const Module *M)
{
// Iterate functions in program
for (auto curFref = M->getFunctionList().begin(), endFref = M->getFunctionList().end();
curFref != endFref; ++curFref) {
// For each function
// Get list of function calls
}
}
A function call is an expression that passes control and arguments (if any) to a function and has the form: expression (expression-list opt) where expression is a function name or evaluates to a function address and expression-list is a list of expressions (separated by commas).
The only requirement in any function call is that the expression before the parentheses must evaluate to a function address. This means that a function can be called through any function-pointer expression. This example illustrates function calls called from a switch statement:
We have functions that are commonly used to manipulate lists. For example: len (), sum (), max (), range () and many more. We also have some functions that are not commonly used like any (), all (), etc.
You can find out all functions defined (but not necessarily called) in an application with the nm command, e.g. You can also use GDB to set a breakpoint on each function: Once you continue, you'll hit a breakpoint for each function called.
This is a fragment from our working code here:
for (auto &module : Ctx.getModules()) {
auto &functionList = module->getModule()->getFunctionList();
for (auto &function : functionList) {
for (auto &bb : function) {
for (auto &instruction : bb) {
if (CallInst *callInst = dyn_cast<CallInst>(&instruction)) {
if (Function *calledFunction = callInst->getCalledFunction()) {
if (calledFunction->getName().startswith("llvm.dbg.declare")) {
Also keep in mind that there are also invoke instructions InvokeInst
which may be obtained in a similar way.
Google CallInst vs InvokeInst
and also learn about the functions with or without a called function. If a function does not have a called function this is indirect call. Indirect calls appear in LLVM IR when the source code instead of calling a function directly, calls a function pointer. In C++ this often happens when some class operates through an abstract interface (polymorphism). So keep in mind that it is not 100% always possible to trace a called function even though you have a call instruction in place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With