5.10. Cocoon Toolchain

The Cocoon toolchain contains the GNU Compiler Collection (GCC), which includes the C and C++ compilers, and Binutils, which includes an assembler and linker.

User Notes: http://wiki.linuxfromscratch.org/hlfs/wiki/toolchain

5.10.1. Installation of the Cocoon Toolchain

Unlike the previous toolchain installation, this toolchain does not need to be bootstrapped. Each component will only be built once.

Unpack the binutils-2.17, gcc-core-4.1.2, and gcc-g++-4.1.2 source packages but do not change directory. Then combine the two packages to the same directory with the following commands:

mv -v gcc-4.1.2/ cocoon-toolchain
mv -v binutils-2.17 cocoon-toolchain/
cd cocoon-toolchain/
ln -vs binutils-2.17/{bfd,binutils,gas,gprof,ld,opcodes} .

This patch is from Binutils CVS: http://sourceware.org/ml/binutils-cvs/2006-06/msg00095.html, and adds the -z lazy option. The vanilla behavior of Binutils is the -z lazy, but later we will make -z now the default for better security. This patch will make it possible to reverse the -z now if needed for debugging reasons. Apply this patch with the following command:

patch -Np1 -i ../binutils-2.17-lazy-1.patch

Patch Binutils for PT_PAX_FLAGS:

cd binutils-2.17/
patch -Np1 -i ../../binutils-2.17-pt_pax-1.patch
cd ../

The following patches have been added to GCC-4.2, in a different way. Apply these patches for uClibc support:

This next patch adds -W[no]-overlength-strings to GCC, from GCC CVS: http://gcc.gnu.org/ml/gcc-patches/2006-01/msg01920.html. This option allows GCC to bypass warnings caused by GCC using longer strings than C89 standards require. When building GCC with GCC this warning is not usefull, and this patch allows GCC to use -Werror more aggressively. This patch is added in this chapter so -Wno-overlength-strings will be found an used when building the toolchain in the next chapter:

patch -Np1 -i ../gcc-4.1.2-Wno_overlength_strings-1.patch

This next patch adds __strncat_chk compile time buffer overflow checking to GCC-4.1.2, and is from GCC CVS: http://gcc.gnu.org/ml/gcc-patches/2006-09/msg00722.html. This checking is performed with the -D_FORTIFY_SOURCE GCC flag, and the same checking will be performed again at run time by the system library. This patch is added in this chapter so the checking can be used when building libc in the next chapter:

patch -Np1 -i ../gcc-4.1.2-strncat_chk-1.patch

This next patch adds -D_FORTIFY_SOURCE=2 to the GCC specs file. This behavior can be reset by using -D_FORTIFY_SOURCE=?, or disabled with -U_FORTIFY_SOURCE, in CFLAGS. The -D_FORTIFY_SOURCE option is a C preprocessor macro, but the GCC documentation recommends adding it to CFLAGS, instead of CPPFLAGS, unless there is a specific reason to do otherwise. This patch also adds the -O option if no other optimization option is used, because -D_FORTIFY_SOURCE only works with optimization. This patch is added at this stage so the toolchain in the next chapter will be built with -D_FORTIFY_SOURCE=2. Apply this patch with the following command:

patch -Np1 -i ../gcc-4.1.2-fortify_source-2.patch

The next patch adds -fstack-protector-all and -Wstack-protector to GCC's default behaviour for C, C++, ObjC, and ObjC++. This patch also reduces the minimum array size for protection from 8 to 4 bytes, if -fstack-protector is used. Additionally, this patch fixes gcc/configure to detect libc support in the C library regardless of where it is installed, but it depends on the existance of the libc.a library file. This patch is added at this stage so the toolchain in the next chapter will be built with -fstack-protector-all. Apply this patch with the following command:

patch -Np1 -i ../gcc-4.1.2-fstack_protector-1.patch

Under uClibc we're using GCC's libssp for SSP and _FORTIFY_SOURCE library functions. The GCC we are building now will link the libstdc++ library, and others, to the existing libssp in /tools/lib. The libssp.so library in /tools/lib is linked to the host system's C library. This is going to cause a problem when the libstdc++ library, and others, are linked to two different C libraries. The following commands will remove the shared libssp.so library and replace it with a symbolic link to the static version, and create an empty archive to replace libssp_nonshared.a. This is only temporary. After we run make install, later on this page, we will be able to use the new libssp.so shared library when building the rest of this chapter, and the toolchain in the next chapter:

rm -v /tools/lib/libssp.so*
rm -v /tools/lib/libssp_nonshared.a
ln -vs libssp.a /tools/lib/libssp.so
ar -r /tools/lib/libssp_nonshared.a

This patch adds -fPIE -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,combreloc to GCC's default behaviour for C, C++, ObjC, and ObjC++. The -fno-PIE -fPIC options will be used if -shared, -nostdlib, or -nostartfiles options are used on GCC's command line. Furthermore, -fno-PIE -fno-PIE will be used if the -static or -D__KERNEL__ options are used. To disable the new behaviour added by this patch use -fno-PIE -nopie together. The -norelro, -nocombreloc, and -nonow options disable the other linking options. This patch is added at this stage so the toolchain in the next chapter will be built with it. Apply this patch with the following command:

patch -Np1 -i ../gcc-4.1.2-fpie-2.patch

Apply the patches for uClibc support:

cd binutils-2.17/
patch -Np1 -i ../../binutils-2.17-uClibc_conf-1.patch
cd ../
patch -Np1 -i ../gcc-4.1.2-uClibc_conf-1.patch
patch -Np1 -i ../gcc-4.1.2-uClibc_locale-1.patch

Add automatic linking for libintl:

cp -v gcc/config/{linux.h,linux.h.orig}
sed 's/%{shared:-lc}/%{!nointl: -lintl} &/' gcc/config/linux.h.orig > \
    gcc/config/linux.h

This version of GCC has a small bug/typo with RPATH_ENVVAR value for bfd and opcode. Use the following commands to fix this bug, so that “--enable-shared” will work:

cp -vi Makefile.in{,.orig}
sed -e 's@/.:$$r@/.libs:$$r@' -e 's@/.:@/.libs:@' \
    Makefile.in.orig > Makefile.in

Under normal circumstances the GCC fixincludes script is run in order to fix potentially broken header files. As GCC-4.1.2 and libc have already been installed at this point, and their respective header files are known to not require fixing, the fixincludes script is not required. The script may in fact pollute the build environment by installing fixed headers from the host system into GCC's private include directory. The running of the fixincludes script can be suppressed by issuing the following commands:

cp -vi gcc/Makefile.in{,.orig2}
sed 's@\./fixinc\.sh@-c true@' gcc/Makefile.in.orig2 > gcc/Makefile.in
[Important]

Important

The following two commands are critical in ensuring a successful build. Do not skip them.

The next command adjusts the location of the default dynamic linker so it points to /tools:

cp -v gcc/config/i386/linux.h{,.orig}
sed 's@/lib/ld-linux.so.2@/tools/lib/ld-uClibc.so.0@' \
    gcc/config/i386/linux.h.orig > gcc/config/i386/linux.h

The next command removes /usr/include from GCC's include search path. This ensures only our newly installed headers, in /tools/include, are used:

cp -v gcc/config/linux.h{,.orig}
echo "#undef STANDARD_INCLUDE_DIR
#define STANDARD_INCLUDE_DIR 0" >> gcc/config/linux.h

The GCC documentation recommends building outside of the source directory in a dedicated build/object directory:

mkdir -v ../cocoon-build/
cd ../cocoon-build/

Prepare the toolchain for compilation:

../cocoon-toolchain/configure --prefix=/tools \
    --with-local-prefix=/tools --enable-clocale \
    --enable-shared --enable-threads \
    --enable-__cxa_atexit --enable-languages=c,c++ \
    --with-lib-path=/tools/lib --disable-libstdcxx-pch \
    --enable-checking --disable-werror

The meaning of the configure options:

--enable-clocale

This option enabled C locale support for the C++ libraries. The uclibc locale model will be automatically detected.

--enable-shared

This switch allows the building of libbfd-2.17.so and libopcodes-2.17.so from the Binutils package. This switch is the default in the GCC package and allows the building of libgcc_s.so.1 and libgcc_eh.a.

--enable-threads

This enables C++ exception handling for multi-threaded code.

--enable-__cxa_atexit

This option allows use of __cxa_atexit, rather than atexit, to register C++ destructors for local statics and global objects. This option is essential for fully standards-compliant handling of destructors. It also affects the C++ ABI, and therefore results in C++ shared libraries and C++ programs that are interoperable with other Linux distributions.

--enable-languages=c,c++

This option ensures that both the C and C++ compilers are built. This option is provided by the specs patch.

--with-lib-path=/tools/lib

This tells the configure script to specify the library search path during the compilation of Binutils, resulting in /tools/lib being passed to the linker. This prevents the linker from searching through library directories on the host.

--disable-libstdcxx-pch

Do not build the pre-compiled header (PCH) for libstdc++. It takes up a lot of space, and we have no use for it.

Compile the toolchain:

make

Install the toolchain:

make install

Libssp uses special header files for the _FORTIFY_SOURCE feature. These headers use the “#include_nextcpp macro. Many GNU packages autoconfigure absolute paths in their private headers, which causes a bug with the “#include_next” macro: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17110. To avoid this the following commands will rename the libc headers and install modified Libssp private headers to /tools/include. Note that the original files remain unmodified:

mv -v /tools/include/{stdio,stdio-uclibc}.h
mv -v /tools/include/{string,string-uclibc}.h
mv -v /tools/include/{unistd,unistd-uclibc}.h

sed -e 's/.*include_next.*/#include <stdio-uclibc.h>/' -e 's@ssp.h@ssp/ssp.h@' \
    `dirname $(gcc -print-libgcc-file-name)`/include/ssp/stdio.h \
    > /tools/include/stdio.h

sed -e 's/.*include_next.*/#include <string-uclibc.h>/' -e 's@ssp.h@ssp/ssp.h@' \
    `dirname $(gcc -print-libgcc-file-name)`/include/ssp/string.h \
    > /tools/include/string.h

sed -e 's/.*include_next.*/#include <unistd-uclibc.h>/' -e 's@ssp.h@ssp/ssp.h@' \
    `dirname $(gcc -print-libgcc-file-name)`/include/ssp/unistd.h \
    > /tools/include/unistd.h

You may notice we get a linker warning every time we link to libssp.so because this library contains the gets function. libssp.so contains the gets function in order to protect it, so these warnings can be ignored, and there's no practical way of preventing the warnings.

[Important]

Important

Confirm the new compiler is working as expected. This program is a perfect example of a very bad thing. It allows user input to go directly to the strcat function without checking the size of the source or destination buffer. This regression program is from the NetBSD project. First test SSP:

cat > strcat-overflow.c << "EOF"
#include <stdio.h>
#include <string.h>
int
main(int argc, char *argv[])
{
        char b[10];
        (void)strcpy(b, "1");
        (void)strcat(b, argv[1]);
        (void)printf("%s\n", b);
        return 0;
}
EOF
gcc -o strcat-overflow strcat-overflow.c -U_FORTIFY_SOURCE
./strcat-overflow 0123456
./strcat-overflow 0123456789

This should display:

$ ./strcat-overflow 0123456
10123456
$ ./strcat-overflow 0123456789
*** stack smashing detected ***: ./strcat-overflow terminated
Aborted

Next test _FORTIFY_SOURCE:

gcc -o strcat-overflow strcat-overflow.c -fno-stack-protector
./strcat-overflow abcdefg
./strcat-overflow abcdefghij

This should display:

$ ./strcat-overflow abcdefg
1abcdefg
./strcat-overflow abcdefghij
*** buffer overflow detected ***: ./strcat-overflow terminated
Aborted

The exact output can vary depending on the compiler and libc versions, the "Aborted" line is what's important. Also check that the program is position independent:

readelf -ld strcat-overflow | \
    grep -E 'Shared object|TEXTREL'

This should display:

$ readelf -ld strcat-overflow | \
    grep -E 'Shared object|TEXTREL'
Elf file type is DYN (Shared object file)

If there are any segementation faults, or TEXTREL is displayed, then something is not working correctly, and you should verify the installation.

Next, prepare the linker for the “Re-adjusting” phase in the next chapter:

make -C ld clean
make -C ld LIB_PATH=/usr/lib:/lib
make -C ld EXEEXT=-new install-exec-local

Details on this package are located in Section 6.14.2, “Contents of Binutils” and Section 6.14.3, “Contents of GCC.”