这是我发现的解决方案的一个有趣提示。
gcc(和 llvm>=3.0)-pg
在编译时有一个选项,传统上用于 gprof 支持。当您使用此标志编译代码时,编译器会将对该函数的调用添加到mcount
每个函数定义的开头。您可以覆盖此函数,但您需要在汇编中执行此操作,否则mcount
您定义的函数将被调用,mcount
并且您将在调用之前快速耗尽堆栈空间main
。
这是一个小概念证明:
富.c:
int total_calls = 0;
void foo(int c) {
if (c > 0)
foo(c-1);
}
int main() {
foo(4);
printf("%d\n", total_calls);
}
foo.s:
.globl mcount
mcount:
movl _total_calls(%rip), %eax
addl $1, %eax
movl %eax, _total_calls(%rip)
ret
编译clang -pg foo.s foo.c -o foo
。结果:
$ ./foo
6
那是 1 main
, 4foo
和 1 printf
。
这是 clang 发出的 asm foo
:
_foo:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl %edi, -8(%rbp) ## 4-byte Spill
callq mcount
movl -8(%rbp), %edi ## 4-byte Reload
...