summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjlh <jlh@FreeBSD.org>2013-06-12 21:12:05 +0000
committerjlh <jlh@FreeBSD.org>2013-06-12 21:12:05 +0000
commit83a1b942fa655a3cf8095e6f80c8aa6f3c4aea6c (patch)
tree692f57730512e680591cd79d61e1911c255a95e1
parent193f745cdd9132c85c5a375c344a26f4013baa1f (diff)
downloadFreeBSD-src-83a1b942fa655a3cf8095e6f80c8aa6f3c4aea6c.zip
FreeBSD-src-83a1b942fa655a3cf8095e6f80c8aa6f3c4aea6c.tar.gz
Turn libc.so into an ld script rather than a symlink pointing to the
real shared object and libssp_nonshared.a. This was the last showstopper that prevented from enabling SSP for ports by default. portmgr@ performed a buildworld which showed no significant breakage with this patch. Details: On i386 for PIC objects, gcc uses the __stack_chk_fail_local hidden symbol instead of calling __stack_chk_fail directly [1]. This happen not only with our gcc-4.2.1 but also with the latest gcc-4.8. If you want the very nasty details, see [2]. OTOH the problem doesn't exist on other architectures. It also doesn't exist with Clang as the latter will somehow manage to create the function in the object file at compile time (contrary to only referencing it through a symbol that will be brought in at link time). In a perfect world, when an object file is compiled with -fstack-protector, it will be linked into a binary or a DSO with this same flag as well, so GCC will add libssp_nonshared.a to the linker command-line. Unfortunately, we don't control softwares in ports and we may have such broken DSO. This is the whole point of this patch. You can reproduce the problem on i386 by compiling a source file into an object file with "-fstack-protector-all -fPIE" and linking it into a binary without "-fstack-protector". This ld script automatically proposes libssp_nonshared.a along with the real libc DSO to the linker. It is important to understand that the object file contained in this library will be pulled in the resulting binary _only if_ the linker notices one of its symbols is needed (i.e. one of the SSP symbol is missing). A theorical performance impact could be when compiling, but my testing showed less than 0.1% of difference. [1] For 32-bit code gcc saves the PIC register setup by using __stack_chk_fail_local hidden function instead of calling __stack_chk_fail directly. See comment line 19460 in: src/contrib/gcc/config/i386/i386.c [2] When compiling a source file to an object file, if you use something which is external to the compilation unit, GCC doesn't know yet if this symbol will be inside or outside the DSO. So it expects the worst case and routes the symbol through the GOT, which means additional space and extra relocation for rtld(1). Declaring a symbol has hidden tells GCC to use the optimal route (no GOT), but on the other hand this means the symbol has to be provided in the same DSO (namely libssp_nonshared.a). On i386, GCC actually uses an hidden symbol for SSP in PIC objects to save PIC register setup, as said in [1]. PR: ports/138228 PR: ports/168010 Reviewed by: kib, kan
-rw-r--r--lib/libc/Makefile1
-rw-r--r--lib/libc/libc.ldscript2
2 files changed, 3 insertions, 0 deletions
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index ed37053..cf2d2aa 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -23,6 +23,7 @@ LIBC_ARCH=${MACHINE_CPUARCH}
# to CFLAGS below. -DSYSLIBC_SCCS affects just the system call stubs.
LIB=c
SHLIB_MAJOR= 7
+SHLIB_LDSCRIPT=libc.ldscript
WARNS?= 2
CFLAGS+=-I${.CURDIR}/include -I${.CURDIR}/../../include
CFLAGS+=-I${.CURDIR}/${LIBC_ARCH}
diff --git a/lib/libc/libc.ldscript b/lib/libc/libc.ldscript
new file mode 100644
index 0000000..a5c8a27
--- /dev/null
+++ b/lib/libc/libc.ldscript
@@ -0,0 +1,2 @@
+/* $FreeBSD$ */
+GROUP ( @@SHLIB@@ @@LIBDIR@@/libssp_nonshared.a )
OpenPOWER on IntegriCloud