我最近在 proggit 上看到了对它的引用,并且(截至目前)它没有被解释。
我怀疑 this 可能是它,但我不确定。
如果您将 LD_PRELOAD
设置为共享对象的路径,则该文件将在在任何其他库(包括 C 运行时 libc.so
)之前加载。因此,要使用您的特殊 malloc()
实现运行 ls
,请执行以下操作:
$ LD_PRELOAD=/path/to/my/malloc.so /bin/ls
您可以通过创建具有相同符号的库并在 LD_PRELOAD
中指定库来覆盖库存库中的符号。
有些人使用它来指定非标准位置的库,但 LD_LIBRARY_PATH
更适合此目的。
正如许多人提到的,使用 LD_PRELOAD
预加载库。顺便说一句,如果设置可用 ldd
命令,您可以CHECK。
示例:假设您需要预加载自己的 libselinux.so.1
。
> ldd /bin/ls
...
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f3927b1d000)
libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007f3927914000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f392754f000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f3927311000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f392710c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3927d65000)
libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007f3926f07000)
因此,设置您的预加载环境:
export LD_PRELOAD=/home/patric/libselinux.so.1
再次检查您的图书馆:
>ldd /bin/ls
...
libselinux.so.1 =>
/home/patric/libselinux.so.1 (0x00007fb9245d8000)
...
使用 LD_PRELOAD
,您可以为库提供优先权。
例如,您可以编写一个实现 malloc
和 free
的库。通过使用 LD_PRELOAD
加载这些,您的 malloc
和 free
将被执行,而不是标准的。
calloc
怎么办?那不是把一切都搞砸了吗?
malloc
和 free 是在 glibc 中专门设计的,以允许这样做,并且 stock calloc
设法调用您导入的 malloc
。不要尝试使用任何其他功能。它不会工作得那么好。
LD_PRELOAD
列出了具有覆盖标准集的函数的共享库,就像 /etc/ld.so.preload
一样。这些由加载程序 /lib/ld-linux.so
实现。如果您只想覆盖几个选定的函数,您可以通过创建一个覆盖目标文件并设置 LD_PRELOAD
来做到这一点;此目标文件中的函数将仅覆盖那些函数,而其他函数则保持原样。
有关共享库的更多信息,请访问 http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
要将 mylib.so
导出到 env:
$ export LD_PRELOAD=/path/mylib.so
$ ./mybin
要禁用它:
$ unset LD_PRELOAD
unset LD_PRELOAD
unset
和 export VAR=
并不完全相同。 unset
是要走的路。
这是有关预加载的详细博客文章:
https://blog.cryptomilk.org/2014/07/21/what-is-preloading/
使用 LD_PRELOAD
路径,您可以强制应用程序加载程序加载提供的共享对象,而不是提供的默认值。
开发人员通过提供不同版本的共享对象来使用它来调试他们的应用程序。
我们用它来破解某些应用程序,通过使用准备好的共享对象覆盖现有函数。
当使用 LD_PRELOAD 时,该文件将在任何其他文件之前加载。使用 $export LD_PRELOAD=/path/lib
预加载 lib。这甚至可以在程序中使用。
LD_PRELOAD
指定一个绝对路径。原因是它是一个环境变量,它是由子进程继承的——它可能具有与父进程不同的工作目录。因此,任何相对路径都无法找到要预加载的库。