使用-Bsymbolic函数有不利之处吗?

时间:2011-08-27 19:52:17

标签: linker visibility elf dynamic-library

我最近在GNU ld:

中发现了链接器选项“-Bsymbolic-functions”
-Bsymbolic
  When creating a shared library, bind references to global symbols to the 
  definition within the shared library, if any. Normally, it is possible 
  for a program linked against a shared library to override the definition 
  within the shared library. 

  This option is only meaningful on ELF platforms which support shared libraries.

-Bsymbolic-functions
  When creating a shared library, bind references to global function symbols 
  to the definition within the shared library, if any.  

  This option is only meaningful on ELF platforms which support shared libraries.

这似乎是GCC选项-fvisibility=hidden的反转,因为它不会阻止将引用的函数导出到其他共享对象,而是阻止对该函数的库内部引用绑定到一个导出不同共享对象的函数。我告诉自己-Bsymbolic-functions将阻止为函数创建PLT条目,这是一个很好的副作用。

  1. 但我想知道是否可能对此进行更精细的控制,例如为库的各个函数定义覆盖-Bsymbolic

  2. 我是否应该注意使用-Bsymbolic-functions的任何陷阱?我打算只使用它,因为-Bsymbolic会破坏异常,我认为(它会使我们认为对typeinfo对象的引用不统一)。

  3. 谢谢!

4 个答案:

答案 0 :(得分:22)

回答我自己的问题,因为我刚刚获得了Tumbleweed徽章......后来我发现了

  

但我想知道是否可能对此进行更精细的控制,例如为库的各个函数定义覆盖-Bsymbolic

是的,有选项--dynamic-list完全符合

  

我是否应该注意使用-Bsymbolic-functions的任何陷阱?我打算只使用它,因为-Bsymbolic会破坏异常,我认为(它会使得我们认为对typeinfo对象的引用不统一)。

我更加注重它,似乎没有问题。 libstdc ++库显然是这样做的,或者至少考虑过它,他们只需要添加--dynamic-list-cpp-new来统一operator new(以防止多个分配器/解除分配器在程序中混淆的问题,但我会争辩这样的程序无论如何都被打破了)。 Ubuntu使用它或默认使用它,它似乎导致与某些包冲突。但总的来说,我应该很好地工作。

答案 1 :(得分:0)

有些副作用。有记录的一个: https://bugs.launchpad.net/ubuntu/+source/xfe/+bug/644645 我还想了解更多关于它的信息,因为我现在有这样的情况。

答案 2 :(得分:0)

建议不要使用-Bsymbolic-functions构建glibc。这是我得到的结果:

Core was generated by `/home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/elf/ld-linux                                                               .'.
Program terminated with signal 11, Segmentation fault.
#0  0x400a3e90 in _int_free ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
(gdb) where
#0  0x400a3e90 in _int_free ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
#1  0x4016b94b in __libc_dlsym ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
#2  0x4004c2c7 in __gconv_find_shlib ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
#3  0x40042320 in find_derivation ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
#4  0x40042889 in __gconv_find_transform ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
#5  0x400d6f00 in __wcsmbs_load_conv ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
#6  0x400c86f6 in mbrtowc ()
   from /home/lano1106/dev/packages/glibc/repos/core-i686/src/glibc-build/libc.so.6
#7  0x08048914 in ?? ()
#8  0x00000000 in ?? ()

答案 3 :(得分:0)

您可以说这是一个“强化”选项,因为它可以确保对库内函数的调用肯定会在那里结束。但是我发现的一个问题是一些项目测试套件。

例如,libvirt测试套件将要调用刚刚构建的libvirt0.so,但还要模拟一些将从此处完成的调用。

由于-Bsymbolic-functions被用在构建上而使测试作为原始版本而不是模拟功能被调用而被破坏。

示例回溯 案例:

#0  virHostCPUGetThreadsPerSubcore (arch=VIR_ARCH_PPC64) at ../../../tests/virhostcpumock.c:30
#1  0x00007ffff7c1e4c4 in virHostCPUGetInfoPopulateLinux (cpuinfo=<optimized out>, arch=VIR_ARCH_PPC64, cpus=0x7fffffffdf38, mhz=<optimized out>, nodes=0x7fffffffdf40, sockets=0x7fffffffdf44, cores=0x7fffffffdf48, threads=0x7fffffffdf4c)
    at ../../../src/util/virhostcpu.c:661                                           
#2  0x0000555555557e6f in linuxTestCompareFiles (outputfile=0x55555558f150 "/build/libvirt-OUKR8i/libvirt-4.10.0/tests/virhostcpudata/linux-ppc64-subcores2.expected", arch=VIR_ARCH_PPC64,·
    cpuinfofile=0x5555555a3f10 "/build/libvirt-OUKR8i/libvirt-4.10.0/tests/virhostcpudata/linux-ppc64-subcores2.cpuinfo") at ../../../tests/virhostcputest.c:44
#3  linuxTestHostCPU (opaque=<optimized out>) at ../../../tests/virhostcputest.c:189
#4  0x000055555555914d in virTestRun (title=0x55555555c0a1 "subcores2", body=0x555555557cc0 <linuxTestHostCPU>, data=0x7fffffffe0c0) at ../../../tests/testutils.c:176
#5  0x000055555555781a in mymain () at ../../../tests/virhostcputest.c:263          
#6  0x0000555555559df4 in virTestMain (argc=1, argv=0x7fffffffe2c8, func=0x5555555577b0 <mymain>) at ../../../tests/testutils.c:1114
#7  0x00007ffff79bb09b in __libc_start_main (main=0x5555555576a0 <main>, argc=1, argv=0x7fffffffe2c8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe2b8) at ../csu/libc-start.c:308
#8  0x00005555555576ea in _start () at ../../../tests/virhostcputest.c:278 

错误的情况:

#0  virHostCPUGetThreadsPerSubcore (arch=arch@entry=VIR_ARCH_PPC64) at ../../../src/util/virhostcpu.c:1119
#1  0x00007ffff7c27e04 in virHostCPUGetInfoPopulateLinux (cpuinfo=<optimized out>, arch=VIR_ARCH_PPC64, cpus=0x7fffffffdea8, mhz=<optimized out>, nodes=0x7fffffffdeb0, sockets=0x7fffffffdeb4, cores=0x7fffffffdeb8, threads=0x7fffffffdebc)
    at ../../../src/util/virhostcpu.c:661                                           
#2  0x0000555555557e6f in linuxTestCompareFiles (outputfile=0x5555555a5c30 "/build/libvirt-4biJ7f/libvirt-4.10.0/tests/virhostcpudata/linux-ppc64-subcores2.expected", arch=VIR_ARCH_PPC64,·
    cpuinfofile=0x55555558fd20 "/build/libvirt-4biJ7f/libvirt-4.10.0/tests/virhostcpudata/linux-ppc64-subcores2.cpuinfo") at ../../../tests/virhostcputest.c:44
#3  linuxTestHostCPU (opaque=<optimized out>) at ../../../tests/virhostcputest.c:189
#4  0x000055555555914d in virTestRun (title=0x55555555c0a1 "subcores2", body=0x555555557cc0 <linuxTestHostCPU>, data=0x7fffffffe030) at ../../../tests/testutils.c:176
#5  0x000055555555781a in mymain () at ../../../tests/virhostcputest.c:263          
#6  0x0000555555559df4 in virTestMain (argc=1, argv=0x7fffffffe238, func=0x5555555577b0 <mymain>) at ../../../tests/testutils.c:1114
#7  0x00007ffff79b009b in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#8  0x00005555555576ea in _start () at ../../../tests/virhostcputest.c:278 

比较这两个地方virHostCPUGetThreadsPerSubcore的来源,您会发现区别。

我看到的另一种情况是:

由于最初的问题是关于潜在弊端的,所以我认为值得一提的是相关问题的一些常见类别。