获取linux可执行加载地址(__builtin_return_address和addr2line)

时间:2013-06-30 11:38:11

标签: c linux gcc backtrace

我正在编写一些代码来存储每个内存分配的回溯。然后我将这些列表写入文件以进行离线分析。在win32中,我使用_AddressOfReturnAddress,然后手动创建回溯。由于每次运行的地址都是随机的,因此我使用GetModuleInformationlpBaseOfDll来获取基址。这适用于没有FPO的x86,这对我来说已经足够了。然后,我使用win32 API加载PDB,将地址转换为函数名。

我如何在linux上执行此操作?我目前的方法是使用__builtin_return_address(x)addr2line离线来获得相同的结果。问题是每次运行时地址都是随机的,因此addr2line不理解它们。 __executable_start无效,因为每次运行都会返回相同的值。有没有办法在运行时获取我的可执行文件的基地址?

一次跑步给了我这个:

__executable_start: 0x8048000
backtrace:
0x9cce628
0x9cce2b8
0x9cce260
0x9cce1f8
0x9cce138
0x9cce0c8
0x9cce060
0x9cce008

接下来:

__executable_start: 0x8048000
backtrace:
0x8db6628
0x8db62b8
0x8db6260
0x8db61f8
0x8db6138
0x8db60c8
0x8db6060
0x8db6008

等等。

1 个答案:

答案 0 :(得分:1)

您可以使用Linux上的dl_iterate_phdr()来确定每个动态加载对象的加载地址:

#define _GNU_SOURCE
#include <stdio.h>
#include <link.h>

int callback(struct dl_phdr_info *info, size_t size, void *data)
{
    printf("%s @ %#lx\n", info->dlpi_name, (unsigned long)info->dlpi_addr);
    return 0;
}

int main()
{
    dl_iterate_phdr(&callback, NULL);
    return 0;
}