
私はUnix / Linuxプラットフォームで次のことを行うためのツールを探しています。
- ソースファイルがあり、アプリケーションを直接コンパイルしました(ソースコードはCになっていますが、それは重要ではないと思います)。
- すべての関数呼び出しをstdout /ファイルに印刷/ログに記録してこのアプリケーションを実行したいと思います。
たとえば、
#include <stdio.h>
int square(int x) { return x*x; }
int main(void) {
square(2);
}
このプログラムを実行すると印刷されます。
- 基本
- 正方形
私はgdb
これをある程度行うことができることを理解しています。valgrind
そうでなければ、それらのどれも私が望むものを正しく実行しません。そのようなツールが存在するかどうか疑問に思います。ありがとうございます。
答え1
実行可能ファイルが呼び出されたときに関数名を印刷するには、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
関数名のみが必要な場合は、印刷用にのみコードを調整できます。
答え2
使用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 > 0
このセクションでは一度も呼び出されなかった関数はスキップされますawk
)。
これは通常、コードの適用範囲(テストされるコードの量)に使用されます。コード分析ツールを使用することもできます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