4

I am looking for such kind of a tool on either Unix/Linux platform which can achieve:

  1. I have the source files and I compiled the application myself (the source code is in C, although I don't really think it matters here)
  2. I want to run this application while every function calls are printed/logged to a stdout/file

For example:

#include <stdio.h>
int square(int x) { return x*x; }
int main(void) {
    square(2);
}

And when I run this program it will print out

  • main
  • square

I understand that gdb can do this to some extent, or valgrind but they all do not do exactly what I want. I am just wondering if such a tool exist? Thanks.

1

2 Answers 2

9

To have the executable print the function names as they are being called, on a GNU system, you can use gcc's -finstrument-functions option and dladdr() to translate addresses to function names.

Create a instrument.c like:

#define _GNU_SOURCE
#include <dlfcn.h>

#include <stdlib.h>
#include <stdio.h>

#define TRACE_FD 3

void __cyg_profile_func_enter (void *, void *)
   __attribute__((no_instrument_function));

void __cyg_profile_func_enter (void *func,  void *caller)
{
  static FILE* trace = NULL;
  Dl_info info;

  if (trace == NULL) {
    trace = fdopen(TRACE_FD, "w");
    if (trace == NULL) abort();
    setbuf(trace, NULL);
  }
  if (dladdr(func, &info))
    fprintf (trace, "%p [%s] %s\n",
             func,
             info.dli_fname ? info.dli_fname : "?",
             info.dli_sname ? info.dli_sname : "?");
}

And then compile your executable as:

$ gcc -O0 -rdynamic -finstrument-functions square.c instrument.c -ldl
$ ./a.out 3>&1
0x400a8f [./a.out] main
0x400a4f [./a.out] square

(here using fd 3 to dump the function names to keep it separate from the stdout and stderr streams).

You can adapt the code to only print the dli_sname if you only want the function name.

1
  • This resembles DTrace a little bit I think. I will definitely give it a try.
    – Boyu Fang
    Aug 18, 2017 at 10:48
6

Using gcov:

$ gcc -O0 --coverage square.c
$ ./a.out
$ gcov -i square.c
$ awk -F '[,:]' '$1 == "function" && $3 > 0 {print $3, $4}' square.c.gcov
1 square
1 main

(where the number is the number of times the function was called (we skip the ones that are never called with $3 > 0 in the awk part)).

That's typically used for code coverage (how much of the code is being tested). You could also use the gprof code profiling tool (typically used to figure out how much time is spent in various areas of the code):

$ gcc -O0 -pg square.c
$ ./a.out
$ gprof -b -P
            Call graph


granularity: each sample hit covers 2 byte(s) no time propagated

index % time    self  children    called     name
        0.00    0.00       1/1           main [7]
[1]      0.0    0.00    0.00       1         square [1]
-----------------------------------------------

Index by function name

   [1] square

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .