【问题标题】:linux gcc linked executable missing static definition of stat64linux gcc链接的可执行文件缺少stat64的静态定义
【发布时间】:2013-05-05 14:43:45
【问题描述】:

linux stat64 调用应该最终调用 xstat64 并生成一个静态版本的 stat64,该版本与调用一起传递一个版本。

我们看到一种情况,即调用 stat64 的 C 链接 (gcc) 版本的代码与旧版本的(C++ 链接)共享库 (libdb2.so.1,使用 stat64,但不是t 应该提供它),并没有以这个 stat64 调用的“正确”静态版本结束。 C++ 链接的应用程序符合我们的预期:

00000000004007c8 <__xstat64@plt>:
  4007c8:  jmpq   *1051250(%rip)        # 501240 <_GLOBAL_OFFSET_TABLE_+0x20>
  4007ce:  pushq  $0x1
  4007d3:  jmpq   4007a8 <_init+0x18>

0000000000400ac0 <stat64>:
  400ac0:  push   %rbp
  400ac1:  mov    %rsp,%rbp
  400ac4:  sub    $0x10,%rsp
  400ac8:  mov    %rdi,0xfffffffffffffff8(%rbp)
  400acc:  mov    %rsi,0xfffffffffffffff0(%rbp)
  400ad0:  mov    0xfffffffffffffff0(%rbp),%rdx
  400ad4:  mov    0xfffffffffffffff8(%rbp),%rsi
  400ad8:  mov    $0x1,%edi
  400add:  callq  4007c8 <__xstat64@plt>
  400ae2:  leaveq
  400ae3:  retq

而 gcc 链接代码(也链接到我们的 libdb2 共享库)最终会得到对 stat64 的全局引用,而不是它应该具有的“静态”版本:

0000000000400618 <stat64@plt>:
  400618:   jmpq   *1050146(%rip)        # 500c40 <_GLOBAL_OFFSET_TABLE_+0x20>
  40061e:   pushq  $0x1
  400623:   jmpq   4005f8 <_init+0x18>

同样的代码,当与 gcc 链接时,当未链接到我们的 libdb2 库时,会以预期的“静态”stat64 函数结束:

0000000000400550 <__xstat64@plt>:
  400550:   jmpq   *1050170(%rip)        # 500b90 <_GLOBAL_OFFSET_TABLE_+0x20>
  400556:   pushq  $0x1
  40055b:   jmpq   400530 <_init+0x18>

00000000004007b0 <stat64>:
  4007b0:   mov    %rsi,%rdx
  4007b3:   mov    %rdi,%rsi
  4007b6:   mov    $0x1,%edi
  4007bb:   jmpq   400550 <__xstat64@plt>

编辑:从链接器映射 (-Wl,--print-map) 获得的更多信息

当 gcc 链接的 exe 没有链接到我们的 (libdb2) 共享库时,我们看到它从 libc_nonshared.a 获取它的 stat64:

/usr/lib64/libc_nonshared.a(stat64.oS)
                              /home/hotellnx94/peeterj/tmp/cc2f7ETx.o (stat64)
...

.plt            0x0000000000400530       0x70
 *(.plt)
 .plt           0x0000000000400530       0x70 /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o
                0x0000000000400540                __libc_start_main@@GLIBC_2.2.5
                0x0000000000400550                __xstat64@@GLIBC_2.2.5
                0x0000000000400560                printf@@GLIBC_2.2.5
                0x0000000000400570                memset@@GLIBC_2.2.5
                0x0000000000400580                strerror@@GLIBC_2.2.5
                0x0000000000400590                __errno_location@@GLIBC_2.2.5

 .text          0x00000000004007b0       0x10 /usr/lib64/libc_nonshared.a(stat64.oS)
                0x00000000004007b0                stat64

然而,一旦我们链接到我们的共享库 (libdb2),就会从 crt1.o 而不是 lib_nonshared.a 中获取符号:

.plt            0x00000000004005f8       0x70
 *(.plt)
 .plt           0x00000000004005f8       0x70 /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o
                0x0000000000400608                __libc_start_main@@GLIBC_2.2.5
                0x0000000000400618                stat64
                0x0000000000400628                printf@@GLIBC_2.2.5
                0x0000000000400638                memset@@GLIBC_2.2.5
                0x0000000000400648                strerror@@GLIBC_2.2.5
                0x0000000000400658                __errno_location@@GLIBC_2.2.5

我们可能在做什么(或者因为在我们的库的新版本中没有看到这一点而一直在做),这会导致一旦消费者链接到我们的库后,lib_nonshared.a 就不再被共享?

【问题讨论】:

    标签: linux linker glibc stat


    【解决方案1】:

    事实证明,这是由于已修复的英特尔编译器错误造成的。当我们开始使用已修复的编译器版本时,我们会遇到二进制兼容性问题,因为新版本的 intel 编译器(生成有问题的共享库)无法正确导出此 stat64 符号。

    【讨论】:

      猜你喜欢
      • 2010-12-25
      • 2011-08-06
      • 1970-01-01
      • 2011-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-16
      相关资源
      最近更新 更多