Peeter Joot
Peeter Joot

Reputation: 8260

linux gcc linked executable missing static definition of stat64

A linux stat64 call is supposed to end up calling xstat64 with a static version of stat64 generated that passes a version along with the call.

We are seeing a condition where a C linked (gcc) version of code that calls stat64, when linked against an older version of a (C++ linked) shared library (libdb2.so.1, that uses stat64, but isn't supposed to provide it), is not ending up with a the "proper" static version of this stat64 call. The C++ linked app has what we expect:

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

whereas the gcc linked code (that also links to our libdb2 shared lib) ends up with a global reference to stat64 instead of the "static" version that it is suppose to have:

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

The same code, also when linked with gcc, when not linked to our libdb2 library, ends up with the expected "static" stat64 function:

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>

EDIT: more info obtained from a linker map (-Wl,--print-map)

When the gcc linked exe doesn't link to our (libdb2) shared lib, we see that it gets it's stat64 from libc_nonshared.a:

/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

whereas, once we link to our shared lib (libdb2), the symbols are picked up from crt1.o instead of 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

What could we be doing (or would have been doing since we don't see this in new versions of our library), that would cause lib_nonshared.a to no longer be shared once the consumer links to our library?

Upvotes: 1

Views: 808

Answers (1)

Peeter Joot
Peeter Joot

Reputation: 8260

It turned out that this was due to an intel compiler bug that was fixed. When we started using the compiler version that had the fix we were then exposed to a binary compatibility issue since the new version of the intel compiler (producing the shared lib in question), properly didn't export this stat64 symbol.

Upvotes: 1

Related Questions