Overview
During the deluge build I tried to workaround the issue with uncaught exceptions (due to the GCC mis-configuration), but after the long effort (and after a discovery of a linker problem) I decided to rebuild GCC compiler.Rationalization
This discussion contains a simple test for exception catching. So we can get the two simple programs and test whether the exceptions are handled properly:dev# cd /usr/local/src/ dev# mkdir test_exceptions dev# cd test_exceptions/ dev# wget http://codepoet.org/throw1.cpp dev# wget http://codepoet.org/throw2.cpp dev# g++ -Wall -O2 throw1.cpp -o throw1 dev# ./throw1 AbortedWith the current compiler (gcc version 3.3.6 configured without --enable-sjlj-exceptions flag) the exceptions are not caught at all. This message named "libgcc_s.so compatibility between 3.3 and 3.4 (sjlj/dwarf2 exceptions)" describes a problem with the change of default exception model and it is likely that this issue applies exactly in our case.
What version?
When we are re-building the compiler, why not to upgrade to a newer version? Based on uClibc FAQ I choose the version 4.1.2 (along with binutils version 2.18):The last two GNU binutils releases are 2.17 and 2.18. While 2.16 should work, workarounds for bugs in it are not considered. Since the GCC-3.4 and GCC-4.1 series are the recent stable release series (since the 4.0 and 4.2 series tend to be a bit broken for everyone), they are the latest versions we will address. If you encounter a compile error using an older version (say GCC 3.2), then you're out of luck. You'll need to workaround it yourself.
binutils-2.18
Building this package was the easy part:Build results: [binary] [files list]
Build sequence:
dev# cd /usr/local/src dev# wget http://ftp.gnu.org/gnu/binutils/binutils-2.18.tar.bz2 dev# tar xjvf binutils-2.18.tar.bz2 dev# cd binutils-2.18 dev# ./configure --host=i386-linux-uclibc --target=i386-linux-uclibc --build=i386-pc-linux-uclibc --prefix=/mnt/C/sys dev# ./make dev# make install
gcc 4.1.2
Info sources: [Prerequisites] [How to configure] [How to build]Build results: [binary] [files list]
Build sequence:
We can either download whole source package:
dev# cd /usr/local/src dev# wget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.1.2/gcc-4.1.2.tar.bz2 dev# tar xjvf gcc-4.1.2.tar.bz2 dev# cd gcc-4.1.2/... or we can pick out just packages we are interested in - for example:
dev# cd /usr/local/src dev# wget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.1.2/gcc-core-4.1.2.tar.bz2 dev# tar xjvf gcc-core-4.1.2.tar.bz2 dev# wget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.1.2/gcc-g++-4.1.2.tar.bz2 dev# tar xjvf gcc-g++-4.1.2.tar.bz2 dev# wget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.1.2/gcc-objc-4.1.2.tar.bz2 dev# tar xjvf gcc-objc-4.1.2.tar.bz2 dev# wget ftp://ftp.fu-berlin.de/unix/languages/gcc/releases/gcc-4.1.2/gcc-testsuite-4.1.2.tar.bz2 dev# tar xjvf gcc-testsuite-4.1.2.tar.bz2 dev# cd gcc-4.1.2/Now we can try to configure it:
dev# ./configure --prefix=/mnt/C/sys --host=i386-linux-uclibc --target=i386-linux-uclibc --build=i386-pc-linux-uclibc --enable-languages=c,c++ --enable-shared --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-nls --enable-multilib --with-x --x-includes=/mnt/C/sys/X11/include/ --x-libraries=/mnt/C/sys/X11/lib/ --with-gxx-include-dir=/usr/include/c++ --enable-bootstrap ... checking for MPFR... no *** This configuration is not supported in the following subdirectories: target-libada gnattools target-libgfortran target-libffi target-boehm-gc target-zlib target-libjava zlib fastjar target-libobjc (Any other directories should still work fine.)
The MPFR library is a C library for multiple-precision floating-point computations with correct rounding.For now I decided to proceed without it:
dev# make ... /usr/local/src/gcc-4.1.2/host-i386-linux-uclibc/prev-gcc/xgcc -B/usr/local/src/gcc-4.1.2/host-i386-linux-uclibc/prev-gcc/ -B/mnt/C/sys/i386-linux-uclibc/bin/ -O2 -g -fomit-frame-pointer -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wold-style-definition -Wmissing-format-attribute -Werror -DHAVE_CONFIG_H -DGENERATOR_FILE -o build/genmodes \ build/genmodes.o build/errors.o ../../build-i386-pc-linux-uclibc/libiberty/libiberty.a build/genmodes -h > tmp-modes.h /bin/sh: build/genmodes: No such file or directory make[3]: *** [s-modes] Error 127This problem emerged after the long portion of the build process, in stage 2. When we try to launch genmodes from the stage 1 (built with the "old" gcc) it runs with no problem:
dev# ./host-i386-linux-uclibc/stage1-gcc/build/genmodes ... DOUBLE ? &ieee_extended_intel_96_round_53_format : &ieee_extended_intel_96_format); }But the one from stage 2 (built with a new gcc) does not run at all:
dev# ./host-i386-linux-uclibc/stage2-gcc/build/genmodes -sh: ./host-i386-linux-uclibc/stage2-gcc/build/genmodes: No such file or directoryIn this message somebody is dealing with similar problem - In such cases it seems there is wrong path to the loader hardcoded in the generated elf file.
So let's inspect the executables with readelf tool (we are mainly interested in used dynamic loader aka interpreter):
dev# readelf -a ./host-i386-linux-uclibc/stage1-gcc/build/genmodes | grep interpreter [Requesting program interpreter: /lib/ld-uClibc.so.0] dev# readelf -a ./host-i386-linux-uclibc/stage2-gcc/build/genmodes | grep interpreter [Requesting program interpreter: /lib/ld-linux.so.2]So now we see the root of the problem. Now how to solve it... I found that there is the loader path hardcoded in gcc/config/linux.h (it does not depend on --target configuration) as follows:
#define DYNAMIC_LINKER "/lib/ld-linux.so.2"... so it seems we need a patch to correct this (and and possibly other settings) specific to the build in uClibc environment.
After some Web browsing I have found such set of patches here (the patches are actually for gcc-4.1.0, to overcome it we use -p1 patch option instead of -p1):
dev# cd /usr/local/src/gcc-4.1.2 dev# wget -O 100-uclibc-conf.patch "http://dev.wireless-fr.org/browser/firmware/trunk/kamikaze/toolchain/gcc/patches/4.1.2/100-uclibc-conf.patch?rev=353&format=raw" dev# patch -p1 < 100-uclibc-conf.patch... now try to continue and after long time we end up with another kind of problem, missing locale support in uClibc:
dev# make ... -fdiagnostics-show-location=once -ffunction-sections -fdata-sections -c ../../.././libstdc++-v3/src/ctype.cc -fPIC -DPIC -o .libs/ctype.o /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h: In static member function 'static const short unsigned int* std::ctype<char>::classic_table()': /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h:51: error: '__ctype_b' was not declared in this scope /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h: In constructor 'std::ctype<char>::ctype(int*, const short unsigned int*, bool, size_t)': /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h:85: error: '__ctype_toupper' was not declared in this scope /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h:86: error: '__ctype_tolower' was not declared in this scope /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h:87: error: '__ctype_b' was not declared in this scope /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h: In constructor 'std::ctype<char>::ctype(const short unsigned int*, bool, size_t)': /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h:120: error: '__ctype_toupper' was not declared in this scope /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h:121: error: '__ctype_tolower' was not declared in this scope /usr/local/src/gcc-4.1.2/i386-linux-uclibc/libstdc++-v3/include/i386-linux-uclibc/bits/ctype_noninline.h:122: error: '__ctype_b' was not declared in this scope make[4]: *** [ctype.lo] Error 1 ...For this there is another patch we can apply:
dev# cd /usr/local/src/gcc-4.1.2 dev# wget -O 200-uclibc-locale.patch "http://dev.wireless-fr.org/browser/firmware/trunk/kamikaze/toolchain/gcc/patches/4.1.2/200-uclibc-locale.patch?rev=353&format=raw" dev# patch -p1 < 200-uclibc-locale.patchAfter that I was able to finish build and installation successfully:
dev# make dev# make install dev# gcc --version gcc (GCC) 4.1.2 Copyright (C) 2006 Free Software Foundation, Inc. ...Ok, let's test the new compiler with our simple exception test:
dev# cd /usr/local/src/test_exceptions/ dev# g++ -Wall -O2 throw1.cpp -o throw1 /mnt/C/sys/lib/gcc/i386-linux-uclibc/4.1.2/../../../../i386-linux-uclibc/lib/libstdc++.so: undefined reference to `___tls_get_addr' collect2: ld returned 1 exit statusAccording to ldd it seems there are no missing library dependencies:
dev# ldd /mnt/C/sys/lib/gcc/i386-linux-uclibc/4.1.2/../../../../i386-linux-uclibc/lib/libstdc++.so libm.so.0 => /lib/libm.so.0 (0x00000000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00000000) libc.so.0 => /lib/libc.so.0 (0x00000000) /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)Following message contains some info about this issue. According to this message there should be no tls problem after applying all the patches, so maybe the correct solution is to download all remaining patches from this site. There is one patch dealing with libstdc++, but I am not sure whether it solves the TLS problem.
At the time I decided to re-configure GCC regarding to advice in this message:
dev# cd /usr/local/src/gcc-4.1.2 dev# make distclean dev# ./configure --prefix=/mnt/C/sys --host=i386-linux-uclibc --target=i386-linux-uclibc --build=i386-pc-linux-uclibc --enable-languages=c,c++ --enable-shared --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-nls --enable-multilib --with-x --x-includes=/mnt/C/sys/X11/include/ --x-libraries=/mnt/C/sys/X11/lib/ --with-gxx-include-dir=/usr/include/c++ --enable-bootstrap --disable-tls dev# make dev# make installNow let's repeat the test:
dev# cd /usr/local/src/test_exceptions/ dev# g++ -Wall -O2 throw1.cpp -o throw1 dev# ./throw1 AbortedIt seem that exceptions are still not being caught, let's debug it just to make sure:
dev# gdb throw1 GNU gdb 6.3 ... (gdb) run Starting program: /usr/local/src/test_exceptions/throw1 Program received signal SIGABRT, Aborted. 0xb7e63164 in kill () from /lib/libc.so.0 (gdb) where #0 0xb7e63164 in kill () from /lib/libc.so.0 #1 0xb7e5345a in raise () from /lib/libc.so.0 #2 0xb7e5cc67 in abort () from /lib/libc.so.0 #3 0xb7eb82f8 in uw_init_context_1 (context=0xbf83b150, outer_cfa=0xbf83b1d0, outer_ra=0xb7f5fb08) at ../.././gcc/unwind-dw2.c:1255 #4 0xb7eb86d4 in _Unwind_RaiseException (exc=0x804ab68) at unwind.inc:92 #5 0xb7f5fb08 in __cxa_throw (obj=0x804ab88, tinfo=0x80499e0, dest=0) at ../../.././libstdc++-v3/libsupc++/eh_throw.cc:72 #6 0x08048737 in main () (gdb) list 67 header->unwindHeader.exception_cleanup = __gxx_exception_cleanup; 68 69 #ifdef _GLIBCXX_SJLJ_EXCEPTIONS 70 _Unwind_SjLj_RaiseException (&header->unwindHeader); 71 #else 72 _Unwind_RaiseException (&header->unwindHeader); 73 #endif 74 75 // Some sort of unwinding error. Note that terminate is a handler. 76 __cxa_begin_catch (&header->unwindHeader);So it seems there are still two versions of exception handling and the one without SjLj does not work even with the new gcc version. I do not know exactly what is going on here, initially I thoought that the exception problem is specific to the 3.3 - 3.4 gcc versions, but regarding to this message it is possible that in some scenarios the --enable-sjlj-exceptions configuration is necessary for 4.x versions as well:
I have rebuilt gcc-3.4.4 w/ sjlj-exceptions, both the uclibc++ test and and throw2 perform ok against libstdc++ and uclibc++, so up to 3.4.4 (but probably 4.0.0 too) need --enable-sjlj-exceptionsSo let's try to re-configure the build once more:
dev# cd /usr/local/src/gcc-4.1.2 dev# make distclean dev# ./configure --prefix=/mnt/C/sys --host=i386-linux-uclibc --target=i386-linux-uclibc --build=i386-pc-linux-uclibc --enable-languages=c,c++ --enable-shared --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-nls --enable-multilib --with-x --x-includes=/mnt/C/sys/X11/include/ --x-libraries=/mnt/C/sys/X11/lib/ --with-gxx-include-dir=/usr/include/c++ --enable-bootstrap --disable-tls --enable-sjlj-exceptions dev# make dev# make installAnd now when we repeat the test:
dev# cd /usr/local/src/test_exceptions/ dev# g++ -Wall -O2 throw1.cpp -o throw1 dev# ./throw1 caught an exceptionHurray! It seems now we have some progress.
Let's try the second one:
dev# g++ -Wall -O2 throw2.cpp -o throw2 dev# ./throw2 1 Throwing out_of_range() Catching: out_of_range out_of_range meaningful comment 2 Throwing exception() // Can't specify comment Catching: St9exception 3 Throwing underflow_error // caught by base class (runtime_error) Catching: runtime_error underflow_error 4 Throwing runtime_error Catching: runtime_error a comment 5 Throwing length_error // caught be super-super-class (exception) Catching: St9exception 6 Throwing int Catching: int 26 7 Throwing const char* Catching: const char* This is a const char* 8 Throwing string Catching: string I'm a string 9 Throwing float ERROR: Nobody caught this! 10 Throwing upThe exception #9 is not caught but regarding to this discussion it seems ok.
Now we have the gcc version 4.1.2 properly configured, built and ready for building c++ applications like deluge.
1 comment:
The gcc bin package does not contain /usr/include/c++ content, and I think it should
Post a Comment