To trace the function entry/exit, you can recompile your code with the option -finstrument-functions so that each time a function is invoked, a __cyg_profile_func_enter() function is called, and __cyg_profile_func_exit() is called when the function returns.
You can implement those functions to trace the addresses on the called functions, and then use nm to convert the addresses into function names.
EDIT: etrace does all this: it provides the source code for the __cyg_profile_func_enter() and __cyg_profile_func_exit() and functions that write the addresses to a named pipe and a Perl and a Python script to read the addresses and do the actual tracing with the function names and indentation.
For GCC, you could build with profiling support, and then run the program. That will create the gmon.out file, which in turn will contain a (sort of) trace of the functions executed by the program.
That will not even come close to the utility or ease of use of hand-written trace printf()s, though.
Since you were asking about gcc. It has the option -finstrument-functions that allows you to execute arbitrary code before and after calls to functions.
make
./callstack
Stack dump:
(stack) 1 main.cpp void foo3(int, int), line 7
(stack) 2 main.cpp void foo2(int), line 12
(stack) 3 main.cpp void foo1(), line 17
(stack) 4 main.cpp int main(int32_t, char **), line 22
I know you don't want to add something to each function, but if it's as simple as changing { to {_ does that win you over? A bit of scripting can do this automatically - ping me if you need that. If this does work, then look at this small utility I put together - just a single header file to include and then you get nice portable tracing
If you don't want to modify all your printf() calls, I'd suggest doing something along those lines in a header file, and include it in all your C code files:
#ifndef DEBUG /* if not in debug mode, disable printf */
#ifdef printf
#undef printf
#define printf(format, ...)
#endif
#endif
What's cool with that is that you can also replace printf with a logging function of your own:
#define printf(format, ...) my_log_function( format, ##__VA_ARGS__ )
Notice that I use here a nice macro trick: variadic macro.
发布评论
评论(6)
要跟踪函数进入/退出,您可以使用选项
-finstrument-functions
以便每次调用函数时,调用__cyg_profile_func_enter()
函数,并在函数返回时调用__cyg_profile_func_exit()
。您可以实现这些函数来跟踪被调用函数的地址,然后使用 nm 将地址转换为函数名称。
编辑:etrace 完成这一切:它提供了源代码
__cyg_profile_func_enter()
和__cyg_profile_func_exit()
以及将地址写入命名管道的函数以及用于读取地址并执行操作的 Perl 和 Python 脚本使用函数名称和缩进进行实际跟踪。To trace the function entry/exit, you can recompile your code with the option
-finstrument-functions
so that each time a function is invoked, a__cyg_profile_func_enter()
function is called, and__cyg_profile_func_exit()
is called when the function returns.You can implement those functions to trace the addresses on the called functions, and then use nm to convert the addresses into function names.
EDIT: etrace does all this: it provides the source code for the
__cyg_profile_func_enter()
and__cyg_profile_func_exit()
and functions that write the addresses to a named pipe and a Perl and a Python script to read the addresses and do the actual tracing with the function names and indentation.对于 GCC,您可以使用分析支持进行构建,然后运行该程序。这将创建 gmon.out 文件,该文件又将包含程序执行的函数的(某种)跟踪。
不过,这甚至无法接近手写跟踪 printf() 的实用性或易用性。
For GCC, you could build with profiling support, and then run the program. That will create the
gmon.out
file, which in turn will contain a (sort of) trace of the functions executed by the program.That will not even come close to the utility or ease of use of hand-written trace printf()s, though.
既然你问的是 gcc。它具有选项
-finstrument-functions
,允许您在调用函数之前和之后执行任意代码。Since you were asking about gcc. It has the option
-finstrument-functions
that allows you to execute arbitrary code before and after calls to functions.使用 Log4cxx。
一旦您在配置文件中指定文件类型、文件名和文件大小,这将记录详细信息。
按照以下步骤运行示例程序。
USE Log4cxx.
This will log the details once you specify the file type,filename and file size in their configuration file.
Follow the steps to run the sample program.
我知道您不想为每个函数添加一些内容,但如果就像将 { 更改为 {_ 一样简单,这会赢得您的青睐吗?一些脚本可以自动完成此操作 - 如果您需要,请联系我。如果这确实有效,那么看看我放在一起的这个小实用程序 - 只需包含一个头文件,然后您就可以得到很好的便携式跟踪
https://github.com/goblinhack/callstack
例如:
随时调用 CALLSTACK_DUMP() 来转储当前的调用堆栈。
只要做
I know you don't want to add something to each function, but if it's as simple as changing { to {_ does that win you over? A bit of scripting can do this automatically - ping me if you need that. If this does work, then look at this small utility I put together - just a single header file to include and then you get nice portable tracing
https://github.com/goblinhack/callstack
e.g.:
Call CALLSTACK_DUMP() at any time to dump the current callstack.
Just do
如果您不想修改所有
printf()
调用,我建议您在头文件中按照这些方式执行某些操作,并将其包含在所有 C 代码文件中:这有什么好处您还可以用自己的日志记录函数替换 printf:
请注意,我在这里使用了一个很好的宏技巧:可变参数宏。
If you don't want to modify all your
printf()
calls, I'd suggest doing something along those lines in a header file, and include it in all your C code files:What's cool with that is that you can also replace printf with a logging function of your own:
Notice that I use here a nice macro trick: variadic macro.