Using LD_PRELOAD
doesn't really involve modifying something which isn't yours, and the injection isn't all that different from normal dynamic library loading. The “typical ELF hacking tool” from the ERESI project is unrelated to LD_PRELOAD
. You should not be afraid of it. A good introduction to writing LD_PRELOAD
-able “proxies” is here.
That being said, if you want to create a system-wide proxy for some library, you might argue that globally setting LD_PRELOAD
(and thus loading your proxy into every binary that ever runs on your system) is undesirable. It is commonly used to override functions from glibc by tools such as libeatmydata or socksify, but if you're overriding a function in a library that is bigger and/or less widespread than glibc, it makes sense to try to find another approach, to really create a proxy for just that one library.
One such approach is to use patchelf --replace-needed
or --add-needed
to hardcode the full pathname of the original library and then make sure the proxy library is found first by setting LD_LIBRARY_PATH
¹. So, the complete procedure is:
- create an
LD_PRELOAD
-able library that overrides some functions of the original one (test that it works using only LD_PRELOAD
before proceeding further!)
- compile and link this library with the original library so that
ldd libwrapper-foo.so
includes something like:
libfoo.so.0 => /usr/lib/x86_64-linux-gnu/libfoo.so.0 (0x0000deadbeef0000)
- hardcode the full path using
patchelf
:
patchelf --replace-needed libfoo.so.0 /usr/lib/x86_64-linux-gnu/libfoo.so.0 libwrapper-foo.so
- symlink
libwrapper-foo.so
to libfoo.so.0
- now
LD_LIBRARY_PATH=. ldd $(which program-that-uses-libfoo)
should include these lines:
libfoo.so.0 => ./libfoo.so.0 (0x0000dead56780000)
/usr/lib/x86_64-linux-gnu/libfoo.so.0 (0x0000dead1234000000)
- set
LD_LIBRARY_PATH
to full path to the wrapper library in your .bashrc
or somewhere
A real-life example of such proxy libary is my wrapper for libpango that enables subpixel positioning for all applications.
¹) It might also be possible to put this proxy library into /usr/local/lib
, but ldconfig
(the tool that updates shared libraries cache) refuses to use libraries with hardcoded absolute paths.