怎么通过__builtin_return_address获得调用函数的起始地址
时间: 2024-03-17 07:45:25 浏览: 163
通过`__builtin_return_address`函数获得的是调用者的返回地址,而不是调用函数的起始地址。但是,我们可以通过一些技巧和调试信息来获取调用函数的起始地址。
一种常用的方法是,在程序中使用`backtrace`函数获取当前函数调用栈的信息,并结合调试信息来定位调用函数的起始地址。`backtrace`函数可以获取当前线程的函数调用栈,并将调用栈信息存储到一个指针数组中。我们可以通过传递这个指针数组和数组大小给`backtrace_symbols`函数来获取每个调用栈帧的函数名和地址信息。这些信息可以通过解析调试符号表(debug symbol table)来得到具体的函数和行号等信息。
以下是一个示例代码:
```c++
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void print_trace()
{
void* trace[16];
char** messages = (char**)NULL;
int i, trace_size = 0;
trace_size = backtrace(trace, 16);
messages = backtrace_symbols(trace, trace_size);
for (i = 0; i < trace_size; ++i)
{
Dl_info info;
if (dladdr(trace[i], &info) && info.dli_sname)
{
printf("[backtrace] %s\n", info.dli_sname);
}
}
if (messages)
{
printf("[backtrace] backtrace symbols:\n");
for (i = 0; i < trace_size; ++i)
{
printf("[backtrace] %s\n", messages[i]);
}
}
free(messages);
}
void foo()
{
print_trace();
}
int main()
{
foo();
return 0;
}
```
在这个示例代码中,我们定义了一个`print_trace`函数来获取当前线程的调用栈信息。我们使用`backtrace`函数获取当前线程的调用栈信息,并使用`dladdr`函数来获取每个调用栈帧的函数信息。`dladdr`函数可以获取一个地址所属的动态链接库(shared library)信息和符号名信息。通过解析符号名信息,我们可以获取到调用函数的起始地址等信息。
需要注意的是,这个方法虽然可以得到调用函数的起始地址,但是它需要依赖于调试符号表等信息,可能会有一定的性能和可移植性问题。同时,由于调试符号表可能会被剔除或编译时关闭,因此这个方法不一定在所有环境下都可行。
阅读全文