【问题标题】:Get linux executable load address (__builtin_return_address and addr2line)获取 linux 可执行文件加载地址(__builtin_return_address 和 addr2line)
【发布时间】:2013-06-30 11:38:11
【问题描述】:

我正在编写一些代码来存储每个内存分配的回溯。然后,我将这些列表写入文件以进行离线分析。在 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

等等。

【问题讨论】:

  • 我以为只有堆栈和数据段有随机地址——文本段应该有一个固定地址,实际上你可以用objdump 看到。无关紧要,你看过像“unwind”这样的库吗?
  • 我采样了更多地址,我认为只有那些指向动态加载的库的地址才会随机化,这更有意义。我刚刚打印了第一个,这可能来自 c++ lib。其他地址似乎与objdump__executable_start 的基地址匹配。
  • 是的,共享库是可重定位的,所以它们的地址也很可能是随机的。

标签: c linux gcc backtrace


【解决方案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;
}

【讨论】:

    猜你喜欢
    • 2020-05-06
    • 2013-04-01
    • 1970-01-01
    • 2012-10-17
    • 2011-11-14
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    相关资源
    最近更新 更多