1

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

我们看到一种情况,即调用 stat64 的 C 链接 (gcc) 版本的代码与旧版本的(C++ 链接的)共享库(libdb2.so.1,使用 stat64,但不应该)链接时提供它),并没有以这个 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 就不再被共享?

4

1 回答 1

1

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

于 2013-10-29T17:55:59.350 回答