Finding a shared library load address on Linux

At runtime, I need to print the address, and then find which function this address belongs to. Functions are in the shared library, so they do not have a fixed address. My map file, obviously, just shows the relative offsets for each function in the shared library. Is it possible at runtime to ask where the library was loaded so that I can subtract this value from my address in order to get the correct map file offset?

I'm currently doing a slightly hacky approach in which I also print out the address of one function in the library, and then find that function in the map file to find out where the download address should be. I would prefer to have a generic method that does not require you to call a reference function.

(GDB is not available in my setup). Thanks.

+7
source share
5 answers

In recent linux, you can use dl_iterate_phdr to find out the addresses of shared libraries.

+4
source

dladdr does it, end .:-)

More comprehensively, dladdr will take the address and determine which library and symbol it matches ... and then it will give you the library name, symbol name and base addresses of each of them. Personally, I find this elegant, it also eases my ongoing debugging work.

Hope this helps!

+7
source

Try looking at the / proc / [PID] / maps file. This should contain the library mapping address in the process memory address space.

If you want to reach the executable, use readelf in your library and find the offset of the .text section.

+3
source

GNU backtrace library ?

I would not rely on hacked approaches to something like that. I do not think that there is a guarantee that the contents of the libraries will be loaded into continuous memory.

+1
source

Check System V ABI, Chapter 5 . For the lazy, there is a standard way to do this for systems that support the binary ELF format:

 #include <link.h> off_t load_offset; for (Elf64_Dyn *dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) { if (dyn->d_tag == DT_DEBUG) { struct r_debug *r_debug = (struct r_debug *) dyn->d_un.d_ptr; struct link_map *link_map = r_debug->r_map; while (link_map) { if (strcmp(link_map->l_name, libname) == 0) { load_offset = (off_t)link_map->l_addr; break; } link_map = link_map->l_next; } break; } } 

It does not depend on the GNU extension.

On GNU systems, the ElfW (Dyn) macro returns either Elf64_Dyn or Elf32_Dyn, which is convenient.

+1
source

All Articles