user408952
user408952

Reputation: 932

Get linux executable load address (__builtin_return_address and addr2line)

I'm writing some code that stores a backtrace for each memory allocation. I'm then writing a list of these to a file for offline analysis. In win32 I use _AddressOfReturnAddress and then manually create the backtrace. Since the address is random for each run I use GetModuleInformation and lpBaseOfDll to get the base address. This works great on x86 without FPO, which is good enough for me. I then load the PDB using win32 API to translate the address to function name.

How would I do this on linux? My current approach is to use __builtin_return_address(x) and addr2line offline to get the same result. The problem is that the addresses are randomized each run, so addr2line doesn't understand them. __executable_start didn't work as it returns the same value each run. Is there any way to get the base address of my executable in runtime?

One run gives me this:

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

And the next:

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

And so on.

Upvotes: 3

Views: 3431

Answers (1)

caf
caf

Reputation: 239011

You can use the dl_iterate_phdr() on Linux to determine the load address of each dynamically loaded object:

#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;
}

Upvotes: 2

Related Questions