diff mbox

Add -lssp_nonshared to LINK_SSP_SPEC

Message ID 201201101514.40392.tijl@coosemans.org
State New
Headers show

Commit Message

Tijl Coosemans Jan. 10, 2012, 2:14 p.m. UTC
On targets where libc implements stack protector functions (GNU libc,
FreeBSD libc), and where gcc (as an optimisation) generates calls to
a locally defined __stack_chk_fail_local instead of directly calling
the global function __stack_chk_fail (e.g. -fpic code on i386), one
must explicitly specify -lssp_nonshared or "-lc -lc_nonshared" on the
command line to statically link in __stack_chk_fail_local.

It would be more convenient if the compiler kept the details of this
target specific optimisation hidden by passing -lssp_nonshared to the
linker internally.

Here's a simple test case that shows the problem on i386-freebsd, but
works just fine on e.g. x86_64 targets:

% cat test.c
int
main( void ) {
    return( 0 );
}
% gcc46 -o test test.c -fstack-protector-all -fPIE
/var/tmp//ccjYQxKu.o: In function `main':
test.c:(.text+0x37): undefined reference to `__stack_chk_fail_local'
/usr/local/bin/ld: test: hidden symbol `__stack_chk_fail_local' isn't defined
/usr/local/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status


I don't have commit access, so please commit when approved.

2011-01-10  Tijl Coosemans  <tijl@coosemans.org>

	* gcc.c [TARGET_LIBC_PROVIDES_SSP] (LINK_SSP_SPEC): Add -lssp_nonshared.

Comments

Richard Biener Jan. 10, 2012, 2:38 p.m. UTC | #1
On Tue, Jan 10, 2012 at 3:14 PM, Tijl Coosemans <tijl@coosemans.org> wrote:
> On targets where libc implements stack protector functions (GNU libc,
> FreeBSD libc), and where gcc (as an optimisation) generates calls to
> a locally defined __stack_chk_fail_local instead of directly calling
> the global function __stack_chk_fail (e.g. -fpic code on i386), one
> must explicitly specify -lssp_nonshared or "-lc -lc_nonshared" on the
> command line to statically link in __stack_chk_fail_local.
>
> It would be more convenient if the compiler kept the details of this
> target specific optimisation hidden by passing -lssp_nonshared to the
> linker internally.
>
> Here's a simple test case that shows the problem on i386-freebsd, but
> works just fine on e.g. x86_64 targets:
>
> % cat test.c
> int
> main( void ) {
>    return( 0 );
> }
> % gcc46 -o test test.c -fstack-protector-all -fPIE
> /var/tmp//ccjYQxKu.o: In function `main':
> test.c:(.text+0x37): undefined reference to `__stack_chk_fail_local'
> /usr/local/bin/ld: test: hidden symbol `__stack_chk_fail_local' isn't defined
> /usr/local/bin/ld: final link failed: Bad value
> collect2: ld returned 1 exit status
>
>
> I don't have commit access, so please commit when approved.

Works fine for me on i?86-linux without -lssp_nonshared (which I do not
have, so linking would fail).

Richard.

> 2011-01-10  Tijl Coosemans  <tijl@coosemans.org>
>
>        * gcc.c [TARGET_LIBC_PROVIDES_SSP] (LINK_SSP_SPEC): Add -lssp_nonshared.
>
> --- gcc/gcc.c.orig
> +++ gcc/gcc.c
> @@ -602,7 +602,7 @@ proper position among the other output f
>
>  #ifndef LINK_SSP_SPEC
>  #ifdef TARGET_LIBC_PROVIDES_SSP
> -#define LINK_SSP_SPEC "%{fstack-protector:}"
> +#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared}"
>  #else
>  #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
>  #endif
Richard Biener Jan. 10, 2012, 2:40 p.m. UTC | #2
On Tue, Jan 10, 2012 at 3:38 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Tue, Jan 10, 2012 at 3:14 PM, Tijl Coosemans <tijl@coosemans.org> wrote:
>> On targets where libc implements stack protector functions (GNU libc,
>> FreeBSD libc), and where gcc (as an optimisation) generates calls to
>> a locally defined __stack_chk_fail_local instead of directly calling
>> the global function __stack_chk_fail (e.g. -fpic code on i386), one
>> must explicitly specify -lssp_nonshared or "-lc -lc_nonshared" on the
>> command line to statically link in __stack_chk_fail_local.
>>
>> It would be more convenient if the compiler kept the details of this
>> target specific optimisation hidden by passing -lssp_nonshared to the
>> linker internally.
>>
>> Here's a simple test case that shows the problem on i386-freebsd, but
>> works just fine on e.g. x86_64 targets:
>>
>> % cat test.c
>> int
>> main( void ) {
>>    return( 0 );
>> }
>> % gcc46 -o test test.c -fstack-protector-all -fPIE
>> /var/tmp//ccjYQxKu.o: In function `main':
>> test.c:(.text+0x37): undefined reference to `__stack_chk_fail_local'
>> /usr/local/bin/ld: test: hidden symbol `__stack_chk_fail_local' isn't defined
>> /usr/local/bin/ld: final link failed: Bad value
>> collect2: ld returned 1 exit status
>>
>>
>> I don't have commit access, so please commit when approved.
>
> Works fine for me on i?86-linux without -lssp_nonshared (which I do not
> have, so linking would fail).

Probably because libc.so is a linker script:

/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a  AS_NEEDED (
/lib64/ld-linux-x86-64.so.2 ) )

and /usr/lib64/libc_nonshared.a provides the symbol.  Why not fix it that
way on *BSD?

Richard.

> Richard.
>
>> 2011-01-10  Tijl Coosemans  <tijl@coosemans.org>
>>
>>        * gcc.c [TARGET_LIBC_PROVIDES_SSP] (LINK_SSP_SPEC): Add -lssp_nonshared.
>>
>> --- gcc/gcc.c.orig
>> +++ gcc/gcc.c
>> @@ -602,7 +602,7 @@ proper position among the other output f
>>
>>  #ifndef LINK_SSP_SPEC
>>  #ifdef TARGET_LIBC_PROVIDES_SSP
>> -#define LINK_SSP_SPEC "%{fstack-protector:}"
>> +#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared}"
>>  #else
>>  #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
>>  #endif
Tijl Coosemans Jan. 10, 2012, 7:50 p.m. UTC | #3
On Tuesday 10 January 2012 15:40:15 Richard Guenther wrote:
> On Tue, Jan 10, 2012 at 3:38 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Tue, Jan 10, 2012 at 3:14 PM, Tijl Coosemans <tijl@coosemans.org> wrote:
>>> On targets where libc implements stack protector functions (GNU libc,
>>> FreeBSD libc), and where gcc (as an optimisation) generates calls to
>>> a locally defined __stack_chk_fail_local instead of directly calling
>>> the global function __stack_chk_fail (e.g. -fpic code on i386), one
>>> must explicitly specify -lssp_nonshared or "-lc -lc_nonshared" on the
>>> command line to statically link in __stack_chk_fail_local.
>>>
>>> It would be more convenient if the compiler kept the details of this
>>> target specific optimisation hidden by passing -lssp_nonshared to the
>>> linker internally.
>>>
>>> Here's a simple test case that shows the problem on i386-freebsd, but
>>> works just fine on e.g. x86_64 targets:
>>>
>>> % cat test.c
>>> int
>>> main( void ) {
>>>    return( 0 );
>>> }
>>> % gcc46 -o test test.c -fstack-protector-all -fPIE
>>> /var/tmp//ccjYQxKu.o: In function `main':
>>> test.c:(.text+0x37): undefined reference to `__stack_chk_fail_local'
>>> /usr/local/bin/ld: test: hidden symbol `__stack_chk_fail_local' isn't defined
>>> /usr/local/bin/ld: final link failed: Bad value
>>> collect2: ld returned 1 exit status
>>>
>>>
>>> I don't have commit access, so please commit when approved.
>>
>> Works fine for me on i?86-linux without -lssp_nonshared (which I do not
>> have, so linking would fail).

So my patch would actually break Linux?

> Probably because libc.so is a linker script:
> 
> /* GNU ld script
>    Use the shared library, but some functions are only in
>    the static library, so try that secondarily.  */
> OUTPUT_FORMAT(elf64-x86-64)
> GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a  AS_NEEDED (
> /lib64/ld-linux-x86-64.so.2 ) )
> 
> and /usr/lib64/libc_nonshared.a provides the symbol.  Why not fix it that
> way on *BSD?

I'll discuss it with some FreeBSD developers. Currently FreeBSD doesn't
use linker scripts anywhere. Would a FreeBSD specific version of the
patch be acceptable? For instance, the version of GCC shipped with
FreeBSD has been patched like this:
http://svnweb.freebsd.org/base/head/contrib/gcc/config/freebsd-spec.h?r1=195697&r2=195696

>>> 2011-01-10  Tijl Coosemans  <tijl@coosemans.org>
>>>
>>>        * gcc.c [TARGET_LIBC_PROVIDES_SSP] (LINK_SSP_SPEC): Add -lssp_nonshared.
>>>
>>> --- gcc/gcc.c.orig
>>> +++ gcc/gcc.c
>>> @@ -602,7 +602,7 @@ proper position among the other output f
>>>
>>>  #ifndef LINK_SSP_SPEC
>>>  #ifdef TARGET_LIBC_PROVIDES_SSP
>>> -#define LINK_SSP_SPEC "%{fstack-protector:}"
>>> +#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared}"
>>>  #else
>>>  #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
>>>  #endif
Richard Biener Jan. 11, 2012, 9:06 a.m. UTC | #4
On Tue, Jan 10, 2012 at 8:50 PM, Tijl Coosemans <tijl@freebsd.org> wrote:
> On Tuesday 10 January 2012 15:40:15 Richard Guenther wrote:
>> On Tue, Jan 10, 2012 at 3:38 PM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Tue, Jan 10, 2012 at 3:14 PM, Tijl Coosemans <tijl@coosemans.org> wrote:
>>>> On targets where libc implements stack protector functions (GNU libc,
>>>> FreeBSD libc), and where gcc (as an optimisation) generates calls to
>>>> a locally defined __stack_chk_fail_local instead of directly calling
>>>> the global function __stack_chk_fail (e.g. -fpic code on i386), one
>>>> must explicitly specify -lssp_nonshared or "-lc -lc_nonshared" on the
>>>> command line to statically link in __stack_chk_fail_local.
>>>>
>>>> It would be more convenient if the compiler kept the details of this
>>>> target specific optimisation hidden by passing -lssp_nonshared to the
>>>> linker internally.
>>>>
>>>> Here's a simple test case that shows the problem on i386-freebsd, but
>>>> works just fine on e.g. x86_64 targets:
>>>>
>>>> % cat test.c
>>>> int
>>>> main( void ) {
>>>>    return( 0 );
>>>> }
>>>> % gcc46 -o test test.c -fstack-protector-all -fPIE
>>>> /var/tmp//ccjYQxKu.o: In function `main':
>>>> test.c:(.text+0x37): undefined reference to `__stack_chk_fail_local'
>>>> /usr/local/bin/ld: test: hidden symbol `__stack_chk_fail_local' isn't defined
>>>> /usr/local/bin/ld: final link failed: Bad value
>>>> collect2: ld returned 1 exit status
>>>>
>>>>
>>>> I don't have commit access, so please commit when approved.
>>>
>>> Works fine for me on i?86-linux without -lssp_nonshared (which I do not
>>> have, so linking would fail).
>
> So my patch would actually break Linux?

Yes.

>> Probably because libc.so is a linker script:
>>
>> /* GNU ld script
>>    Use the shared library, but some functions are only in
>>    the static library, so try that secondarily.  */
>> OUTPUT_FORMAT(elf64-x86-64)
>> GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a  AS_NEEDED (
>> /lib64/ld-linux-x86-64.so.2 ) )
>>
>> and /usr/lib64/libc_nonshared.a provides the symbol.  Why not fix it that
>> way on *BSD?
>
> I'll discuss it with some FreeBSD developers. Currently FreeBSD doesn't
> use linker scripts anywhere. Would a FreeBSD specific version of the
> patch be acceptable? For instance, the version of GCC shipped with
> FreeBSD has been patched like this:
> http://svnweb.freebsd.org/base/head/contrib/gcc/config/freebsd-spec.h?r1=195697&r2=195696

That looks better to me.

Richard.
diff mbox

Patch

--- gcc/gcc.c.orig
+++ gcc/gcc.c
@@ -602,7 +602,7 @@  proper position among the other output f
 
 #ifndef LINK_SSP_SPEC
 #ifdef TARGET_LIBC_PROVIDES_SSP
-#define LINK_SSP_SPEC "%{fstack-protector:}"
+#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared}"
 #else
 #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
 #endif