I want to visualize the relationship between function calls as an analysis of past software

Question: Question:

I am currently analyzing past software, but is there an application that lists function calls?

I made a call graph with doxygen, but it's too complicated to document.
I want to output with csv etc. (I hope it can be listed not only for csv)

fooa-> fob-> foc1
-> foc2

If it was a call
fooa, foob, foc1
,, foc2

I'm looking for software that outputs like Please tell me

Answer: Answer:

As mentioned in user29553's comment, I think cflow is good.
I tried to format the result into CSV.

[Example of formatting by awk (call_stack.sh)]

#!/bin/bash
while read file; do cflow ${file}; done | sed '
s/    /\t/g
s/) /)\t/
' | awk -F '\t' '
BEGIN{
        ##DELIMITER = "->"
        DELIMITER = ","
}
{
        num = NF;
        for(no = 1; no <= num; no++){
                if($no != ""){
                        if(!match($no, "^<")){
                                ga[no] = $no
                        }
                        else{
                                if(match($no, "recursive:")){
                                        ga[no-1] = ga[no-1] "*";
                                }
                                delete ga[no];
                                num -= 1;
                        }
                }
        }
        dlmt = ""
        call_stack = "";
        for(no = 1; no <= num; no++){
                call_stack = call_stack dlmt ga[no]
                dlmt = DELIMITER
        }
        printf("%s\n", call_stack);
}
'

[How to use]

find . -name "*.c" | ./call_stack.sh

【Execution result】
I marked the function with * because cflow will detect a simple recursive call.


func()
func(),printf()
func(),func2()
func(),n_sub()
func(),n_sub(),func3()
func(),n_sub(),printf()
func(),func()*
func2()
func2(),printf()
func2(),n_sub()
func2(),n_sub(),func3()
func2(),n_sub(),printf()
func2(),func()
func3()
func3(),printf()
func3(),func2()
func3(),n_sub()
func3(),n_sub(),printf()
main()
main(),printf()
main(),n_sub()
main(),n_sub(),printf()
main(),func()
main(),func2()

[Cflow output (reference)]

for file in *.c; do cflow  ${file}; done
func() <int func () at func.c:7> (R):
    printf()
    func2()
    n_sub() <int n_sub () at func.c:14>:
        func3()
        printf()
    func() <int func () at func.c:7> (recursive: see 1)
func2() <int func2 (void) at func2.c:7>:
    printf()
    n_sub() <int n_sub () at func2.c:13>:
        func3()
        printf()
    func()
func3() <int func3 () at func3.c:5>:
    printf()
    func2()
    n_sub() <int n_sub () at func3.c:11>:
        printf()
main() <int main (int argc, char *argv[]) at main.c:6>:
    printf()
    n_sub() <int n_sub () at main.c:13>:
        printf()
    func()
    func2()

[Tools used]

cflow (GNU cflow) 1.4
sed (GNU sed) 4.4
GNU bash, version 4.4.20 (1)-release (x86_64-pc-linux-gnu)
GNU Awk 4.1.4, API: 1.1 (GNU MPFR 4.0.1, GNU MP 6.1.2)

【bonus】

Clang's Python bindings make source analysis in C a lot easier.
* Cflow is easier if you just want to check the function call relationship.

Scroll to Top