【问题标题】:Is there a downside to using -Bsymbolic-functions?使用 -Bsymbolic-functions 有缺点吗?
【发布时间】:2011-11-05 05:29:30
【问题描述】:

我最近在 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 对象的引用不统一)。

谢谢!

【问题讨论】:

  • 你是我光荣、快乐地解决了几个小时的链接器地狱。我有点爱你。

标签: linker visibility elf dynamic-library


【解决方案1】:

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

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

是的,有一个选项 --dynamic-list 正是这样做的

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

我仔细研究了一下,似乎没有问题。 libstdc++ 库显然做到了,或者至少考虑过了,他们只需要添加--dynamic-list-cpp-new 就可以使operator new 统一(以防止多个分配器/释放器在程序中混合的问题,但我认为这样的程序被破坏了反正)。 Ubuntu 使用它或默认使用它,它似乎会导致与某些软件包发生冲突。但总的来说,我期望它应该能很好地工作。

【讨论】:

  • 一个陷阱是同时使用--dynamic-list-Bsymbolic* 在当前发布的gold 版本中被破坏(在bfd ld 中很好),请参阅sourceware.org/bugzilla/show_bug.cgi?id=13577
  • 抱歉愚蠢的建议(我不擅长这个):你看到this了吗? (它们似乎描述了更多的副作用,尽管可能与符号数据有关,而不是与-Bsymbolic-functions。)
【解决方案2】:

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

例如,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 的来源,您会发现差异。

我见过的另一个案例是:

由于最初的问题是关于潜在的缺点,我认为值得一提的是那些比较常见的相关问题类别。

【讨论】:

    【解决方案3】:

    有副作用的情况。一个记录在案的: https://bugs.launchpad.net/ubuntu/+source/xfe/+bug/644645 我也想多了解一下,因为我现在有这样一个案例。

    【讨论】:

      【解决方案4】:

      也不建议使用 -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 ?? ()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-30
        • 1970-01-01
        • 1970-01-01
        • 2010-09-27
        • 1970-01-01
        • 2020-08-07
        • 2011-02-04
        相关资源
        最近更新 更多