gpt4 book ai didi

c++ - Ld 神奇地覆盖静态链接的符号

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:17:00 26 4
gpt4 key购买 nike

这几天我们一直在处理非常奇怪的问题。

我什至无法理解它是如何发生的——当第三方 (MATLAB) 程序使用我们的共享库时,它会以某种方式用它自己的符号覆盖我们的一些符号(准确地说是增强)。这些符号是静态链接的并且 (!!) 是本地的。

这是交易 - 我们使用 boost 1.47,MATLAB 有 boost 1.40。目前,库在从我们的库调用它们的 boost(正则表达式)时会出现段错误。

所以,这是神奇的:

  • 我们没有依赖库,ldd:
    linux-vdso.so.1 =>  (0x00007fff4abff000)    libpthread.so.0 => /lib/libpthread.so.0 (0x00007f1a3fd65000)    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f1a3fa51000)    libm.so.6 => /lib/libm.so.6 (0x00007f1a3f7cd000)    libgomp.so.1 => /usr/lib/libgomp.so.1 (0x00007f1a3f5bf000)    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f1a3f3a8000)    libc.so.6 => /lib/libc.so.6 (0x00007f1a3f024000)    /lib64/ld-linux-x86-64.so.2 (0x00007f1a414f9000)    librt.so.1 => /lib/librt.so.1 (0x00007f1a3ee1c000)
  • 没有从我们的库导出 Cxx 符号(我们的公共(public)符号是 POC C 以实现二进制兼容性),nm:
nm -g --defined-only libmysharedlib.soaddr1 T OurCSymbol1addr2 T OurCSymbol2addr3 T OurCSymbol3...
  • 仍然,它使用了他们的提升。如何? Stacktrace(路径切割):
[  0] 0x00007f21fddbb0a9 bin/libmwfl.so+00454825 fl::sysdep::linux::unwind_stack(void const**, unsigned long, unsigned long, fl::diag::thread_context const&)+000009[  1] 0x00007f21fdd74111 bin/glnxa64/libmwfl.so+00164113 fl::diag::stacktrace_base::capture(fl::diag::thread_context const&, unsigned long)+000161[  2] 0x00007f21fdd7d42d bin/glnxa64/libmwfl.so+00201773[  3] 0x00007f21fdd7d6b4 bin/glnxa64/libmwfl.so+00202420 fl::diag::terminate_log(char const*, fl::diag::thread_context const&, bool)+000100[  4] 0x00007f21fce525a7 bin/glnxa64/libmwmcr.so+00365991[  5] 0x00007f21fb9eb8f0 lib/libpthread.so.0+00063728[  6] 0x00007f21f3e939a9 libboost_regex.so.1.40.0+00342441 boost::re_detail::perl_matcher, std::allocator > >, boost::regex_traits > >::match_all_states()+000073[  7] 0x00007f21f3eb6546 bin/glnxa64/libboost_regex.so.1.40.0+00484678 boost::re_detail::perl_matcher, std::allocator > >, boost::regex_traits > >::match_imp()+000758[  8] 0x00007f21c04ad595 lib/libmysharedlib.so+04855189 bool boost::regex_match, std::allocator > >, char, boost::regex_traits > >(__gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator, boost::match_results, std::allocator > > >&, boost::basic_regex > > const&, boost::regex_constants::_match_flags)+000245[  9] 0x00007f21c04a71c7 lib/libmysharedlib.so+04829639 myfunc2()+000183[ 10] 0x00007f21c01b41e3 lib/libmysharedlib.so+01737187 myfunc1()+000307

众所周知,MATLAB 仅使用 RTLD_NOW 标志执行 dlopen。

人们,请和我一起思考。现在我什至不想解决这个问题,只是想简单地了解 ld&elf 的行为。

编辑:小的附加问题:我怎么理解,没有特殊的链接器选项,linux 中的符号.so 库永远不会通过地址链接?所以即使是静态链接的局部符号也会在运行时解析?

最佳答案

检查ld-Bsymbolic 选项。

如果指定了-Bsymbolic,那么在创建共享时对象 ld 将尝试将对全局符号的引用绑定(bind)到定义 共享库中。默认是将绑定(bind)延迟到运行时。

举个例子可能会更清楚。

假设 example.o 包含对定义在global.o,

$ nm example.o | grep ' U'
U _GLOBAL_OFFSET_TABLE_
U globalfn
$ nm global.o | grep ' T'
00000000 T globalfn

和两个共享对象,normal.sosymbolic.so,构建为如下:

$ cc -fPIC -c example.c
$ cc -c global.c
$ rm -f archive.a; ar cr archive.a global.o
$ ld -shared -o normal.so example.o archive.a
$ ld -Bsymbolic -shared -o symbolic.so example.o archive.a

反汇编 normal.so 的代码显示调用globalfn 实际上是在遍历过程链接表,并且因此调用的最终目的地是在运行时确定的。

$ objdump --disassemble normal.so
...snip...
00000194 <example>:
...snip...
1a6: e8 d9 ff ff ff call 184 <globalfn@plt>
...snip...
$ readelf -r normal.so

Relocation section '.rel.plt' at offset 0x16c contains 1 entries:
Offset Info Type Sym.Value Sym. Name
00001244 00000207 R_386_JUMP_SLOT 000001b8 globalfn

而在 symbolic.so 中,调用总是调用的定义共享对象中的 globalfn

$ objdump --disassemble symbolic.so
...snip...
0000016c <shared>:
...snip...
17e: e8 0d 00 00 00 call 190 <globalfn>
...snip...
$ readelf -r symbolic.so

There are no relocations in this file.

关于c++ - Ld 神奇地覆盖静态链接的符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7201667/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com