fix musl-gcc.specs.sh to correctly handle -static-pie

Submitted by Ferdi265 on May 28, 2019, 8:19 p.m.

Details

Message ID 9ea47b05-2298-dc48-d938-f1593c1d0d3c@gmail.com
State New
Series "fix musl-gcc.specs.sh to correctly handle -static-pie"
Headers show

Commit Message

Ferdi265 May 28, 2019, 8:19 p.m.
Hello,

Today I wanted to use musl-gcc to build -static-pie binaries. I noticed
that this does not work (musl-libc is still linked as a shared library
and is also still requested as an interpreter).

Looking into the musl-gcc.specs file the bug was obvious: rcrt1.o was
not used as a startfile, and neither -no-dynamic-linker nor -static were
passed to the linker.

This patch fixes this by actually using rcrt1.o and passing the linker
options when -static-pie is given.

I don't have much experience with the specifics of gcc .spec files and
which options need to be passed, but this seems to work with all
variations of -shared, -static, and -static-pie that I've tried.

Here (https://github.com/Ferdi265/musl) is the repository with the patch
on GitHub, and I've also attached the patch below.

Greetings,
Ferdinand "Ferdi265" Bachmann

--- PATCH BELOW ---

From 070bce8f7e508a951d3b65da227b2fca3a65f37b Mon Sep 17 00:00:00 2001
From: Ferdinand Bachmann <theferdi265@gmail.com>
Date: Tue, 28 May 2019 21:53:25 +0200
Subject: [PATCH] fix musl-gcc.specs.sh to correctly handle -static-pie

---
 tools/musl-gcc.specs.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

%{rdynamic:-export-dynamic}

 *esp_link:

Patch hide | download patch | download mbox

diff --git a/tools/musl-gcc.specs.sh b/tools/musl-gcc.specs.sh
index 30492574..7206cb25 100644
--- a/tools/musl-gcc.specs.sh
+++ b/tools/musl-gcc.specs.sh
@@ -17,13 +17,13 @@  cat <<EOF
 libgcc.a%s %:if-exists(libgcc_eh.a%s)

 *startfile:
-%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s
+%{static-pie: $libdir/rcrt1.o} %{!static-pie: %{!shared:
$libdir/Scrt1.o}} $libdir/crti.o crtbeginS.o%s

 *endfile:
 crtendS.o%s $libdir/crtn.o

 *link:
--dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static}
%{rdynamic:-export-dynamic}
+%{static-pie:-no-dynamic-linker -static} %{!static-pie:-dynamic-linker
$ldso} -nostdlib %{shared:-shared} %{static:-static}

Comments

Rich Felker May 30, 2019, 3:17 a.m.
On Tue, May 28, 2019 at 10:19:18PM +0200, Ferdi265 wrote:
> Hello,
> 
> Today I wanted to use musl-gcc to build -static-pie binaries. I noticed
> that this does not work (musl-libc is still linked as a shared library
> and is also still requested as an interpreter).
> 
> Looking into the musl-gcc.specs file the bug was obvious: rcrt1.o was
> not used as a startfile, and neither -no-dynamic-linker nor -static were
> passed to the linker.
> 
> This patch fixes this by actually using rcrt1.o and passing the linker
> options when -static-pie is given.
> 
> I don't have much experience with the specifics of gcc .spec files and
> which options need to be passed, but this seems to work with all
> variations of -shared, -static, and -static-pie that I've tried.
> 
> Here (https://github.com/Ferdi265/musl) is the repository with the patch
> on GitHub, and I've also attached the patch below.
> 
> Greetings,
> Ferdinand "Ferdi265" Bachmann
> 
> --- PATCH BELOW ---
> 
> From 070bce8f7e508a951d3b65da227b2fca3a65f37b Mon Sep 17 00:00:00 2001
> From: Ferdinand Bachmann <theferdi265@gmail.com>
> Date: Tue, 28 May 2019 21:53:25 +0200
> Subject: [PATCH] fix musl-gcc.specs.sh to correctly handle -static-pie
> 
> ---
>  tools/musl-gcc.specs.sh | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/musl-gcc.specs.sh b/tools/musl-gcc.specs.sh
> index 30492574..7206cb25 100644
> --- a/tools/musl-gcc.specs.sh
> +++ b/tools/musl-gcc.specs.sh
> @@ -17,13 +17,13 @@ cat <<EOF
>  libgcc.a%s %:if-exists(libgcc_eh.a%s)
> 
>  *startfile:
> -%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s
> +%{static-pie: $libdir/rcrt1.o} %{!static-pie: %{!shared:
> $libdir/Scrt1.o}} $libdir/crti.o crtbeginS.o%s
> 
>  *endfile:
>  crtendS.o%s $libdir/crtn.o
> 
>  *link:
> --dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static}
> %{rdynamic:-export-dynamic}
> +%{static-pie:-no-dynamic-linker -static} %{!static-pie:-dynamic-linker
> $ldso} -nostdlib %{shared:-shared} %{static:-static}
> %{rdynamic:-export-dynamic}
> 
>  *esp_link:
> 

This looks okay-ish, but could be improved. GCC spec syntax doesn't
require separate static-pie and !static-pie conditions; it supports
"else" with notation:

	%{static-pie:-no-dynamic-linker -static;-dynamic-linker $ldso}

There's also the question of whether we should make -static -pie work
like it's intended to by us, or like gcc does it upstream (ignoring
-pie). I think it's hard to duplicate the behavior we want since it
depends on knowing if the compiler was built as default-pie, so the
way you've done it is probably the best we can easily do, and at least
non-broken.

Anyone else have comments on this?

Rich
Fangrui Song May 30, 2019, 6:20 a.m.
On 2019-05-29, Rich Felker wrote:
>On Tue, May 28, 2019 at 10:19:18PM +0200, Ferdi265 wrote:
>> Hello,
>>
>> Today I wanted to use musl-gcc to build -static-pie binaries. I noticed
>> that this does not work (musl-libc is still linked as a shared library
>> and is also still requested as an interpreter).
>>
>> Looking into the musl-gcc.specs file the bug was obvious: rcrt1.o was
>> not used as a startfile, and neither -no-dynamic-linker nor -static were
>> passed to the linker.
>>
>> This patch fixes this by actually using rcrt1.o and passing the linker
>> options when -static-pie is given.
>>
>> I don't have much experience with the specifics of gcc .spec files and
>> which options need to be passed, but this seems to work with all
>> variations of -shared, -static, and -static-pie that I've tried.
>>
>> Here (https://github.com/Ferdi265/musl) is the repository with the patch
>> on GitHub, and I've also attached the patch below.
>>
>> Greetings,
>> Ferdinand "Ferdi265" Bachmann
>>
>> --- PATCH BELOW ---
>>
>> From 070bce8f7e508a951d3b65da227b2fca3a65f37b Mon Sep 17 00:00:00 2001
>> From: Ferdinand Bachmann <theferdi265@gmail.com>
>> Date: Tue, 28 May 2019 21:53:25 +0200
>> Subject: [PATCH] fix musl-gcc.specs.sh to correctly handle -static-pie
>>
>> ---
>>  tools/musl-gcc.specs.sh | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/tools/musl-gcc.specs.sh b/tools/musl-gcc.specs.sh
>> index 30492574..7206cb25 100644
>> --- a/tools/musl-gcc.specs.sh
>> +++ b/tools/musl-gcc.specs.sh
>> @@ -17,13 +17,13 @@ cat <<EOF
>>  libgcc.a%s %:if-exists(libgcc_eh.a%s)
>>
>>  *startfile:
>> -%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s
>> +%{static-pie: $libdir/rcrt1.o} %{!static-pie: %{!shared:
>> $libdir/Scrt1.o}} $libdir/crti.o crtbeginS.o%s
>>
>>  *endfile:
>>  crtendS.o%s $libdir/crtn.o
>>
>>  *link:
>> --dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static}
>> %{rdynamic:-export-dynamic}
>> +%{static-pie:-no-dynamic-linker -static} %{!static-pie:-dynamic-linker
>> $ldso} -nostdlib %{shared:-shared} %{static:-static}
>> %{rdynamic:-export-dynamic}
>>
>>  *esp_link:
>>
>
>This looks okay-ish, but could be improved. GCC spec syntax doesn't
>require separate static-pie and !static-pie conditions; it supports
>"else" with notation:
>
>	%{static-pie:-no-dynamic-linker -static;-dynamic-linker $ldso}
>
>There's also the question of whether we should make -static -pie work
>like it's intended to by us, or like gcc does it upstream (ignoring
>-pie). I think it's hard to duplicate the behavior we want since it
>depends on knowing if the compiler was built as default-pie, so the
>way you've done it is probably the best we can easily do, and at least
>non-broken.
>
>Anyone else have comments on this?

gcc -dumpspecs says:

%{static-pie:-static -pie --no-dynamic-linker -z text}

Do we want to specify -z text?

In ld.bfd and gold, -z notext is the default. If text relocations are needed:

-z notext: allow and emit DF_TEXTREL. DF_TEXTREL is not emitted if there is no text relocation.
-z text: error
In lld, -z text is the default (this change is a no-op).

-z text: error on text relocations
-z notext: allow text relocations, and emit DF_TEXTREL no matter whether text relocations exist.


While comparing the differences, I also came across this rule:

%{!static|static-pie:--eh-frame-hdr}

> It means "pass --eh-frame-hdr to ld if -static isn't used or -static-pie
> is used since -static-pie needs PT_GNU_EH_FRAME segment.

This is related to PT_GNU_EH_FRAME (it is produced if .eh_frame_hdr exists) and various unwinders.
I'm not particularly clear about the internals. Some related links:

https://reviews.llvm.org/D19029 FreeBSD folk said LLVM's libunwind needed this on ARM
  I think this piece of code is relevant
  https://github.com/llvm-mirror/libunwind/blob/master/src/AddressSpace.hpp#L532
https://reviews.llvm.org/D43203 clang -static adds --eh-frame-hdr unconditionally
https://www.openwall.com/lists/musl/2014/06/16/2 Re: gcc'c crtstuff.c: a musl-related experience
Szabolcs Nagy May 30, 2019, 10:52 a.m.
* Fangrui Song <i@maskray.me> [2019-05-30 14:20:44 +0800]:
> On 2019-05-29, Rich Felker wrote:
> > On Tue, May 28, 2019 at 10:19:18PM +0200, Ferdi265 wrote:
> > > Hello,
> > > 
> > > Today I wanted to use musl-gcc to build -static-pie binaries. I noticed
> > > that this does not work (musl-libc is still linked as a shared library
> > > and is also still requested as an interpreter).
> > > 
> > > Looking into the musl-gcc.specs file the bug was obvious: rcrt1.o was
> > > not used as a startfile, and neither -no-dynamic-linker nor -static were
> > > passed to the linker.
> > > 
> > > This patch fixes this by actually using rcrt1.o and passing the linker
> > > options when -static-pie is given.
> > > 
> > > I don't have much experience with the specifics of gcc .spec files and
> > > which options need to be passed, but this seems to work with all
> > > variations of -shared, -static, and -static-pie that I've tried.
> > > 
> > > Here (https://github.com/Ferdi265/musl) is the repository with the patch
> > > on GitHub, and I've also attached the patch below.
> > > 
> > > Greetings,
> > > Ferdinand "Ferdi265" Bachmann
> > > 
> > > --- PATCH BELOW ---
> > > 
> > > From 070bce8f7e508a951d3b65da227b2fca3a65f37b Mon Sep 17 00:00:00 2001
> > > From: Ferdinand Bachmann <theferdi265@gmail.com>
> > > Date: Tue, 28 May 2019 21:53:25 +0200
> > > Subject: [PATCH] fix musl-gcc.specs.sh to correctly handle -static-pie
> > > 
> > > ---
> > >  tools/musl-gcc.specs.sh | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/tools/musl-gcc.specs.sh b/tools/musl-gcc.specs.sh
> > > index 30492574..7206cb25 100644
> > > --- a/tools/musl-gcc.specs.sh
> > > +++ b/tools/musl-gcc.specs.sh
> > > @@ -17,13 +17,13 @@ cat <<EOF
> > >  libgcc.a%s %:if-exists(libgcc_eh.a%s)
> > > 
> > >  *startfile:
> > > -%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s
> > > +%{static-pie: $libdir/rcrt1.o} %{!static-pie: %{!shared:
> > > $libdir/Scrt1.o}} $libdir/crti.o crtbeginS.o%s
> > > 
> > >  *endfile:
> > >  crtendS.o%s $libdir/crtn.o
> > > 
> > >  *link:
> > > --dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static}
> > > %{rdynamic:-export-dynamic}
> > > +%{static-pie:-no-dynamic-linker -static} %{!static-pie:-dynamic-linker
> > > $ldso} -nostdlib %{shared:-shared} %{static:-static}
> > > %{rdynamic:-export-dynamic}
> > > 
> > >  *esp_link:
> > > 
> > 
> > This looks okay-ish, but could be improved. GCC spec syntax doesn't
> > require separate static-pie and !static-pie conditions; it supports
> > "else" with notation:
> > 
> > 	%{static-pie:-no-dynamic-linker -static;-dynamic-linker $ldso}
> > 
> > There's also the question of whether we should make -static -pie work
> > like it's intended to by us, or like gcc does it upstream (ignoring
> > -pie). I think it's hard to duplicate the behavior we want since it
> > depends on knowing if the compiler was built as default-pie, so the
> > way you've done it is probably the best we can easily do, and at least
> > non-broken.
> > 
> > Anyone else have comments on this?
> 
> gcc -dumpspecs says:
> 
> %{static-pie:-static -pie --no-dynamic-linker -z text}
> 
> Do we want to specify -z text?

musl does not really support text rels so
arguably -z text should be always passed.

but since it's just a diagnostic option it
is not strictly necessary, just userfriendly.

> 
> In ld.bfd and gold, -z notext is the default. If text relocations are needed:
> 
> -z notext: allow and emit DF_TEXTREL. DF_TEXTREL is not emitted if there is no text relocation.
> -z text: error
> In lld, -z text is the default (this change is a no-op).
> 
> -z text: error on text relocations
> -z notext: allow text relocations, and emit DF_TEXTREL no matter whether text relocations exist.
> 
> 
> While comparing the differences, I also came across this rule:
> 
> %{!static|static-pie:--eh-frame-hdr}
> 
> > It means "pass --eh-frame-hdr to ld if -static isn't used or -static-pie
> > is used since -static-pie needs PT_GNU_EH_FRAME segment.
> 
> This is related to PT_GNU_EH_FRAME (it is produced if .eh_frame_hdr exists) and various unwinders.
> I'm not particularly clear about the internals. Some related links:

allows unwinding across or within an elf module
without load-time registration of the module with
the unwinder (registration implies single unwinder
instance with global data).

(with eh-frame-hdr an unwinder can find the data
using dl_iterate_phdr, no registration is needed)

i think the difference between static and static-pie
exists because different compiler startup code
(crtbeginT.o vs crtbeginS.o) gets linked in, the first
uses the registry (__register_frame_info) the second
assumes eh-frame-hdr.

> 
> https://reviews.llvm.org/D19029 FreeBSD folk said LLVM's libunwind needed this on ARM
>  I think this piece of code is relevant
>  https://github.com/llvm-mirror/libunwind/blob/master/src/AddressSpace.hpp#L532
> https://reviews.llvm.org/D43203 clang -static adds --eh-frame-hdr unconditionally
> https://www.openwall.com/lists/musl/2014/06/16/2 Re: gcc'c crtstuff.c: a musl-related experience