I'm working on a project that involves the use of LD_PRELOAD to overwrite symbols that are dynamically linked from a shared object at runtime, for example:
LD_PRELOAD=/some_library.so ./myapp
I'm getting a segfault when running the executable, but only when I run it outside of GDB. Another detail is that I'm looking up the address of the symbol in the executable using bfd -- and this address matches the address I've found using objdump -d ./myapp
, but when I call that address at runtime without GDB it segfaults. I'm happy to add code / more details on the exact use case, but my question is really: How does GDB change dynamic linking behavior? My suspicion is that the symbol I'm trying to override is being relocated to another region of memory at runtime, but I don't know how that process works, or how to lookup the relocated address (outside of using gdb at runtime)
I've tried looking up the symbol manually:
root@server:/workspace/test_apps# objdump -dC ./myapp | grep -i myfunction 0000000000001b65 <__sti____myFunction()>:
and in my LD_PRELOADED library I'm trying to call it like this:
void (*myFunc)(void) =
(void(*)(void)) 0x1b65;
myFunc();
If I look up that same symbol using gdb without the preloaded library, I see something interesting:
root@server:/workspace/test_apps# gdb --args env
LD_PRELOAD=/some_library.so ./myapp
(gdb) info functions
...
0x0000000000001b65 __sti____myFunction()
but then if I run it with GDB, and then lookup the symbol, it's been relocated to a different address:
root@server:/workspace/test_apps# gdb --args env LD_PRELOAD=/some_library.so ./myapp
(gdb) run
(gdb) info functions
...
0x0000555555555b65 __sti____myFunction()
The last thing I'll note is that if I use this new address (0x0000555555555b65) to call the function, instead of the address I looked up earlier (0x1b65), it works (no segfault), but only in the context of gdb. Outside of GDB it doesn't work with either address.