C

列印執行時呼叫的函式的工具?

  • August 18, 2017

我正在尋找可以在任一 Unix/Linux 平台上實現的此類工具:

  1. 我有源文件,我自己編譯了應用程序(原始碼在 C 中,雖然我真的不認為這在這裡很重要)
  2. 我想在每個函式呼叫都列印/記錄到標準輸出/文件時執行這個應用程序

例如:

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

當我執行這個程序時,它會列印出來

  • 主要的
  • 正方形

我知道gdb在某種程度上可以做到這一點,或者valgrind但他們都沒有完全按照我的意願去做。我只是想知道這樣的工具是否存在?謝謝。

使用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

(其中數字是函式被呼叫的次數(我們跳過部分中從未呼叫過的函式$3 > 0awk)。

這通常用於程式碼覆蓋率(正在測試多少程式碼)。您還可以使用gprof程式碼分析工具(通常用於計算在程式碼的各個區域花費了多少時間):

$ 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

要讓執行檔在呼叫函式名時列印它們,在 GNU 系統上,您可以使用gcc-finstrument-functions選項並將dladdr()地址轉換為函式名。

創建一個instrument.c喜歡:

#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 : "?");
}

然後將您的執行檔編譯為:

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

(這裡使用 fd 3 轉儲函式名稱以使其與 stdout 和 stderr 流分開)。

dli_sname如果您只想要函式名稱,您可以調整程式碼以僅列印。

引用自:https://unix.stackexchange.com/questions/386747