Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411500 Posts in 69373 Topics- by 58428 Members - Latest Member: shelton786

April 25, 2024, 09:57:45 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)glibc compatibility issues on Ubuntu
Pages: [1]
Print
Author Topic: glibc compatibility issues on Ubuntu  (Read 3876 times)
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« on: December 31, 2013, 06:35:18 PM »

I had to solve an issue yesterday which had no straightforward answer to it anywhere I could find on the internet. The purpose of this post is to document the problem and solution somewhere that's indexed by Google. If I had a blog I'd post it there, but I currently don't... Hopefully in the future someone finds this and has an easier time fixing it than I did!

I've been working on the Linux portion of my game framework over the last few days, and had just made a test build of one of my games using the new changes. This build was made on Ubuntu 12.04 LTS (64-bit) using typical dev tools, with gcc-multilib and some i386 versions of certain libraries installed alongside the x86_64 versions (which is a process that deserves its own post, some other time). When I tried to run it on a 32-bit Ubuntu 10.04 LTS I happened to have on another computer, it failed to launch and I was greeted by this message:

Code:
$ ./my_executable
./my_executable: /lib/tls/i686/cmov/libc.so.6: version `GLIBC_2.15' not found (required by ./my_executable)

Something I'd done caused my executable to require a newer version of glibc than was installed on that computer. I figured out which glibc it was using (2.11.1) by doing this:

Code:
$ ldd my_executable
./my_executable: /lib/tls/i686/cmov/libc.so.6: version `GLIBC_2.15' not found (required by ./my_executable)
linux-gate.so.1 =>  (0x0059d000)
librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0x004fe000)
libGLU.so.1 => /usr/lib/libGLU.so.1 (0x00c4b000)
libGL.so.1 => /usr/lib/mesa/libGL.so.1 (0x00a28000)
libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x001be000)
libasound.so.2 => /usr/lib/libasound.so.2 (0x00311000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x0071c000)
libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x00e8c000)
libX11.so.6 => /usr/lib/libX11.so.6 (0x001e4000)
/lib/ld-linux.so.2 (0x00690000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x003d9000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00dea000)
libXext.so.6 => /usr/lib/libXext.so.6 (0x00110000)
libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0x00b31000)
libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x0055a000)
libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x00708000)
libdrm.so.2 => /lib/libdrm.so.2 (0x00120000)
libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0x00be0000)
libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00d80000)
libXau.so.6 => /usr/lib/libXau.so.6 (0x005d9000)
libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x0012b000)

$ ls -ld /lib/tls/i686/cmov/libc.so.6
lrwxrwxrwx 1 root root 14 2011-05-26 20:48 /lib/tls/i686/cmov/libc.so.6 -> libc-2.11.1.so

After some sleuthing, I found a way to get a closer look at what was causing the glibc 2.15 dependency:

Code:
$ objdump -x my_executable | grep GLIBC_2.15
    0x06969195 0x00 07 GLIBC_2.15
    0x06969195 0x00 17 GLIBC_2.15
0000000000000000       F *UND* 0000000000000000              __pow_finite@@GLIBC_2.15
0000000000000000       F *UND* 0000000000000000              __acosf_finite@@GLIBC_2.15
0000000000000000       F *UND* 0000000000000000              __log_finite@@GLIBC_2.15
0000000000000000       F *UND* 0000000000000000              __exp_finite@@GLIBC_2.15
0000000000000000       F *UND* 0000000000000000              __fdelt_chk@@GLIBC_2.15

...and a couple more that are just short of 2.15 which we probably need to address too:

Code:
$ objdump -x my_executable | grep GLIBC_2.14
    0x06969194 0x00 13 GLIBC_2.14
0000000000000000       F *UND* 0000000000000000              memcpy@@GLIBC_2.14

$ objdump -x my_executable | grep GLIBC_2.11
    0x06969191 0x00 09 GLIBC_2.11
000000000043fb70       F *UND* 0000000000000000              __longjmp_chk@@GLIBC_2.11

(longjmp probably would've been OK since my old installation had 2.11.1, but that was cutting it a bit too close for comfort; I'd prefer to support a wider range of machines than whatever I happen to have lying around for testing)

The @@GLIBC_2.15 part (and 2.14, and 2.11) only showed up in my fully-linked executable. The symbols that used it were coming from some of the static libraries I linked to. Through more objdumping and grepping, I found the culprits: libvorbis, libpng, and portaudio:

Code:
$ objdump -x libvorbis.a | grep _finite
0000000000000000         *UND* 0000000000000000 __log_finite
0000000000002a65 R_X86_64_PC32     __log_finite-0x0000000000000004
0000000000000000         *UND* 0000000000000000 __exp_finite
0000000000000000         *UND* 0000000000000000 __acosf_finite
00000000000007c4 R_X86_64_PC32     __exp_finite-0x0000000000000004
0000000000000d27 R_X86_64_PC32     __acosf_finite-0x0000000000000004
0000000000000d58 R_X86_64_PC32     __acosf_finite-0x0000000000000004
0000000000000000         *UND* 0000000000000000 __log_finite
0000000000000000         *UND* 0000000000000000 __exp_finite
000000000000198e R_X86_64_PC32     __log_finite-0x0000000000000004
00000000000019d4 R_X86_64_PC32     __log_finite-0x0000000000000004
0000000000001c4a R_X86_64_PC32     __exp_finite-0x0000000000000004
0000000000001c7d R_X86_64_PC32     __exp_finite-0x0000000000000004
0000000000001e28 R_X86_64_PC32     __exp_finite-0x0000000000000004
00000000000020bb R_X86_64_PC32     __exp_finite-0x0000000000000004
00000000000020e8 R_X86_64_PC32     __exp_finite-0x0000000000000004
00000000000021cb R_X86_64_PC32     __exp_finite-0x0000000000000004
00000000000021fe R_X86_64_PC32     __exp_finite-0x0000000000000004
00000000000025e8 R_X86_64_PC32     __log_finite-0x0000000000000004
000000000000268a R_X86_64_PC32     __log_finite-0x0000000000000004
00000000000026f0 R_X86_64_PC32     __log_finite-0x0000000000000004
000000000000286d R_X86_64_PC32     __exp_finite-0x0000000000000004
0000000000002c1a R_X86_64_PC32     __log_finite-0x0000000000000004
0000000000002d1f R_X86_64_PC32     __log_finite-0x0000000000000004
0000000000000000         *UND* 0000000000000000 __log_finite
0000000000000000         *UND* 0000000000000000 __pow_finite
0000000000000072 R_X86_64_PC32     __log_finite-0x0000000000000004
0000000000000360 R_X86_64_PC32     __pow_finite-0x0000000000000004
00000000000004cf R_X86_64_PC32     __pow_finite-0x0000000000000004
0000000000000bf2 R_X86_64_PC32     __pow_finite-0x0000000000000004

$ objdump -x libpng.a | grep __longjmp_chk
00000000         *UND* 00000000 __longjmp_chk
000000d5 R_386_32          __longjmp_chk
00000000         *UND* 00000000 __longjmp_chk
000017b7 R_386_32          __longjmp_chk

$ objdump -x libportaudio.a | grep __fdelt_chk
00000000         *UND* 00000000 __fdelt_chk
00001d37 R_386_PC32        __fdelt_chk
00001d4f R_386_PC32        __fdelt_chk
00001db4 R_386_PC32        __fdelt_chk
00001dc9 R_386_PC32        __fdelt_chk
00001ded R_386_PC32        __fdelt_chk
00001e0d R_386_PC32        __fdelt_chk

(you might notice these don't include memcpy@@GLIBC_2.14; more on that in a bit)

Here's where things get tricky. Now that we know where the problematic symbols are coming from, how can we compile without them? I found suggestions to compile against an older version of glibc, but that's unwieldy. Fortunately, it turns out that there are gcc optimization flags that can suppress the behavior that generates these symbols. Here are the ones I had to use for each:

Code:
*_chk (__fdelt_chk, __longjmp_chk): -fno-stack-protector
*_finite (__pow_finite, etc.): -fno-finite-math-only

With the three offending libraries recompiled with the appropriate -fno-* flags, my executable links without requiring too new a glibc version, and runs successfully on my test machine. Yay!

One lingering problem is memcpy. By coincidence, only the 64-bit version of my executable required memcpy@@GLIBC_2.14, and my old test machine was 32-bit. Telling users to use the 32-bit version of my executable if they're in a situation where they're 64-bit but have an old glibc is acceptable for my purposes. This Stack Overflow post has some possible solutions, but I wasn't able to verify any of them with the hardware I had at my disposal.
Logged

fractilegames
Level 1
*



View Profile WWW
« Reply #1 on: January 02, 2014, 12:16:41 AM »

When setting up my build environment some time ago I spend a lot of time trying to figure out a good solution to these GLIBC version compatibility issues, but I didn't find any usable way to tell gcc to link against specific older GLIBC version.

I finally gave up and now I just build all my releases in VirtualBox environment that has "old enough" library versions. In my case that is currently Debian 5.x, which uses GLIBC 2.13.
Logged

Liosan
Level 2
**


View Profile
« Reply #2 on: January 02, 2014, 03:37:50 AM »

One lingering problem is memcpy.
Have you considered rolling you own? Even taking various options like SSE and handling alignment into account, it could be simpler that solving this problem.

Liosan
Logged

ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #3 on: January 02, 2014, 01:56:33 PM »

One lingering problem is memcpy.
Have you considered rolling you own? Even taking various options like SSE and handling alignment into account, it could be simpler that solving this problem.

Ah, good idea. The easy way would be to have it call memmove, which apparently hasn't changed as recently as memcpy. As long as I linked my drop-in replacement before linking to libc, it shouldn't conflict and I wouldn't have to change all the places where memcpy is called, I think?
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic