Kla*_*ing 7 linux shared-libraries ld static-linking
我想创建一个使用第三方静态库中的函数的共享库.例如,foo与bar从libfoobar.a.我知道我的主要应用程序也在使用foo并将导出该符号.所以我只是想链接bar以保存代码大小并保持'foo'未解析(因为它将由主应用程序提供).如果我包含libfoobar.a,链接器ld将在我的共享库中包含这两个函数.如果我不包括libfoobar.a,我的库将无法访问功能,bar因为应用程序本身没有链接bar.问题:
libfoobar.a到一个共享库?bar从libfoobar.a,并指定在连接线?bar将从您的应用程序中使用,因此bar不会加载共享库中的副本?以下几点试图回答我提出的问题:
--just-symbolsor --undefined(或EXTERN链接描述文件命令)不会阻止ld链接符号。将静态库libfoobar.a转换为共享库libfoobar.so.1.0,并导出所有可见符号。您还可以使用--version-script其他方法仅导出符号的子集。
ld -shared -soname libfoobar.so.1 -o libfoobar.so.1.0 --whole-archive libfoobar.a --no-whole-archive
从静态库的副本中删除存档成员比提取它们更好,因为可能存在必须管理的内部依赖项。例如,假设您要导出所有符号,则可以从主可执行文件生成映射文件。然后,您可以 grep 查找可执行文件从静态库副本中拉入的所有存档成员,并将它们从副本中删除。因此,当您的 DSO 在静态库中链接时,它将留下相同的符号未解析。
如果使用该选项编译可执行文件,则可以将主可执行文件指定为 DSO 的共享库--pie。如果链接命令中的静态库位于 DSO 之前,则 DSO 将首先链接到可执行文件。LD_LIBRARY_PATH需要注意的是,主可执行文件必须通过或可用-rpath。此外,使用strace表明,由于可执行文件是您的库的依赖项,因此当您的 DSO 加载时它会再次加载。
ld -shared -rpath '$ORIGIN' -L. -lc -ldl -o DSO.so DSO.o app libfoobar.a
动态链接器将首先使用可执行文件的foo版本,除非您使用该标志调用dlopen()RTLD_DEEPBIND。使用strace显示整个 DSO 是通过文件映射mmap2()到内存中的。然而,维基百科声称,对于 mmap,“在访问特定位置后,从磁盘的实际读取是以“惰性”方式执行的。” 如果这是 true,则不会加载重复的foo 。请注意,仅当您的 DSO导出函数foo时才会发生覆盖。否则,只要 DSO 调用foo ,就会使用静态链接到 DSO的函数foo。
总之,如果mmap()使用惰性读取,那么最好的解决方案是以正常方式链接 DSO,并让动态链接器和 linux 处理剩下的事情。
| 归档时间: |
|
| 查看次数: |
4827 次 |
| 最近记录: |