Finding address of variable in shared library

2019-09-24 06:14发布

问题:

I would like to find the address in the .so file of a variable. I do not know the name of if, I only know that it is an integer, and I know the value of it. I also know that once the library is loaded and linked by the dynamic linker the address in the memory is 0x6416A0 relative to the library address. This offset is larger than the size of the dynamic library itself. I only have the binary, compiled version of the library.

To find the address of the variable in the .so file I looked at it using objdump:

$ objdump -x /path/to/lib.so
Program Header:
LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**21
     filesz 0x0000000000505fa9 memsz 0x0000000000505fa9 flags r-x
LOAD off    0x0000000000506000 vaddr 0x0000000000706000 paddr 0x0000000000706000 align 2**21
     filesz 0x00000000000db8f0 memsz 0x00000000001764c0 flags rw-
DYNAMIC off    0x00000000005210b0 vaddr 0x00000000007210b0 paddr 0x00000000007210b0 align 2**3
     filesz 0x00000000000003e0 memsz 0x00000000000003e0 flags rw-
EH_FRAME off    0x0000000000476898 vaddr 0x0000000000476898 paddr 0x0000000000476898 align 2**2
     filesz 0x0000000000014674 memsz 0x0000000000014674 flags r--
STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3
     filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
[...]

Above I only showed the Program Header, but the address I am looking for is not in any address range of the available sections. As you see, addresses used are as large as 0x7210b0, but my address is not in any of the ranges I see.

Since the linker uses mmap to load the contents of the .so file, I assumed that knowing the offset in the memory is equivalent to knowing the offset in the file. Apparently this is wrong. Could anyone help me understand how that works? Is there a simple way to map the memory address onto the file address?

回答1:

If you are on a Linux system with a GNU libc, and if the variable is a known name inside the dynamic symbol table of some dynamically linked library, i.e. ELF shared object, and if you can change the code of the main program (or some shared object dynamically linked by it, perhaps playing LD_PRELOAD tricks) you could use the dladdr(3) function (given a pointer, dladdr gives you a Dl_info structure with symbol and shared object names close to the given pointer).

Since dynamically linked shared object libraries are often mmap(2)-ed at non predictable addresses (e.g. because of ASLR) you need to do that at runtime. (See also /proc/self/maps from inside your process; read proc(5) etc...)

Read Drepper's paper: How to write Shared Libraries; be aware of VDSO...

Notice that a given *.so file has several mmap-ed segments, and that some of its (file) data is not mmap-ed! Use pmap(1) to find out.