我正在研究Linux的堆分析器,称为heaptrack.目前,我依赖于LD_PRELOAD重载各种(解)分配函数,这非常有效.
现在我想扩展该工具以允许运行时附加到现有进程,该进程是在没有LD_PRELOAD我的工具的情况下启动的.我可以dlopen通过GDB很好地使用我的库,但是这不会覆盖malloc等等.我认为,这是因为此时链接器已经解决了已经运行的进程的位置相关代码 - 正确吗?
那么我该怎么办才能超载malloc和朋友呢?
我不熟悉汇编代码.从我到目前为止所读到的,我想我将以某种方式必须修补malloc和其他功能,以便他们首先回调我的跟踪功能,然后继续他们的实际实现?那是对的吗?我怎么做?
我希望有现有的工具,或者我可以利用GDB/ptrace.
我正在Ubuntu 14.04(64位)编译深度学习库Caffe.
Version: 2.4.8+dfsg1-2ubuntu1从ubuntu软件包服务器安装OpenCV():
sudo apt-get install libopencv-dev
Caffe使用CMake 2.8 编译.
链接错误:
链接CXX可执行文件
/usr/lib/x86_64-linux-gnu/libopencv_highgui.so.2.4.8:未定义引用`TIFFOpen@LIBTIFF_4.0'
似乎找不到TIFF库的一些符号.我努力找到原因(没有运气).这是关于库的一些信息.
TIFF库链接 libopencv_highgui.so.2.4.8
$ ldd libopencv_highgui.so.2.4.8 | grep tiff
libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5(0x00007f978313b000)
导入符号 libopencv_highgui.so.2.4.8
$ readelf -s libopencv_highgui.so.2.4.8 | grep TIFFOpen
62:0000000000000000 0 FUNC GLOBAL DEFAULT UND TIFFOpen@LIBTIFF_4.0(9)
注意:@符号名称中只有一个.
$ nm -D libopencv_highgui.so.2.4.8 | grep TIFFOpen
你TIFFOpen
出口符号libtiff.so.5:
$ nm -D /usr/lib/x86_64-linux-gnu/libtiff.so.5
0000000000000000 A LIBTIFF_4.0
...
00000000000429f0 T TIFFOpen
...
$ readelf -s /usr/lib/x86_64-linux-gnu/libtiff.so.5|grep TIFFOpen …
如何通过库名找到库的文件名?
换句话说,当我使用"-lc"时,我知道它是/lib/libc.so.6(或类似的东西.)我希望能够输入一些命令,其中"-lc"是输入和"/ lib /libc.so.6"是输出.为了进一步扩展这个想法,我想指定我自己的搜索路径,这样我就可以将这个库解析器用于不同的工具链......任何帮助都会很棒,
谢谢Chenz
我有一个系统"fsimage.so"需要mkdirp,它恰好存在于libgen.so中.但fsimage.so不知道这一点.例如:
# ldd /usr/lib/python2.4/vendor-packages/fsimage.so
libfsimage.so.1.0 => /usr/lib/libfsimage.so.1.0
libxml2.so.2 => /lib/libxml2.so.2
libgcc_s.so.1 => /usr/sfw/lib/libgcc_s.so.1
libpthread.so.1 => /lib/libpthread.so.1
libz.so.1 => /lib/libz.so.1
libm.so.2 => /lib/libm.so.2
libsocket.so.1 => /lib/libsocket.so.1
libnsl.so.1 => /lib/libnsl.so.1
libc.so.1 => /lib/libc.so.1
libmp.so.2 => /lib/libmp.so.2
libmd.so.1 => /lib/libmd.so.1
# ./test
Traceback (most recent call last):
File "./test", line 26, in ?
import fsimage
ImportError: ld.so.1: isapython2.4: fatal: relocation error: file /usr/lib/python2.4/vendor-packages/fsimage.so: symbol mkdirp: referenced symbol not found
# LD_PRELOAD=/usr/lib/libgen.so ./test
Usage: ./test
Run Code Online (Sandbox Code Playgroud)
当然,如果我有源等,我可以简单地再次链接它,并添加"-lgen",它将添加libgen.so作为依赖.
但作为hackery的练习,说我没有任何资源,只是想添加fsimage.so还需要加载libgen.so.使用elfedit/objcopy等,这是不可能的?我不认为我可以使用"ld"来使用.so作为输入,并用额外的库写一个新的.so?
# elfdump /usr/lib/python2.4/vendor-packages/fsimage.so|grep NEEDED
[0] NEEDED 0x5187 …Run Code Online (Sandbox Code Playgroud) 我注意到取决于共享库的应用程序失败:如果您缺少某些依赖项,即使用户无意使用依赖项的功能,应用程序也会在加载时失败.
我希望我的应用程序比这更好.理想情况下,而不是分配n个不同的包,其中n = numberOfSupportedArchitectures*numberOfSupportedOS*Π(对于每个共享库)(备选方案的数量) 我会在加载时发出"加载共享库时出错"异常我想 - 但不需要 - 的库被发现不存在,然后以一种简单避免使用未解决的链接的方式继续执行.但显然,人们无法捕捉到这一点.如果缺少某些东西,那么在main()开始之前它都会崩溃.
我可以控制加载过程最接近的是使用dlopen,dlsym等解决所有链接.太无聊了.我希望有一个图书馆可供我这样做吗?
我注意到这不会是基于源的发行版或Windows上的问题.我打算在标签中放入二进制包,但显然我没有硬币标签的代表.
'似乎最优雅的解决方案在于改进OS的加载器/链接器的行为.
我正在用autoconf,automake和libtool构建一个程序.我的工作要求我静态链接(大多数)库.这在过去并不是一个问题,因为我可以静态地将所有内容联系起来
-all-static.现在这是一个问题因为我必须使用一个只是动态的库; 它是由第三方给我们的,我们没有来源.
当然,-all-static现在导致构建失败.是否有可能告诉libtool静态链接所有内容,除了这个库?是否有可能让libtool进行静态和动态链接的任何组合,还是全部或全部?
到目前为止,我已经尝试创建一个便利库LDFLAGS = -static,这取决于我想要静态链接的库.但libtool并没有像我希望的那样连接静态库.取决于便利库的程序仍然动态地链接所有内容.
我也尝试过--disable-shared,但这并没有影响构建.
这些问题类似,但没有真正回答我的问题:
(我不想从我的系统中删除共享库,并且指定所有内容的完整路径并不比手动链接更好,但也许这是唯一的方法.)
我有一个项目"Logger",其中配置类型是.dll.
"Logger"使用"libconfig"(开源配置解析器).目前,我有一个单独的"libconfig"项目,其配置类型是.lib
我将"libconfig"添加到Logger的框架和引用设置:
在Logger的链接器命令行中,我看到:/ IMPLIB:"path\to\Logger.lib"
我的问题是:为什么需要创建Logger.lib?我看到/ OUT ="path\to\Logger.dll",但我试图抓住visual studio的构建过程.
从M $的IMPLIB文档中,我看到了LINK过程的一部分.我还是不明白.
编辑:我没有提到如何使用Logger DLL.我的应用程序将在运行时加载它(因为只有特定的cmd行args才需要此功能)
在Linux中,对于共享库,我通常会看到一个库的.so,.so.1和.so.1.0文件.例如,库测试应该由libtest.so libtest.so.1 libtest.so.1.0文件提供.据我了解,.so.1.0包含真实数据; .so链接到.so.1.0并用于链接.但我不明白.so.1文件的目的.有人可以澄清.so.1文件的使用吗?谢谢.
我用了
readelf --dyn-sym my_elf_binary | grep FUNC | grep UND
Run Code Online (Sandbox Code Playgroud)
my_elf_binary从动态符号表中.dynsym精确显示动态符号表中的动态导入函数.示例输出将是:
[...]
3: 00000000 0 FUNC GLOBAL DEFAULT UND tcsetattr@GLIBC_2.0 (3)
4: 00000000 0 FUNC GLOBAL DEFAULT UND fileno@GLIBC_2.0 (3)
5: 00000000 0 FUNC GLOBAL DEFAULT UND isatty@GLIBC_2.0 (3)
6: 00000000 0 FUNC GLOBAL DEFAULT UND access@GLIBC_2.0 (3)
7: 00000000 0 FUNC GLOBAL DEFAULT UND open64@GLIBC_2.2 (4)
[...]
Run Code Online (Sandbox Code Playgroud)
假设与这些符号相关联的名称(例如tcsetattr或access)始终是唯一的,是否安全?或者是否有可能或合理的*),有一个动态符号表(过滤为FUNC和UND),其中包含两个具有相同关联字符串的条目?
我问的原因是我正在寻找动态导入函数的唯一标识符...
*)动态链接器不会将UND FUNC具有相同名称的所有" 符号" 解析为相同的函数吗?
据我所知,在典型的ELF二进制文件中,函数通过过程链接表(PLT)调用.函数的PLT条目通常包含跳转到全局偏移表(GOT)条目.此条目将首先引用一些代码将实际的函数地址加载到GOT中,并在第一次调用(lazy binding)后包含实际的函数地址.
确切地说,在延迟绑定之前,GOT入口指向PLT,跳转到GOT之后的指令.这些指令通常会跳转到PLT的头部,从那里调用一些绑定例程,然后更新GOT条目.
现在我想知道为什么有两个间接(调用PLT然后从GOT跳转到一个地址),而不是仅仅保留PLT并直接从GOT调用地址.看起来这可以节省跳跃和完整的PLT.您当然仍需要一些调用绑定例程的代码,但这可能在PLT之外.
有什么我想念的吗?额外PLT的目的是什么?
更新: 正如评论中所建议的那样,我创建了一些(伪)代码ASCII艺术来进一步解释我所指的内容:
据我所知,在懒惰绑定之前的当前PLT方案中就是这种情况:( PLT之间的一些间接printf由"......"表示.)
Program PLT printf
+---------------+ +------------------+ +-----+
| ... | | push [0x603008] |<---+ +-->| ... |
| call j_printf |--+ | jmp [0x603010] |----+--...--+ +-----+
| ... | | | ... | |
+---------------+ +-->| jmp [printf@GOT] |-+ |
| push 0xf |<+ |
| jmp 0x400da0 |----+
| ... |
+------------------+
Run Code Online (Sandbox Code Playgroud)
...和懒惰绑定后:
Program PLT printf
+---------------+ +------------------+ +-----+
| ... | | push [0x603008] | +-->| ... | …Run Code Online (Sandbox Code Playgroud)