gcc Invalid version (max ) error adding symbols: Bad value

Gil-Mor picture Gil-Mor · Jan 24, 2017 · Viewed 23.9k times · Source

I've successfully build several 32 bit, static and Shared, libraries on Linux x86_x64 and I'm now trying to link them together to an executable and I get the following error:

/usr/bin/ld: foo.so: __moddi3: invalid version 21 (max 0)

foo.so: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

where foo.so is one of the shared libraries I built.

the __moddi3 function is part of the libgcc Integer Library Routines. Its signature is:

— Runtime Function: long __moddi3 (long a, long b)

And its role is to provide 64 bit arithmetic for 32 bit code.

I can't even find the meaning of the versions of this library.

Why do I see this error now - after the library was already build?

I built all the shared libs with -fPIC and -m32 flag for compiling and linking.

The executable is CXX executable.

here's the linker output with --verbose

Using built-in specs.
COLLECT_GCC=/usr/bin/c++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/5/32/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/:/lib/i386-linux-gnu/:/lib/../lib32/:/usr/lib/i386-linux-gnu/:/usr/lib/../lib32/:/usr/lib/gcc/x86_64-linux-gnu/5/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/5/../../../:/lib/i386-linux-gnu/:/lib/:/usr/lib/i386-linux-gnu/:/usr/lib/
COLLECT_GCC_OPTIONS='-g' '-m32' '-v' '-o' '../BIN/Y' '-L/home/X/W/Y/LibTee/lib/Linux' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=i686'
 /usr/lib/gcc/x86_64-linux-gnu/5/collect2 -plugin /usr/lib/gcc/x86_64-linux-gnu/5/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper -plugin-opt=-fresolution=/tmp/ccM5EczN.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc --sysroot=/ --build-id --eh-frame-hdr -m elf_i386 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib/ld-linux.so.2 -z relro -o ../BIN/Y /usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/crt1.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/crti.o /usr/lib/gcc/x86_64-linux-gnu/5/32/crtbegin.o -L/home/X/W/Y/LibTee/lib/Linux -L/usr/lib/gcc/x86_64-linux-gnu/5/32 -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32 -L/lib/i386-linux-gnu -L/lib/../lib32 -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib32 -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/gcc/x86_64-linux-gnu/5/../../../i386-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/5/../../.. -L/lib/i386-linux-gnu -L/usr/lib/i386-linux-gnu -rpath /home/X/W/Y/LibTee/lib/Linux:/home/X/W/Y/BIN -ltee ../openssl/Lib/Linux/libssl.a ../IPP_5_3_1_064/IA32/lib/Linux/libippcore.a ../IPP_5_3_1_064/IA32/lib/Linux/libippcp.a ../IPP_5_3_1_064/IA32/lib/Linux/libipps.a ../BIN/libCryptoDataGen.so -lgcc -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/5/32/crtend.o /usr/lib/gcc/x86_64-linux-gnu/5/../../../../lib32/crtn.o
/usr/bin/ld: ../BIN/libCryptoDataGen.so: __moddi3: invalid version 21 (max 0)
../BIN/libCryptoDataGen.so: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

Answer

Gil-Mor picture Gil-Mor · Jan 31, 2017

So, I found the solution. The problem was:

I built a shared library - foo.so. foo was linked with some static libraries. I found that a lot of them included the __moddi3 function along with more libgcc stuff.

I was trying to link foo.so to an executable bar. bar also linked against static libraries and a lot of them also included the __moddi3 function along with more libgcc stuff.

The problem was that foo.so exported symbols it took from the static libraries - the __moddi3 function was among those symbols. See here a detailed cover of the scenario. So apparently what happened is that the executable took some libgcc stuff that weren't compatible with the __moddi3 function version that was exported by foo, Then when the linker encountered the __moddi3 version - It raised an error about me trying to link incompatible versions.

The Solution is given in the previous link. The way to deal with this is to use an export list in which you tell the compiler to export wanted symbols and hide all other symbols (using wildcard *).
Since I'm using CMake - I added -Wl,--version-script,exportmap to set_target_properties(foo PROPERTIES LINK_FLAGS. 'exportmap' is the name of my export list file. It's in the format of:

    {  
    global:  
         func_1;  
         func_2;  
         func_3;  
    local:  
         *;  
    }

If you're not using CMake add -Wl,--version-script,exportmap to C_FLAGS or CXX_FLAGS in the makefile.

use readelf -Ws foo.so to see your export symbols table.

Here's another good read on the subject.