--- /home/ftp/pub/svn/hardened/toolchain-psm/eclass/toolchain.eclass 2006-10-08 20:18:47 +0200 +++ ./toolchain.eclass 2006-10-09 17:00:37 +0200 @@ -1,6 +1,6 @@ # Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/eclass/toolchain.eclass,v 1.314 2006/10/02 22:35:50 vapier Exp $ +# $ HOMEPAGE="http://gcc.gnu.org/" LICENSE="GPL-2 LGPL-2.1" @@ -455,7 +455,7 @@ [[ ${GCCMAJOR} -lt 4 ]] && return 1 # gcc 4.1 and above have native ssp support - [[ ( ${GCCMAJOR} -gt 4 || ${GCCMINOR} -ge 1 ) ]] && return 0 + tc_version_is_at_least "4.1" && return 0 # gcc 4.0 might have the gcc 4.1 ssp support backport applied grep -q TARGET_LIBC_PROVIDES_SSP ${S}/gcc/gcc.c @@ -483,6 +483,9 @@ want_pie() { _want_stuff PIE_VER !nopie ; } want_ssp() { gcc_has_native_ssp || _want_stuff PP_VER !nossp ; } +want_minispecs() { + version_is_at_least "9.0.4" ${PIE_VER} && want_pie +} want_split_specs() { [[ ${SPLIT_SPECS} == "true" ]] && want_pie } @@ -551,6 +554,7 @@ gcc_common_hard="-DEFAULT_RELRO -DEFAULT_BIND_NOW" # configure to build with the hardened GCC specs as the default +# Legacy code for pre-minispecs compilers. make_gcc_hard() { if hardened_gcc_works ; then einfo "Updating gcc to use automatic PIE + SSP building ..." @@ -583,41 +587,38 @@ _create_specs_file() { # Usage: _create_specs_file local uflag=$1 name=$2 flags=${*:3} - ebegin "Creating a ${name} gcc specs file" - pushd "${WORKDIR}"/build/gcc > /dev/null - if [[ -z ${uflag} ]] || use ${uflag} ; then - # backup the compiler first - cp Makefile Makefile.orig - sed -i -e '/^HARD_CFLAGS/s:=.*:='"${flags}"':' Makefile - mv xgcc xgcc.foo - mv gcc.o gcc.o.foo - emake -s xgcc - $(XGCC) -dumpspecs > "${WORKDIR}"/build/${name}.specs - # restore everything to normal - mv gcc.o.foo gcc.o - mv xgcc.foo xgcc - mv Makefile.orig Makefile - else - $(XGCC) -dumpspecs > "${WORKDIR}"/build/${name}.specs + if want_minispecs ; then + # instead of copying we should generate them from the micro specs + # using concat_minispecs() + ebegin "Copying ${name} gcc specs file" + cp -f ${GCC_FILESDIR}/specs/${name}.specs "${WORKDIR}"/build/ || die "failed copying specs file" + else + ebegin "Creating a ${name} gcc specs file" + pushd "${WORKDIR}"/build/gcc > /dev/null + if [[ -z ${uflag} ]] || use ${uflag} ; then + # backup the compiler first + cp Makefile Makefile.orig + sed -i -e '/^HARD_CFLAGS/s:=.*:='"${flags}"':' Makefile + mv xgcc xgcc.foo + mv gcc.o gcc.o.foo + emake -s xgcc + $(XGCC) -dumpspecs > "${WORKDIR}"/build/${name}.specs + # restore everything to normal + mv gcc.o.foo gcc.o + mv xgcc.foo xgcc + mv Makefile.orig Makefile + else + $(XGCC) -dumpspecs > "${WORKDIR}"/build/${name}.specs + fi + popd > /dev/null fi - popd > /dev/null - eend $([[ -s ${WORKDIR}/build/${name}.specs ]] ; echo $?) -} - -# requires the multi GCC_SPECS patch from kevquinn and pie-ssp >= 9.0.3 -__create_specs_file() { - # Usage: __create_specs_file - local uflag=$1 name=$2 flags=${*:3} - ebegin "Copying a ${name} gcc specs file" - cp ${GCC_FILESDIR}/specs/${name}.specs "${WORKDIR}"/build/ || die "failed copying specs file" eend $([[ -s ${WORKDIR}/build/${name}.specs ]] ; echo $?) } - -create_vanilla_specs_file() { __create_specs_file hardened vanilla ; } -create_hardened_specs_file() { __create_specs_file !hardened hardened ${gcc_common_hard} -DEFAULT_PIE_SSP ; } -create_hardenednossp_specs_file() { __create_specs_file "" hardenednossp ${gcc_common_hard} -DEFAULT_PIE ; } -create_hardenednopie_specs_file() { __create_specs_file "" hardenednopie ${gcc_common_hard} -DEFAULT_SSP ; } -create_hardenednopiessp_specs_file() { __create_specs_file "" hardenednopiessp ${gcc_common_hard} ; } +create_vanilla_specs_file() { _create_specs_file hardened vanilla ; } +create_hardened_specs_file() { _create_specs_file !hardened hardened ${gcc_common_hard} -DEFAULT_PIE_SSP ; } +create_hardenednossp_specs_file() { _create_specs_file "" hardenednossp ${gcc_common_hard} -DEFAULT_PIE ; } +create_hardenednopie_specs_file() { _create_specs_file "" hardenednopie ${gcc_common_hard} -DEFAULT_SSP ; } +create_hardenednopiessp_specs_file() { _create_specs_file "" hardenednopiessp ${gcc_common_hard} ; } split_out_specs_files() { local s spec_list="hardenednopiessp vanilla" @@ -796,19 +797,30 @@ add_profile_eselect_conf "${compiler_config_file}" "${abi}" hardened fi - if hardened_gcc_works || hardened_gcc_works pie ; then + hardened_gcc_works pie && add_profile_eselect_conf "${compiler_config_file}" "${abi}" hardenednossp - fi - if hardened_gcc_works || hardened_gcc_works ssp ; then + hardened_gcc_works ssp && add_profile_eselect_conf "${compiler_config_file}" "${abi}" hardenednopie - fi add_profile_eselect_conf "${compiler_config_file}" "${abi}" hardenednopiessp fi done } +concat_minispecs() { + local entry spec + while read entry; do + spec=${entry/\%include <} + if [[ ${spec} == ${entry} ]]; then + printf "%s\n" "$entry" >> $2 + else + spec=${spec/>} + cat "${GCC_FILESDIR}"/specs/${spec} >> $2 + fi + done < ${GCC_FILESDIR}/specs/${1}.specs +} + #----<< specs + env.d logic >>---- #---->> pkg_* <<---- @@ -978,8 +990,8 @@ # the necessary support want_pie && use hardened && glibc_have_pie - if use hardened ; then - einfo "updating configuration to build hardened GCC" + if use hardened && ! want_minispecs ; then + einfo "updating configuration to build hardened GCC, old-style" make_gcc_hard || die "failed to make gcc hard" fi } @@ -1042,19 +1054,19 @@ epatch "${WORKDIR}"/patch fi if [[ -n ${UCLIBC_VER} ]] ; then - if tc_version_is_at_least 4.1.2 ; then - if [[ ! -d libstdc++-v3/config/locale/uclibc ]] ; then - mkdir libstdc++-v3/config/locale/uclibc && - cp libstdc++-v3/config/locale/gnu/* \ - libstdc++-v3/config/locale/uclibc/ - # gcc-4.2.0 has this already - if [[ ! -d libstdc++-v3/config/os/uclibc ]] ; then - mkdir libstdc++-v3/config/os/uclibc && - cp libstdc++-v3/config/os/gnu-linux/* \ - libstdc++-v3/config/os/uclibc/ - fi + if tc_version_is_at_least 4.1.2 ; then + if [[ ! -d libstdc++-v3/config/locale/uclibc ]] ; then + mkdir libstdc++-v3/config/locale/uclibc && + cp libstdc++-v3/config/locale/gnu/* \ + libstdc++-v3/config/locale/uclibc/ + # gcc-4.2.0 has this already + if [[ ! -d libstdc++-v3/config/os/uclibc ]] ; then + mkdir libstdc++-v3/config/os/uclibc && + cp libstdc++-v3/config/os/gnu-linux/* \ + libstdc++-v3/config/os/uclibc/ fi fi + fi guess_patch_type_in_dir "${WORKDIR}"/uclibc EPATCH_MULTI_MSG="Applying uClibc patches ..." \ epatch "${WORKDIR}"/uclibc @@ -1066,7 +1078,7 @@ ${ETYPE}_src_unpack || die "failed to ${ETYPE}_src_unpack" - # protoize doesn't build on FreeBSD, skip it + # protoize don't build on FreeBSD, skip it if ! is_crosscompile && ! use elibc_FreeBSD ; then # enable protoize / unprotoize sed -i -e '/^LANGUAGES =/s:$: proto:' "${S}"/gcc/Makefile.in @@ -1438,11 +1450,6 @@ BOOT_CFLAGS=${BOOT_CFLAGS-"$(get_abi_CFLAGS) ${CFLAGS}"} fi - if gcc_has_native_ssp ; then - STAGE1_CFLAGS="${STAGE1_CFLAGS} -DTARGET_LIBC_PROVIDES_SSP" - BOOT_CFLAGS="${BOOT_CFLAGS} -DTARGET_LIBC_PROVIDES_SSP" - fi - pushd "${WORKDIR}"/build einfo "Running make LDFLAGS=\"${LDFLAGS}\" STAGE1_CFLAGS=\"${STAGE1_CFLAGS}\" LIBPATH=\"${LIBPATH}\" BOOT_CFLAGS=\"${BOOT_CFLAGS}\" ${GCC_MAKE_TARGET}" @@ -1560,6 +1567,19 @@ einfo "CFLAGS=\"${CFLAGS}\"" einfo "CXXFLAGS=\"${CXXFLAGS}\"" + if use hardened && want_minispecs ; then + if hardened_gcc_works ; then + concat_minispecs hardened "${WORKDIR}"/build.specs + elif hardened_gcc_works pie ; then + concat_minispecs hardenednossp "${WORKDIR}"/build.specs + elif hardened_gcc_works ssp ; then + concat_minispecs hardenednopie "${WORKDIR}"/build.specs + else + concat_minispecs hardenednopiessp "${WORKDIR}"/build.specs + fi + export GCC_SPECS="${WORKDIR}"/build.specs + fi + # Build in a separate build tree mkdir -p "${WORKDIR}"/build pushd "${WORKDIR}"/build > /dev/null @@ -1581,7 +1601,7 @@ gcc_do_make ${GCC_MAKE_TARGET} # Do not create multiple specs files for PIE+SSP if boundschecking is in - # USE, as we disable PIE+SSP when it is. + # USE, as we disable PIE+SSP when it is (comment is obsolete) if [[ ${ETYPE} == "gcc-compiler" ]] && want_split_specs ; then split_out_specs_files || die "failed to split out specs" fi @@ -1673,14 +1693,16 @@ if want_split_specs ; then if use hardened ; then create_gcc_env_entry vanilla + elif hardened_gcc_works ; then + create_gcc_env_entry hardened fi - ! use hardened && hardened_gcc_works && create_gcc_env_entry hardened - if hardened_gcc_works || hardened_gcc_works pie ; then + + hardened_gcc_works pie && create_gcc_env_entry hardenednossp - fi - if hardened_gcc_works || hardened_gcc_works ssp ; then + + hardened_gcc_works ssp && create_gcc_env_entry hardenednopie - fi + create_gcc_env_entry hardenednopiessp insinto ${LIBPATH} @@ -1806,6 +1828,31 @@ # Create config files for eselect-compiler create_eselect_conf + + # Build system specs file which, if it exists, must be a complete set of + # specs as it completely and unconditionally overrides the builtin specs. + if use hardened && want_minispecs ; then + $(XGCC) -dumpspecs > "${WORKDIR}"/build/specs + if hardened_gcc_works ; then + for s in pie ssp sspall znow zrelro; do + cat "${GCC_FILESDIR}"/specs/${s}.specs >> "${WORKDIR}"/build/specs + done + elif hardened_gcc_works pie ; then + for s in pie znow zrelro; do + cat "${GCC_FILESDIR}"/specs/${s}.specs >> "${WORKDIR}"/build/specs + done + elif hardened_gcc_works ssp ; then + for s in ssp sspall znow zrelro; do + cat "${GCC_FILESDIR}"/specs/${s}.specs >> "${WORKDIR}"/build/specs + done + else + for s in znow zrelro; do + cat "${GCC_FILESDIR}"/specs/${s}.specs >> "${WORKDIR}"/build/specs + done + fi + insinto ${LIBPATH} + doins "${WORKDIR}"/build/specs || die "Failed to install system specs" + fi } # Move around the libs to the right location. For some reason, @@ -1896,7 +1943,7 @@ [[ -n ${UCLIBC_VER} ]] && \ unpack gcc-${UCLIBC_GCC_VER}-uclibc-patches-${UCLIBC_VER}.tar.bz2 - if want_ssp && ! gcc_has_native_ssp; then + if want_ssp && ! gcc_has_native_ssp ; then if [[ -n ${PP_FVER} ]] ; then # The gcc 3.4 propolice versions are meant to be unpacked to ${S} pushd ${S:-$(gcc_get_s_dir)} > /dev/null @@ -1977,16 +2024,16 @@ # patch in ProPolice Stack Smashing protection do_gcc_SSP_patches() { - # PARISC has no love ... it's our stack :( - if [[ $(tc-arch) == "hppa" ]] || \ - ! want_ssp || \ - (want_boundschecking && [[ ${HTB_EXCLUSIVE} == "true" ]]) - then - do_gcc_stub ssp - return 0 - fi - if ! gcc_has_native_ssp ; then + # PARISC has no love ... it's our stack :( + if [[ $(tc-arch) == "hppa" ]] || \ + ! want_ssp || \ + (want_boundschecking && [[ ${HTB_EXCLUSIVE} == "true" ]]) + then + do_gcc_stub ssp + return 0 + fi + local ssppatch local sspdocs @@ -2021,7 +2068,8 @@ if [[ ${PN} == "gcc" && ${sspdocs} == "no" ]] ; then epatch "${GCC_FILESDIR}"/pro-police-docs.patch fi - # gcc_has_native_ssp + + release_version="${release_version}, ssp-${PP_FVER:-${PP_GCC_VER}-${PP_VER}}" fi # Don't build crtbegin/end with ssp @@ -2030,7 +2078,7 @@ # Don't build libgcc with ssp sed -e 's|^LIBGCC2_CFLAGS = |LIBGCC2_CFLAGS = -fno-stack-protector |'\ - -i gcc/Makefile.in || die "Failed to update gcc!" + -i gcc/Makefile.in || die "Failed to update libgcc2!" # if gcc in a stage3 defaults to ssp, is version 3.4.0 and a stage1 is built # the build fails building timevar.o (3.4.x) or ggc-common.o (4.x) w/: @@ -2039,53 +2087,44 @@ # this should be moved out of do_GCC_ssp_patches(), because it fails if gcc # is hardened, but we build w/ nossp as well if tc_version_is_at_least 3.4.0 ; then - # useless check - #if gcc -dumpspecs | grep -q "fno-stack-protector:" ; then - if tc_version_is_at_least 4.0.0 ; then - if [[ ${GCCMINOR} -lt 2 ]] ; then - epatch "${GCC_FILESDIR}"/4.0.2/gcc-4.0.2-cc1-no-stack-protector.patch - else - epatch "${GCC_FILESDIR}"/4.2.0/gcc-4.2.0-cc1-no-stack-protector.patch - fi + if tc_version_is_at_least 4.0.0 ; then + if [[ ${GCCMINOR} -lt 2 ]] ; then + epatch "${GCC_FILESDIR}"/4.0.2/gcc-4.0.2-cc1-no-stack-protector.patch else - epatch "${GCC_FILESDIR}"/3.4.0/gcc-3.4.0-cc1-no-stack-protector.patch + epatch "${GCC_FILESDIR}"/4.2.0/gcc-4.2.0-cc1-no-stack-protector.patch fi - #fi + else + epatch "${GCC_FILESDIR}"/3.4.0/gcc-3.4.0-cc1-no-stack-protector.patch + fi fi - if gcc_has_native_ssp ; then - if [[ ${GCCMAJOR}.${GCCMINOR} == 4.0 ]] ; then - # Indicate that ssp support is a backport + # Indicate that ssp support is a backport, if it's present in 4.0 + gcc_has_native_ssp && + [[ ${GCCMAJOR}.${GCCMINOR} == 4.0 ]] && release_version="${release_version}, ssp-4.1-backport" - fi - else - release_version="${release_version}, ssp-${PP_FVER:-${PP_GCC_VER}-${PP_VER}}" - fi - if want_libssp ; then - update_gcc_for_libssp - else - update_gcc_for_libc_ssp + if ! gcc_has_native_ssp ; then + if want_libssp ; then + update_gcc_for_libssp + else + update_gcc_for_libc_ssp + fi fi } # If glibc or uclibc has been patched to provide the necessary symbols itself, # then lets use those for SSP instead of libgcc. +# Legacy support for ancient gcc-3.x ssp patches. update_gcc_for_libc_ssp() { if libc_has_ssp ; then einfo "Updating gcc to use SSP from libc ..." - if ! gcc_has_native_ssp ; then - # we should better correct the configure check for this, uclibc ok - #sed -e 's|^LIBGCC2_CFLAGS = |LIBGCC2_CFLAGS = -DTARGET_LIBC_PROVIDES_SSP |'\ - #-i "${S}"/gcc/Makefile.in || die "Failed to update gcc!" - #else - sed -e 's|^LIBGCC2_CFLAGS = |LIBGCC2_CFLAGS = -D_LIBC_PROVIDES_SSP_ |'\ + sed -e 's|^LIBGCC2_CFLAGS = |LIBGCC2_CFLAGS = -D_LIBC_PROVIDES_SSP_ |'\ -i "${S}"/gcc/Makefile.in || die "Failed to update gcc!" - fi fi } # a split out non-libc non-libgcc ssp requires additional spec logic changes +# Legacy support for ancient gcc-3.x ssp patches. update_gcc_for_libssp() { einfo "Updating gcc to use SSP from libssp..." sed -e 's|^\(INTERNAL_CFLAGS.*\)$|\1 -D_LIBSSP_PROVIDES_SSP_|' \ @@ -2104,7 +2143,7 @@ && rm -f "${WORKDIR}"/piepatch/*/*-boundschecking-no.patch* \ || rm -f "${WORKDIR}"/piepatch/*/*-boundschecking-yes.patch* - use vanilla && rm -f "${WORKDIR}"/piepatch/*/*uclibc* + (use vanilla || [[ -z ${UCLIBC_VER} ]]) && rm -f "${WORKDIR}"/piepatch/*/*uclibc* guess_patch_type_in_dir "${WORKDIR}"/piepatch/upstream @@ -2115,14 +2154,16 @@ EPATCH_MULTI_MSG="Applying non-default pie patches ..." \ epatch "${WORKDIR}"/piepatch/nondef # adds default pie support (rs6000 too) if DEFAULT_PIE[_SSP] is defined - EPATCH_MULTI_MSG="Applying default pie patches ..." \ - epatch "${WORKDIR}"/piepatch/def + want_minispecs || + EPATCH_MULTI_MSG="Applying default pie patches ..." \ + epatch "${WORKDIR}"/piepatch/def # we want to be able to control the pie patch logic via something other # than ALL_CFLAGS... - sed -e '/^ALL_CFLAGS/iHARD_CFLAGS = ' \ - -e 's|^ALL_CFLAGS = |ALL_CFLAGS = $(HARD_CFLAGS) |' \ - -i "${S}"/gcc/Makefile.in + want_minispecs || + sed -e '/^ALL_CFLAGS/iHARD_CFLAGS = ' \ + -e 's|^ALL_CFLAGS = |ALL_CFLAGS = $(HARD_CFLAGS) |' \ + -i "${S}"/gcc/Makefile.in release_version="${release_version}, pie-${PIE_VER}" }