Is there a way to find all the functions used in a c program?

2k views Asked by At

I have the source code for a huge (exaggerated) c program with multiple files. I was hoping if there was any way to find all the functions (both standard and builtin) used (both declared and called) in the program. I know I can compile it and track the function and system calls using tools like ltrace and strace, by redirecting the output to a file first and then using grep to select the function calls. Or I can use regex on shell on all the files, but I don't know regex (yet). So does any one know a tool that could help me to quickly find all the functions called and declared in a c program?

3

There are 3 answers

5
David Ranieri On BEST ANSWER

Check if this helps, comments in code:

#!/bin/bash

# For each .c in the current path (recursive)
for f in $(find . -name '*.c'); do
    # Extract the functions and his location with aux-info
    # Send the results to output.info
    # Send errors to /dev/null
    gcc -aux-info output.info $f 2>/dev/null
    # Extract function names from output.info excluding std headers and comments
    grep -Ev "/usr|compiled from" output.info
done
# Remove output.info
rm output.info

Since it seems that you are trying to extract your own code following a pattern: type function(params), you can avoid using gcc -aux-info, try the following:

#!/bin/bash

# For each .c in the current path (recursive)
for f in $(find . -name '*.c'); do
    # Extract the lines starting with a letter or underscore
    #                 and ending with ')' or '{' or '}' ignoring trailing spaces
    grep --with-filename --line-number --color '^[a-z|A-Z|_].*[)|{|} ]$' $f
done

Another way combining readelf and awk, notice that in this case you need to provide the name of the program/binary instead of the source files:

# Column 3 != 0 and Column 4 = "FUNC" and Column 8 not starting with _
readelf -sW your_program | awk '$3 != 0 && $4 == "FUNC" && $8 !~ /^ ?_/ {print $8}'
3
EHM On

@David, gave me a good answer, but after learning for loops in bash I came up with a method that is a little cleaner as far as messages are concerned. And the best thing about this method is that it scans the file statically which means even if some functions are assigned to a pointer as @joseph pointed you will be able to see a list of all the function calls made. The out put of this program isn't as clean as it could be as I don't know much regex, so if any one knows a better way don't forget to clean it up,

#!/bin/bash

#go through each .c file in the directory
for f in $(find . -maxdepth 1 -name "*.c");do
    #print the name of the file
    echo "$f"
    #print the content of the file
    #and then choose the lines that contain function calls
    cat -n $f|grep -v "if\|else\|for\|while\|return"| grep --color=always "_*(\|[[:alpha:]]*("

done
1
Joseph Sible-Reinstate Monica On

Because of function pointers, no, there's not. Consider this program:

#include <dlfcn.h>

int main(int argc, char **argv) {
    void *handle = dlopen(argv[1], RTLD_LAZY);
    void (*f)(void) = dlsym(handle, argv[2]);
    f();
    dlclose(handle);
}

It should be obvious that you can't possibly hope to make a list of all the functions that it can call.