1

我想使用 gcc 选项 -finstrument-functions 获取程序的函数调用堆栈。

典型代码

void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));
void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function));
int depth = -1;

void __cyg_profile_func_enter (void *func,  void *caller)
{    }

void __cyg_profile_func_exit (void *func, void *caller)
{    }

int main()
{
printf("Hello world");
return 0
}

用 gcc -finstrument-functions test.c 编译它

运行./a.out,一切正常。

但是当我使用 g++ 时,我得到了对 __cyg_profile_func_enter 函数的未定义引用。我读到它的发生是因为 _cyg 函数是 C 代码的一部分,如果我想在 C++ 中使用它们,我应该使用 extern "C",所以有最终代码。

extern "C"{
void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));
void __cyg_profile_func_exit (void *, void *) __attribute__((no_instrument_function));
int depth = -1;

void __cyg_profile_func_enter (void *func,  void *caller)
{    }

void __cyg_profile_func_exit (void *func, void *caller)
{    }
}
int main()
{
printf("Hello world");
return 0
}

它使用 g++ -finstrument-functions test.c 编译,然后尝试执行它但得到 Core dumped 错误消息。我用 gdb 跟踪转储,__cyg_profile_func_enter() 中存在分段错误。

GCC 版本是 2.95.4。我还在 4.4.3 上对其进行了测试,一切正常。那么使用 2.95.4 gcc 是否可以解决这个问题?

4

2 回答 2

4

gcc 2.95.4 已经超过十年了。我已经设法挖出一个......并编译你的东西。它显然无法识别__attribute__((no_instrument_function)),因为生成的汇编代码有:

__cyg_profile_func_enter:
.LFB1:
        pushl %ebp
.LCFI0:
        movl %esp,%ebp
.LCFI1:
        subl $8,%esp
.LCFI2:
        movl 4(%ebp),%eax
        addl $-8,%esp
        pushl %eax
        pushl $__cyg_profile_func_enter
.LCFI3:
        call __cyg_profile_func_enter
        movl 4(%ebp),%eax
        addl $16,%esp
        addl $-8,%esp
        pushl %eax
        pushl $__cyg_profile_func_enter
        call __cyg_profile_func_exit
        movl %ebp,%esp
        popl %ebp
        ret
所以它递归地调用自己,当然以堆栈溢出结束。

如果你真的需要两个 gcc 2.95.x(面对天堂,翻白眼,脸上畏缩,“为什么哦为什么???”)然后 -finstrument-functions你必须让它们“真正extern” - 即把它们放在一个单独的源文件中您在没有选项的情况下编译它,然后在稍后链接它。

于 2012-09-21T10:57:38.183 回答
3

即使使用 gcc 4.4.3,no_instrument_functions 也不能在所有情况下正常工作。如果一个函数是内联的,那么即使它设置了 no_instrument_functions 属性,也会将检测调用添加到它。甚至 -finstrument-functions-exclude-file-list 也不起作用。

让它可靠工作的唯一方法是将跟踪代码放入另一个文件并在没有 -finstrument-functions 的情况下编译该文件。

于 2012-12-28T15:33:21.310 回答