Patchwork PING^N: [PATCH] Add --enable-static-pie to build static PIE [BZ #19574]

login
register
mail settings
Submitter H.J. Lu
Date Dec. 1, 2017, 6:24 p.m.
Message ID <CAMe9rOpehZgqn6AXyRf8e99eTO8_Vw2+GVgcEyie0cW3fwwe=g@mail.gmail.com>
Download mbox | patch
Permalink /patch/24679/
State New
Headers show

Comments

H.J. Lu - Dec. 1, 2017, 6:24 p.m.
On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote:
> H.J.,
>
> High Level:
>
> At a high level I have no objection with the idea of static PIE executables,
> it makes sense to support such things.

Thanks for your feedbacks.

> My only nit is that we need to do a better job of explaining to users why
> they would use them and under what circumstances. To that end you have a bit
> more work to do in the commit message, install.texit, and NEWS entry.
>
> Design:
>
> I have one design question below which around testing static non-PIE executables
> in a --enable-static-pie build. See below.
>
> Implementation:
>
> Everything looks good except the use of firstword in +link-static-before-libc,
> which I describe below. I think this is a hack and should be changed to better
> represent the expected semantics and structure you are looking to support.

Fixed.

> Thank you for your work in this area.
>
> Look forward to a v2.
>
>> From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001
>> From: "H.J. Lu" <hjl.tools@gmail.com>
>> Date: Mon, 17 Jul 2017 08:17:32 -0700
>> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE
>>  [BZ #19574]
>>
>> Dynamic linker, ld.so, is a standalone program which can be loaded at
>> any address.  This patch adds a configure option, --enable-static-pie,
>> to embed the part of ld.so in static executable to create static position
>> independent executable (static PIE).  A static PIE is similar to static
>> executable, but can be loaded at any address without help from a dynamic
>> linker.  When --enable-static-pie is used to configure glibc, libc.a is
>> built as PIE and all static executables, including tests, are built as
>> static PIE.  The resulting libc.a can be used together with GCC 8 or
>> above to build static PIE with the compiler option, -static-pie.  But
>> GCC 8 isn't required to build glibc with --enable-static-pie.  When an
>> older GCC is used to build glibc with --enable-static-pie, proper input
>> files are passed to linker to create static executables as static PIE,
>> together with "-z text" to prevent dynamic relocations in read-only
>> segments, which are allowed in static PIE.
>
> You write "which are allowed", shouldn't that be "which are not allowed"?

Fixed.

> The commit message must explain the following:
>
> * Why would a user use this feature?
>   - What does it provide over and beyond existing static executables
>
> * How does a user decide to use this feature?
>   - Should everyone use it?
>   - Should you use it if you care about security, and what does it cost?
>
> Please include the answers to these questions in a the next versions
> commit message.

I added :

Static PIE extends address space layout randomization to static
executables.  It provides additional security hardening benefits at
the cost of some memory and performance.

Is this OK?

>> @@ -420,7 +440,7 @@ endif
>>  # Command for statically linking programs with the C library.
>>  ifndef +link-static
>>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
>> -           $(DEFAULT-LDFLAGS-$(@F)) \
>> +           $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \
>
> Is the use of firstword here just a hack to put $(no-pie-ldflag) first so
> you can override it with the subsequent $(default-pie-ldflag)?
>
> It is not a robust design to use firstword here because it implies that the
> DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting.
>
> I would like to see this done some other way. My preference would be for a new
> value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm.
>

I replaced DEFAUTL-LDFLAGS-$(@F) with $($(@F)-no-pie).   Now I have

 # Command for statically linking programs with the C library.
 ifndef +link-static
 +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
-       $(DEFAULT-LDFLAGS-$(@F)) \
+       $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
        $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \

>>
>> diff --git a/NEWS b/NEWS
>> index ab14d1eb1b..61598be94d 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -9,6 +9,11 @@ Version 2.27
>>
>>  Major new features:
>>
>> +* Add --enable-static-pie configure option to build static PIE.  The
>> +  resulting libc.a can be used with the GCC option, -static-pie, which
>> +  is available with GCC 8 or above, to create static position independent
>> +  executable (static PIE).
>> +
>
> The description of a new configure option is relevant only to INSTALL.
>
> We must explain when users would use this feature and why. NEWS entries are
> user facing and must explain the function of the new feature. Does it improve
> security for static binaries? Should users switch to using them instead of
> normal static binaries?
>
> Lastly, we must explain which machines are supported in this initial release
> of the feature. Only x86_64? You need not check all machines, other maintainers
> can check and adjust the NEWS entry, but we have to commit to at least one
> machine supporting this feature, which I assume is x86_64.
>
> For example:
>
> * The GNU C Library can now be compiled with support for building static
>   PIE executables (See --enable-static-pie in INSTALL). These static PIE
>   exectuables are like static executables but can be loaded at any address
>   and provide additional security hardening benefits at the cost of some
>   memory and performance. When the library is built with --enable-static-pie
>   the resulting libc.a is usable with GCC 8 and above to create static PIE
>   executables using the GCC option '-static-pie'. This feature is currently
>   supported on x86_64.
>

I took your example.  Thanks.

>
>> diff --git a/configure.ac b/configure.ac
>> index 8ebc490a55..ae219f8fe0 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile],
>>                            [build profiled library @<:@default=no@:>@]),
>>             [profile=$enableval],
>>             [profile=no])
>> +AC_ARG_ENABLE([static-pie],
>> +           AC_HELP_STRING([--enable-static-pie],
>> +                          [build static executables as PIE @<:@default=no@:>@]),
>
> This does 2 things:
> * It enables support for building static PIE executables.
> * It builds all static binaries and tests in the testsuite as static PIE executables.
>
> It should say that e.g.
>
> "Enable static PIE executable support and use it in the testsuite."
>
> I understand the desire to use such a functionality to test static PIE executables
> by converting the entire testsuite to use them, but we still need to test non-PIE
> static executables? How are we still doing that after this change?
>
> How are we testing non-PIE static executables after this change?

This is similar to PIE vs non-PIE.  When you build glibc with GCC
defaulting to PIE, most of dynamic tests are built as PIE, except for
a couple of them linked with $(no-pie-ldflag).   I added

elf/tst-tls1-static-non-pie.c

which is always built as  non-PIE static executable, regardless if
--enable-static-pie is used to configure glibc.

To get better coverage for non-PIE, we need to build glibc with GCC
defaulting to non-PIE and configure glibc without --enable-static-pie.

>> diff --git a/manual/install.texi b/manual/install.texi
>> index f1fa28c937..86193ade3f 100644
>> --- a/manual/install.texi
>> +++ b/manual/install.texi
>> @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible.  Not all systems
>>  support shared libraries; you need ELF support and (currently) the GNU
>>  linker.
>>
>> +@item --enable-static-pie
>
> This should be rewritten to explain the feature that it enables first,
> and then the ancilliary benefits like turning it on in the testsuite.
>
>> +Build static executables, including tests, as position independent
>> +executable (static PIE) which is similar to static executable, but can
>> +be loaded at any address without help from a dynamic linker.  The
>> +resulting libc.a can be used with the GCC option, -static-pie, which
>> +is available with GCC 8 or above, to create static PIE.
>> +

I changed it to

'--enable-static-pie'
     Enable static position independent executable (static PIE) support.
     Static PIE is similar to static executable, but can be loaded at
     any address without help from a dynamic linker.  All static
     programs as well as static tests are built as static PIE, except
     for those marked with no-pie.  The resulting glibc can be used with
     the GCC option, -static-pie, which is available with GCC 8 or
     above, to create static PIE.

Here is the updated patch.

Using GCC 7 and binutils master branch, build-many-glibcs.py with
--enable-static-pie with all patches for static PIE applied have the
following build successes:

PASS: glibcs-aarch64_be-linux-gnu build
PASS: glibcs-aarch64-linux-gnu build
PASS: glibcs-armeb-linux-gnueabi-be8 build
PASS: glibcs-armeb-linux-gnueabi build
PASS: glibcs-armeb-linux-gnueabihf-be8 build
PASS: glibcs-armeb-linux-gnueabihf build
PASS: glibcs-arm-linux-gnueabi build
PASS: glibcs-arm-linux-gnueabihf build
PASS: glibcs-arm-linux-gnueabihf-v7a build
PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build
PASS: glibcs-m68k-linux-gnu build
PASS: glibcs-microblazeel-linux-gnu build
PASS: glibcs-microblaze-linux-gnu build
PASS: glibcs-mips64el-linux-gnu-n32 build
PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build
PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
PASS: glibcs-mips64el-linux-gnu-n32-soft build
PASS: glibcs-mips64el-linux-gnu-n64 build
PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build
PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build
PASS: glibcs-mips64el-linux-gnu-n64-soft build
PASS: glibcs-mips64-linux-gnu-n32 build
PASS: glibcs-mips64-linux-gnu-n32-nan2008 build
PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build
PASS: glibcs-mips64-linux-gnu-n32-soft build
PASS: glibcs-mips64-linux-gnu-n64 build
PASS: glibcs-mips64-linux-gnu-n64-nan2008 build
PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build
PASS: glibcs-mips64-linux-gnu-n64-soft build
PASS: glibcs-mipsel-linux-gnu build
PASS: glibcs-mipsel-linux-gnu-nan2008 build
PASS: glibcs-mipsel-linux-gnu-nan2008-soft build
PASS: glibcs-mipsel-linux-gnu-soft build
PASS: glibcs-mips-linux-gnu build
PASS: glibcs-mips-linux-gnu-nan2008 build
PASS: glibcs-mips-linux-gnu-nan2008-soft build
PASS: glibcs-mips-linux-gnu-soft build
PASS: glibcs-nios2-linux-gnu build
PASS: glibcs-powerpc64le-linux-gnu build
PASS: glibcs-powerpc64-linux-gnu build
PASS: glibcs-tilegxbe-linux-gnu-32 build
PASS: glibcs-tilegxbe-linux-gnu build
PASS: glibcs-tilegx-linux-gnu-32 build
PASS: glibcs-tilegx-linux-gnu build
PASS: glibcs-tilepro-linux-gnu build

I don't know how many of them actually work, except for aarch64.

Thanks.
H.J. Lu - Dec. 8, 2017, 1:14 p.m.
On Fri, Dec 1, 2017 at 10:24 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>> H.J.,
>>
>> High Level:
>>
>> At a high level I have no objection with the idea of static PIE executables,
>> it makes sense to support such things.
>
> Thanks for your feedbacks.
>
>> My only nit is that we need to do a better job of explaining to users why
>> they would use them and under what circumstances. To that end you have a bit
>> more work to do in the commit message, install.texit, and NEWS entry.
>>
>> Design:
>>
>> I have one design question below which around testing static non-PIE executables
>> in a --enable-static-pie build. See below.
>>
>> Implementation:
>>
>> Everything looks good except the use of firstword in +link-static-before-libc,
>> which I describe below. I think this is a hack and should be changed to better
>> represent the expected semantics and structure you are looking to support.
>
> Fixed.
>
>> Thank you for your work in this area.
>>
>> Look forward to a v2.
>>
>>> From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001
>>> From: "H.J. Lu" <hjl.tools@gmail.com>
>>> Date: Mon, 17 Jul 2017 08:17:32 -0700
>>> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE
>>>  [BZ #19574]
>>>
>>> Dynamic linker, ld.so, is a standalone program which can be loaded at
>>> any address.  This patch adds a configure option, --enable-static-pie,
>>> to embed the part of ld.so in static executable to create static position
>>> independent executable (static PIE).  A static PIE is similar to static
>>> executable, but can be loaded at any address without help from a dynamic
>>> linker.  When --enable-static-pie is used to configure glibc, libc.a is
>>> built as PIE and all static executables, including tests, are built as
>>> static PIE.  The resulting libc.a can be used together with GCC 8 or
>>> above to build static PIE with the compiler option, -static-pie.  But
>>> GCC 8 isn't required to build glibc with --enable-static-pie.  When an
>>> older GCC is used to build glibc with --enable-static-pie, proper input
>>> files are passed to linker to create static executables as static PIE,
>>> together with "-z text" to prevent dynamic relocations in read-only
>>> segments, which are allowed in static PIE.
>>
>> You write "which are allowed", shouldn't that be "which are not allowed"?
>
> Fixed.
>
>> The commit message must explain the following:
>>
>> * Why would a user use this feature?
>>   - What does it provide over and beyond existing static executables
>>
>> * How does a user decide to use this feature?
>>   - Should everyone use it?
>>   - Should you use it if you care about security, and what does it cost?
>>
>> Please include the answers to these questions in a the next versions
>> commit message.
>
> I added :
>
> Static PIE extends address space layout randomization to static
> executables.  It provides additional security hardening benefits at
> the cost of some memory and performance.
>
> Is this OK?
>
>>> @@ -420,7 +440,7 @@ endif
>>>  # Command for statically linking programs with the C library.
>>>  ifndef +link-static
>>>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
>>> -           $(DEFAULT-LDFLAGS-$(@F)) \
>>> +           $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \
>>
>> Is the use of firstword here just a hack to put $(no-pie-ldflag) first so
>> you can override it with the subsequent $(default-pie-ldflag)?
>>
>> It is not a robust design to use firstword here because it implies that the
>> DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting.
>>
>> I would like to see this done some other way. My preference would be for a new
>> value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm.
>>
>
> I replaced DEFAUTL-LDFLAGS-$(@F) with $($(@F)-no-pie).   Now I have
>
>  # Command for statically linking programs with the C library.
>  ifndef +link-static
>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
> -       $(DEFAULT-LDFLAGS-$(@F)) \
> +       $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
>         $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
>
>>>
>>> diff --git a/NEWS b/NEWS
>>> index ab14d1eb1b..61598be94d 100644
>>> --- a/NEWS
>>> +++ b/NEWS
>>> @@ -9,6 +9,11 @@ Version 2.27
>>>
>>>  Major new features:
>>>
>>> +* Add --enable-static-pie configure option to build static PIE.  The
>>> +  resulting libc.a can be used with the GCC option, -static-pie, which
>>> +  is available with GCC 8 or above, to create static position independent
>>> +  executable (static PIE).
>>> +
>>
>> The description of a new configure option is relevant only to INSTALL.
>>
>> We must explain when users would use this feature and why. NEWS entries are
>> user facing and must explain the function of the new feature. Does it improve
>> security for static binaries? Should users switch to using them instead of
>> normal static binaries?
>>
>> Lastly, we must explain which machines are supported in this initial release
>> of the feature. Only x86_64? You need not check all machines, other maintainers
>> can check and adjust the NEWS entry, but we have to commit to at least one
>> machine supporting this feature, which I assume is x86_64.
>>
>> For example:
>>
>> * The GNU C Library can now be compiled with support for building static
>>   PIE executables (See --enable-static-pie in INSTALL). These static PIE
>>   exectuables are like static executables but can be loaded at any address
>>   and provide additional security hardening benefits at the cost of some
>>   memory and performance. When the library is built with --enable-static-pie
>>   the resulting libc.a is usable with GCC 8 and above to create static PIE
>>   executables using the GCC option '-static-pie'. This feature is currently
>>   supported on x86_64.
>>
>
> I took your example.  Thanks.
>
>>
>>> diff --git a/configure.ac b/configure.ac
>>> index 8ebc490a55..ae219f8fe0 100644
>>> --- a/configure.ac
>>> +++ b/configure.ac
>>> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile],
>>>                            [build profiled library @<:@default=no@:>@]),
>>>             [profile=$enableval],
>>>             [profile=no])
>>> +AC_ARG_ENABLE([static-pie],
>>> +           AC_HELP_STRING([--enable-static-pie],
>>> +                          [build static executables as PIE @<:@default=no@:>@]),
>>
>> This does 2 things:
>> * It enables support for building static PIE executables.
>> * It builds all static binaries and tests in the testsuite as static PIE executables.
>>
>> It should say that e.g.
>>
>> "Enable static PIE executable support and use it in the testsuite."
>>
>> I understand the desire to use such a functionality to test static PIE executables
>> by converting the entire testsuite to use them, but we still need to test non-PIE
>> static executables? How are we still doing that after this change?
>>
>> How are we testing non-PIE static executables after this change?
>
> This is similar to PIE vs non-PIE.  When you build glibc with GCC
> defaulting to PIE, most of dynamic tests are built as PIE, except for
> a couple of them linked with $(no-pie-ldflag).   I added
>
> elf/tst-tls1-static-non-pie.c
>
> which is always built as  non-PIE static executable, regardless if
> --enable-static-pie is used to configure glibc.
>
> To get better coverage for non-PIE, we need to build glibc with GCC
> defaulting to non-PIE and configure glibc without --enable-static-pie.
>
>>> diff --git a/manual/install.texi b/manual/install.texi
>>> index f1fa28c937..86193ade3f 100644
>>> --- a/manual/install.texi
>>> +++ b/manual/install.texi
>>> @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible.  Not all systems
>>>  support shared libraries; you need ELF support and (currently) the GNU
>>>  linker.
>>>
>>> +@item --enable-static-pie
>>
>> This should be rewritten to explain the feature that it enables first,
>> and then the ancilliary benefits like turning it on in the testsuite.
>>
>>> +Build static executables, including tests, as position independent
>>> +executable (static PIE) which is similar to static executable, but can
>>> +be loaded at any address without help from a dynamic linker.  The
>>> +resulting libc.a can be used with the GCC option, -static-pie, which
>>> +is available with GCC 8 or above, to create static PIE.
>>> +
>
> I changed it to
>
> '--enable-static-pie'
>      Enable static position independent executable (static PIE) support.
>      Static PIE is similar to static executable, but can be loaded at
>      any address without help from a dynamic linker.  All static
>      programs as well as static tests are built as static PIE, except
>      for those marked with no-pie.  The resulting glibc can be used with
>      the GCC option, -static-pie, which is available with GCC 8 or
>      above, to create static PIE.
>
> Here is the updated patch.
>
> Using GCC 7 and binutils master branch, build-many-glibcs.py with
> --enable-static-pie with all patches for static PIE applied have the
> following build successes:
>
> PASS: glibcs-aarch64_be-linux-gnu build
> PASS: glibcs-aarch64-linux-gnu build
> PASS: glibcs-armeb-linux-gnueabi-be8 build
> PASS: glibcs-armeb-linux-gnueabi build
> PASS: glibcs-armeb-linux-gnueabihf-be8 build
> PASS: glibcs-armeb-linux-gnueabihf build
> PASS: glibcs-arm-linux-gnueabi build
> PASS: glibcs-arm-linux-gnueabihf build
> PASS: glibcs-arm-linux-gnueabihf-v7a build
> PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build
> PASS: glibcs-m68k-linux-gnu build
> PASS: glibcs-microblazeel-linux-gnu build
> PASS: glibcs-microblaze-linux-gnu build
> PASS: glibcs-mips64el-linux-gnu-n32 build
> PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build
> PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
> PASS: glibcs-mips64el-linux-gnu-n32-soft build
> PASS: glibcs-mips64el-linux-gnu-n64 build
> PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build
> PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build
> PASS: glibcs-mips64el-linux-gnu-n64-soft build
> PASS: glibcs-mips64-linux-gnu-n32 build
> PASS: glibcs-mips64-linux-gnu-n32-nan2008 build
> PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build
> PASS: glibcs-mips64-linux-gnu-n32-soft build
> PASS: glibcs-mips64-linux-gnu-n64 build
> PASS: glibcs-mips64-linux-gnu-n64-nan2008 build
> PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build
> PASS: glibcs-mips64-linux-gnu-n64-soft build
> PASS: glibcs-mipsel-linux-gnu build
> PASS: glibcs-mipsel-linux-gnu-nan2008 build
> PASS: glibcs-mipsel-linux-gnu-nan2008-soft build
> PASS: glibcs-mipsel-linux-gnu-soft build
> PASS: glibcs-mips-linux-gnu build
> PASS: glibcs-mips-linux-gnu-nan2008 build
> PASS: glibcs-mips-linux-gnu-nan2008-soft build
> PASS: glibcs-mips-linux-gnu-soft build
> PASS: glibcs-nios2-linux-gnu build
> PASS: glibcs-powerpc64le-linux-gnu build
> PASS: glibcs-powerpc64-linux-gnu build
> PASS: glibcs-tilegxbe-linux-gnu-32 build
> PASS: glibcs-tilegxbe-linux-gnu build
> PASS: glibcs-tilegx-linux-gnu-32 build
> PASS: glibcs-tilegx-linux-gnu build
> PASS: glibcs-tilepro-linux-gnu build
>
> I don't know how many of them actually work, except for aarch64.
>
> Thanks.
>

Hi Carlos,

Do you get a chance to take a look

https://sourceware.org/ml/libc-alpha/2017-12/msg00033.html

Thanks.
Carlos O'Donell - Dec. 15, 2017, 9:19 p.m.
On 12/01/2017 10:24 AM, H.J. Lu wrote:
> On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>> H.J.,
>>
>> High Level:
>>
>> At a high level I have no objection with the idea of static PIE executables,
>> it makes sense to support such things.
> Thanks for your feedbacks.

Thank you for putting together a v2, sorry it took me a while to review.

This version looks good to me, it cleans up the outstanding issues with the
implementation, and you have answered my questions about testing in the design.
The firstword hack is removed in the implementation and that was the only thing
that needed cleanup.

Looks good to me. Please feel free to commit.

>> My only nit is that we need to do a better job of explaining to users why
>> they would use them and under what circumstances. To that end you have a bit
>> more work to do in the commit message, install.texit, and NEWS entry.
>>
>> Design:
>>
>> I have one design question below which around testing static non-PIE executables
>> in a --enable-static-pie build. See below.
>>
>> Implementation:
>>
>> Everything looks good except the use of firstword in +link-static-before-libc,
>> which I describe below. I think this is a hack and should be changed to better
>> represent the expected semantics and structure you are looking to support.
> Fixed.
> 
>> Thank you for your work in this area.
>>
>> Look forward to a v2.
>>
>>> From 7026a79c1f71f5decd135208503fd4186193ffb8 Mon Sep 17 00:00:00 2001
>>> From: "H.J. Lu" <hjl.tools@gmail.com>
>>> Date: Mon, 17 Jul 2017 08:17:32 -0700
>>> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE
>>>  [BZ #19574]
>>>
>>> Dynamic linker, ld.so, is a standalone program which can be loaded at
>>> any address.  This patch adds a configure option, --enable-static-pie,
>>> to embed the part of ld.so in static executable to create static position
>>> independent executable (static PIE).  A static PIE is similar to static
>>> executable, but can be loaded at any address without help from a dynamic
>>> linker.  When --enable-static-pie is used to configure glibc, libc.a is
>>> built as PIE and all static executables, including tests, are built as
>>> static PIE.  The resulting libc.a can be used together with GCC 8 or
>>> above to build static PIE with the compiler option, -static-pie.  But
>>> GCC 8 isn't required to build glibc with --enable-static-pie.  When an
>>> older GCC is used to build glibc with --enable-static-pie, proper input
>>> files are passed to linker to create static executables as static PIE,
>>> together with "-z text" to prevent dynamic relocations in read-only
>>> segments, which are allowed in static PIE.
>> You write "which are allowed", shouldn't that be "which are not allowed"?
> Fixed.
> 
>> The commit message must explain the following:
>>
>> * Why would a user use this feature?
>>   - What does it provide over and beyond existing static executables
>>
>> * How does a user decide to use this feature?
>>   - Should everyone use it?
>>   - Should you use it if you care about security, and what does it cost?
>>
>> Please include the answers to these questions in a the next versions
>> commit message.
> I added :
> 
> Static PIE extends address space layout randomization to static
> executables.  It provides additional security hardening benefits at
> the cost of some memory and performance.
> 
> Is this OK?

Perfect.


>>> @@ -420,7 +440,7 @@ endif
>>>  # Command for statically linking programs with the C library.
>>>  ifndef +link-static
>>>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
>>> -           $(DEFAULT-LDFLAGS-$(@F)) \
>>> +           $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \
>> Is the use of firstword here just a hack to put $(no-pie-ldflag) first so
>> you can override it with the subsequent $(default-pie-ldflag)?
>>
>> It is not a robust design to use firstword here because it implies that the
>> DEFAUTL-LDFLAGS-$(@F) has some structure that we are not documenting.
>>
>> I would like to see this done some other way. My preference would be for a new
>> value other than DEFAULT-LDFLAGS to control the PIE-ness of the built progarm.
>>
> I replaced DEFAUTL-LDFLAGS-$(@F) with $($(@F)-no-pie).   Now I have
> 
>  # Command for statically linking programs with the C library.
>  ifndef +link-static
>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
> -       $(DEFAULT-LDFLAGS-$(@F)) \
> +       $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
>         $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
> 

This is much better. Thanks.

>>> diff --git a/NEWS b/NEWS
>>> index ab14d1eb1b..61598be94d 100644
>>> --- a/NEWS
>>> +++ b/NEWS
>>> @@ -9,6 +9,11 @@ Version 2.27
>>>
>>>  Major new features:
>>>
>>> +* Add --enable-static-pie configure option to build static PIE.  The
>>> +  resulting libc.a can be used with the GCC option, -static-pie, which
>>> +  is available with GCC 8 or above, to create static position independent
>>> +  executable (static PIE).
>>> +
>> The description of a new configure option is relevant only to INSTALL.
>>
>> We must explain when users would use this feature and why. NEWS entries are
>> user facing and must explain the function of the new feature. Does it improve
>> security for static binaries? Should users switch to using them instead of
>> normal static binaries?
>>
>> Lastly, we must explain which machines are supported in this initial release
>> of the feature. Only x86_64? You need not check all machines, other maintainers
>> can check and adjust the NEWS entry, but we have to commit to at least one
>> machine supporting this feature, which I assume is x86_64.
>>
>> For example:
>>
>> * The GNU C Library can now be compiled with support for building static
>>   PIE executables (See --enable-static-pie in INSTALL). These static PIE
>>   exectuables are like static executables but can be loaded at any address
>>   and provide additional security hardening benefits at the cost of some
>>   memory and performance. When the library is built with --enable-static-pie
>>   the resulting libc.a is usable with GCC 8 and above to create static PIE
>>   executables using the GCC option '-static-pie'. This feature is currently
>>   supported on x86_64.
>>
> I took your example.  Thanks.

You are welcome. I hope you fixed my spelling mistakes ;-)

I tried to provide at least some examples of what I was looking for.

I appreciate your patience.

>>> diff --git a/configure.ac b/configure.ac
>>> index 8ebc490a55..ae219f8fe0 100644
>>> --- a/configure.ac
>>> +++ b/configure.ac
>>> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile],
>>>                            [build profiled library @<:@default=no@:>@]),
>>>             [profile=$enableval],
>>>             [profile=no])
>>> +AC_ARG_ENABLE([static-pie],
>>> +           AC_HELP_STRING([--enable-static-pie],
>>> +                          [build static executables as PIE @<:@default=no@:>@]),
>> This does 2 things:
>> * It enables support for building static PIE executables.
>> * It builds all static binaries and tests in the testsuite as static PIE executables.
>>
>> It should say that e.g.
>>
>> "Enable static PIE executable support and use it in the testsuite."
>>
>> I understand the desire to use such a functionality to test static PIE executables
>> by converting the entire testsuite to use them, but we still need to test non-PIE
>> static executables? How are we still doing that after this change?
>>
>> How are we testing non-PIE static executables after this change?
> This is similar to PIE vs non-PIE.  When you build glibc with GCC
> defaulting to PIE, most of dynamic tests are built as PIE, except for
> a couple of them linked with $(no-pie-ldflag).   I added
> 
> elf/tst-tls1-static-non-pie.c
> 
> which is always built as  non-PIE static executable, regardless if
> --enable-static-pie is used to configure glibc.

OK, this is better than nothing. Thank you for checking.

> To get better coverage for non-PIE, we need to build glibc with GCC
> defaulting to non-PIE and configure glibc without --enable-static-pie.
> 
>>> diff --git a/manual/install.texi b/manual/install.texi
>>> index f1fa28c937..86193ade3f 100644
>>> --- a/manual/install.texi
>>> +++ b/manual/install.texi
>>> @@ -120,6 +120,13 @@ Don't build shared libraries even if it is possible.  Not all systems
>>>  support shared libraries; you need ELF support and (currently) the GNU
>>>  linker.
>>>
>>> +@item --enable-static-pie
>> This should be rewritten to explain the feature that it enables first,
>> and then the ancilliary benefits like turning it on in the testsuite.
>>
>>> +Build static executables, including tests, as position independent
>>> +executable (static PIE) which is similar to static executable, but can
>>> +be loaded at any address without help from a dynamic linker.  The
>>> +resulting libc.a can be used with the GCC option, -static-pie, which
>>> +is available with GCC 8 or above, to create static PIE.
>>> +
> I changed it to
> 
> '--enable-static-pie'
>      Enable static position independent executable (static PIE) support.
>      Static PIE is similar to static executable, but can be loaded at
>      any address without help from a dynamic linker.  All static
>      programs as well as static tests are built as static PIE, except
>      for those marked with no-pie.  The resulting glibc can be used with
>      the GCC option, -static-pie, which is available with GCC 8 or
>      above, to create static PIE.

OK.

> Here is the updated patch.
> 
> Using GCC 7 and binutils master branch, build-many-glibcs.py with
> --enable-static-pie with all patches for static PIE applied have the
> following build successes:
> 
> PASS: glibcs-aarch64_be-linux-gnu build
> PASS: glibcs-aarch64-linux-gnu build
> PASS: glibcs-armeb-linux-gnueabi-be8 build
> PASS: glibcs-armeb-linux-gnueabi build
> PASS: glibcs-armeb-linux-gnueabihf-be8 build
> PASS: glibcs-armeb-linux-gnueabihf build
> PASS: glibcs-arm-linux-gnueabi build
> PASS: glibcs-arm-linux-gnueabihf build
> PASS: glibcs-arm-linux-gnueabihf-v7a build
> PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build
> PASS: glibcs-m68k-linux-gnu build
> PASS: glibcs-microblazeel-linux-gnu build
> PASS: glibcs-microblaze-linux-gnu build
> PASS: glibcs-mips64el-linux-gnu-n32 build
> PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build
> PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
> PASS: glibcs-mips64el-linux-gnu-n32-soft build
> PASS: glibcs-mips64el-linux-gnu-n64 build
> PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build
> PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build
> PASS: glibcs-mips64el-linux-gnu-n64-soft build
> PASS: glibcs-mips64-linux-gnu-n32 build
> PASS: glibcs-mips64-linux-gnu-n32-nan2008 build
> PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build
> PASS: glibcs-mips64-linux-gnu-n32-soft build
> PASS: glibcs-mips64-linux-gnu-n64 build
> PASS: glibcs-mips64-linux-gnu-n64-nan2008 build
> PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build
> PASS: glibcs-mips64-linux-gnu-n64-soft build
> PASS: glibcs-mipsel-linux-gnu build
> PASS: glibcs-mipsel-linux-gnu-nan2008 build
> PASS: glibcs-mipsel-linux-gnu-nan2008-soft build
> PASS: glibcs-mipsel-linux-gnu-soft build
> PASS: glibcs-mips-linux-gnu build
> PASS: glibcs-mips-linux-gnu-nan2008 build
> PASS: glibcs-mips-linux-gnu-nan2008-soft build
> PASS: glibcs-mips-linux-gnu-soft build
> PASS: glibcs-nios2-linux-gnu build
> PASS: glibcs-powerpc64le-linux-gnu build
> PASS: glibcs-powerpc64-linux-gnu build
> PASS: glibcs-tilegxbe-linux-gnu-32 build
> PASS: glibcs-tilegxbe-linux-gnu build
> PASS: glibcs-tilegx-linux-gnu-32 build
> PASS: glibcs-tilegx-linux-gnu build
> PASS: glibcs-tilepro-linux-gnu build
> 
> I don't know how many of them actually work, except for aarch64.

Right, the real test is that they work. However, making sure they compilation
passes is the first real step allowing the machine maintainers to look into
runtime issues.

> Thanks.
> 
> -- H.J.
> 
> 
> 0001-Add-enable-static-pie-configure-option-to-build-stat.patch
> 
> 
> From 86d8013ccc24e4c07fdc6da04dac0448c4f5fc29 Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Mon, 17 Jul 2017 08:17:32 -0700
> Subject: [PATCH] Add --enable-static-pie configure option to build static PIE
>  [BZ #19574]
> 
> Dynamic linker, ld.so, is a standalone program which can be loaded at
> any address.  This patch adds a configure option, --enable-static-pie,
> to embed the part of ld.so in static executable to create static position
> independent executable (static PIE).  A static PIE is similar to static
> executable, but can be loaded at any address without help from a dynamic
> linker.  When --enable-static-pie is used to configure glibc, libc.a is
> built as PIE and all static executables, including tests, are built as
> static PIE.  The resulting libc.a can be used together with GCC 8 or
> above to build static PIE with the compiler option, -static-pie.  But
> GCC 8 isn't required to build glibc with --enable-static-pie.  Only GCC
> with PIE support is needed.  When an older GCC is used to build glibc
> with --enable-static-pie, proper input files are passed to linker to
> create static executables as static PIE, together with "-z text" to
> prevent dynamic relocations in read-only segments, which are not allowed
> in static PIE.
> 
> Static PIE extends address space layout randomization to static
> executables.  It provides additional security hardening benefits at
> the cost of some memory and performance.

Put this paragraph first in your commit message please. It's they key
purpose of this entire patch.

> The following changes are made for static PIE:
> 
> 1. Add a new function, _dl_relocate_static_pie, to:
>    a. Get the run-time load address.
>    b. Read the dynamic section.
>    c. Perform dynamic relocations.
> Dynamic linker also performs these steps.  But static PIE doesn't load
> any shared objects.
> 2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in
> libc.a.  crt1.o, which is used to create dynamic and non-PIE static
> executables, is updated to include a dummy _dl_relocate_static_pie.
> rcrt1.o is added to create static PIE, which will link in the real
> _dl_relocate_static_pie.  grcrt1.o is also added to create static PIE
> with -pg.  GCC 8 has been updated to support rcrt1.o and grcrt1.o for
> static PIE.
> 
> Static PIE can work on all architectures which support PIE, provided:
> 
> 1. Target must support accessing of local functions without dynamic
> relocations, which is needed in start.S to call __libc_start_main with
> function addresses of __libc_csu_init, __libc_csu_fini and main.  All
> functions in static PIE are local functions.  If PIE start.S can't reach
> main () defined in a shared object, the code sequence:
> 
> 	pass addess of local_main to __libc_start_main

s/addess/address/g

> 	...
> 
> local_main:
> 	tail call to main via PLT
> 
> can be used.
> 2. start.S is updated to check PIC instead SHARED for PIC code path and
> avoid dynamic relocation, when PIC is defined and SHARED isn't defined,
> to support static PIE.  Patches are submitted for aarch64, hppa, m68k,
> microblaze and sparc.
> 3. All assembly codes are updated check PIC instead SHARED for PIC code
> path to avoid dynamic relocations in read-only sections.
> 4. All assembly codes are updated check SHARED instead PIC for static
> symbol name.  A patch is submitted for tile.
> 5. elf_machine_load_address in dl-machine.h are updated to support static
> PIE.  Patches are submitted for aarch64, s390 and sh.
> 6. __brk works without TLS nor dynamic relocations in read-only section
> so that it can be used by __libc_setup_tls to initializes TLS in static
> PIE.
> 
> NB: When glibc is built with GCC defaulted to PIE, libc.a is compiled
> with -fPIE, regardless if --enable-static-pie is used to configure glibc.
> When glibc is configured with --enable-static-pie, libc.a is compiled
> with -fPIE, regardless wether GCC defaults to PIE or not.  The same libc.a

s/wether/whether/g

> can be used to build both static executable and static PIE.  There is no
> need for separate PIE copy of libc.a.
> 
> On x86-64, the normal static sln:
> 
>    text	   data	    bss	    dec	    hex	filename
>  625425	   8284	   5456	 639165	  9c0bd	elf/sln
> 
> the static PIE sln:
> 
>    text	   data	    bss	    dec	    hex	filename
>  657626	  20636	   5392	 683654	  a6e86	elf/sln
> 
> The code size is increased by 5% and the binary size is increased by 7%.
> 
> Linker requirements to build glibc with --enable-static-pie:
> 
> 1. Linker supports --no-dynamic-linker to remove PT_INTERP segment from
> static PIE.
> 2. Linker can create working static PIE.  The x86-64 linker needs the
> fix for
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=21782
> 
> The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax"
> to "leal main@GOTOFF(%ebx), %eax" if main is defined locally.
> 
> Binutils 2.29 or above are OK for i686 and x86-64.  But linker status for
> other targets need to be verified.
> 
> 3. Linker should resolve undefined weak symbols to 0 in static PIE:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=22269
> 
> 4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS
> relocations, which should check bfd_link_executable instead:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=22263
> 
> Tested on aarch64, i686 and x86-64.
> 
> Using GCC 7 and binutils master branch, build-many-glibcs.py with
> --enable-static-pie with all patches for static PIE applied have the
> following build successes:
> 
> PASS: glibcs-aarch64_be-linux-gnu build
> PASS: glibcs-aarch64-linux-gnu build
> PASS: glibcs-armeb-linux-gnueabi-be8 build
> PASS: glibcs-armeb-linux-gnueabi build
> PASS: glibcs-armeb-linux-gnueabihf-be8 build
> PASS: glibcs-armeb-linux-gnueabihf build
> PASS: glibcs-arm-linux-gnueabi build
> PASS: glibcs-arm-linux-gnueabihf build
> PASS: glibcs-arm-linux-gnueabihf-v7a build
> PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build
> PASS: glibcs-m68k-linux-gnu build
> PASS: glibcs-microblazeel-linux-gnu build
> PASS: glibcs-microblaze-linux-gnu build
> PASS: glibcs-mips64el-linux-gnu-n32 build
> PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build
> PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
> PASS: glibcs-mips64el-linux-gnu-n32-soft build
> PASS: glibcs-mips64el-linux-gnu-n64 build
> PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build
> PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build
> PASS: glibcs-mips64el-linux-gnu-n64-soft build
> PASS: glibcs-mips64-linux-gnu-n32 build
> PASS: glibcs-mips64-linux-gnu-n32-nan2008 build
> PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build
> PASS: glibcs-mips64-linux-gnu-n32-soft build
> PASS: glibcs-mips64-linux-gnu-n64 build
> PASS: glibcs-mips64-linux-gnu-n64-nan2008 build
> PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build
> PASS: glibcs-mips64-linux-gnu-n64-soft build
> PASS: glibcs-mipsel-linux-gnu build
> PASS: glibcs-mipsel-linux-gnu-nan2008 build
> PASS: glibcs-mipsel-linux-gnu-nan2008-soft build
> PASS: glibcs-mipsel-linux-gnu-soft build
> PASS: glibcs-mips-linux-gnu build
> PASS: glibcs-mips-linux-gnu-nan2008 build
> PASS: glibcs-mips-linux-gnu-nan2008-soft build
> PASS: glibcs-mips-linux-gnu-soft build
> PASS: glibcs-nios2-linux-gnu build
> PASS: glibcs-powerpc64le-linux-gnu build
> PASS: glibcs-powerpc64-linux-gnu build
> PASS: glibcs-tilegxbe-linux-gnu-32 build
> PASS: glibcs-tilegxbe-linux-gnu build
> PASS: glibcs-tilegx-linux-gnu-32 build
> PASS: glibcs-tilegx-linux-gnu build
> PASS: glibcs-tilepro-linux-gnu build
> 
> and the following build failures:
> 
> FAIL: glibcs-alpha-linux-gnu build
> 
> elf/sln is failed to link due to:
> 
> assertion fail bfd/elf64-alpha.c:4125
> 
> This is caused by linker bug and/or non-PIC code in PIE libc.a.
> 
> FAIL: glibcs-hppa-linux-gnu build
> 
> elf/sln is failed to link due to:
> 
> collect2: fatal error: ld terminated with signal 11 [Segmentation fault]
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=22537
> 
> FAIL: glibcs-ia64-linux-gnu build
> 
> elf/sln is failed to link due to:
> 
> collect2: fatal error: ld terminated with signal 11 [Segmentation fault]
> 
> FAIL: glibcs-powerpc-linux-gnu build
> FAIL: glibcs-powerpc-linux-gnu-soft build
> FAIL: glibcs-powerpc-linux-gnuspe build
> FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build
> 
> elf/sln is failed to link due to:
> 
> ld: read-only segment has dynamic relocations.
> 
> This is caused by linker bug and/or non-PIC code in PIE libc.a.  See:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=22264
> 
> FAIL: glibcs-powerpc-linux-gnu-power4 build
> 
> elf/sln is failed to link due to:
> 
> findlocale.c:96:(.text+0x22c): @local call to ifunc memchr
> 
> This is caused by linker bug and/or non-PIC code in PIE libc.a.
> 
> FAIL: glibcs-s390-linux-gnu build
> 
> elf/sln is failed to link due to:
> 
> collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped
> 
> assertion fail bfd/elflink.c:14299
> 
> This is caused by linker bug and/or non-PIC code in PIE libc.a.
> 
> FAIL: glibcs-sh3eb-linux-gnu build
> FAIL: glibcs-sh3-linux-gnu build
> FAIL: glibcs-sh4eb-linux-gnu build
> FAIL: glibcs-sh4eb-linux-gnu-soft build
> FAIL: glibcs-sh4-linux-gnu build
> FAIL: glibcs-sh4-linux-gnu-soft build
> 
> elf/sln is failed to link due to:
> 
> ld: read-only segment has dynamic relocations.
> 
> This is caused by linker bug and/or non-PIC code in PIE libc.a.  See:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=22263
> 
> Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS
> code sequence expected by ld:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=22270
> 
> FAIL: glibcs-sparc64-linux-gnu build
> FAIL: glibcs-sparcv9-linux-gnu build
> FAIL: glibcs-tilegxbe-linux-gnu build
> FAIL: glibcs-tilegxbe-linux-gnu-32 build
> FAIL: glibcs-tilegx-linux-gnu build
> FAIL: glibcs-tilegx-linux-gnu-32 build
> FAIL: glibcs-tilepro-linux-gnu build
> 
> elf/sln is failed to link due to:
> 
> ld: read-only segment has dynamic relocations.
> 
> This is caused by linker bug and/or non-PIC code in PIE libc.a.  See:
> 
> https://sourceware.org/bugzilla/show_bug.cgi?id=22263
> 
> 	[BZ #19574]
> 	* INSTALL: Regenerated.
> 	* Makeconfig (real-static-start-installed-name): New.
> 	(pic-default): Updated for --enable-static-pie.
> 	(pie-default): New for --enable-static-pie.
> 	(default-pie-ldflag): Likewise.
> 	(+link-static-before-libc): Replace $(DEFAULT-LDFLAGS-$(@F))
> 	with $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)).
> 	Replace $(static-start-installed-name) with
> 	$(real-static-start-installed-name).
> 	(+prectorT): Updated for --enable-static-pie.
> 	(+postctorT): Likewise.
> 	(CFLAGS-.o): Add $(pie-default).
> 	(CFLAGS-.op): Likewise.
> 	* NEWS: Mention --enable-static-pie.
> 	* config.h.in (ENABLE_STATIC_PIE): New.
> 	* configure.ac (--enable-static-pie): New configure option.
> 	(have-no-dynamic-linker): New LIBC_CONFIG_VAR.
> 	(have-static-pie): Likewise.
> 	Enable static PIE if linker supports --no-dynamic-linker.
> 	(ENABLE_STATIC_PIE): New AC_DEFINE.
> 	(enable-static-pie): New LIBC_CONFIG_VAR.
> 	* configure: Regenerated.
> 	* csu/Makefile (omit-deps): Add r$(start-installed-name) and
> 	gr$(start-installed-name) for --enable-static-pie.
> 	(extra-objs): Likewise.
> 	(install-lib): Likewise.
> 	(extra-objs): Add static-reloc.o and static-reloc.os
> 	($(objpfx)$(start-installed-name)): Also depend on
> 	$(objpfx)static-reloc.o.
> 	($(objpfx)r$(start-installed-name)): New.
> 	($(objpfx)g$(start-installed-name)): Also depend on
> 	$(objpfx)static-reloc.os.
> 	($(objpfx)gr$(start-installed-name)): New.
> 	* csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie
> 	in libc.a.
> 	* csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to
> 	initimage.
> 	* csu/static-reloc.c: New file.
> 	* elf/Makefile (routines): Add dl-reloc-static-pie.
> 	(elide-routines.os): Likewise.
> 	(DEFAULT-LDFLAGS-tst-tls1-static-non-pie): Removed.
> 	(tst-tls1-static-non-pie-no-pie): New.
> 	* elf/dl-reloc-static-pie.c: New file.
> 	* elf/dl-support.c (_dl_get_dl_main_map): New function.
> 	* elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
> 	STATIC_PIE_BOOTSTRAP.
> 	* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
> 	* gmon/Makefile (tests): Add tst-gmon-static-pie.
> 	(tests-static): Likewise.
> 	(DEFAULT-LDFLAGS-tst-gmon-static): Removed.
> 	(tst-gmon-static-no-pie): New.
> 	(CFLAGS-tst-gmon-static-pie.c): Likewise.
> 	(CRT-tst-gmon-static-pie): Likewise.
> 	(tst-gmon-static-pie-ENV): Likewise.
> 	(tests-special): Likewise.
> 	($(objpfx)tst-gmon-static-pie.out): Likewise.
> 	(clean-tst-gmon-static-pie-data): Likewise.
> 	($(objpfx)tst-gmon-static-pie-gprof.out): Likewise.
> 	* gmon/tst-gmon-static-pie.c: New file.
> 	* manual/install.texi: Document --enable-static-pie.
> 	* sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
> 	(_dl_get_dl_main_map): Likewise.
> 	* sysdeps/i386/configure.ac: Check if linker supports static PIE.
> 	* sysdeps/x86_64/configure.ac: Likewise.
> 	* sysdeps/i386/configure: Regenerated.
> 	* sysdeps/x86_64/configure: Likewise.
> 	* sysdeps/mips/Makefile (ASFLAGS-.o): Add $(pie-default).
> 	(ASFLAGS-.op): Likewise.
> ---
>  INSTALL                     |  9 ++++++
>  Makeconfig                  | 38 +++++++++++++++++++---
>  NEWS                        |  9 ++++++
>  config.h.in                 |  3 ++
>  configure                   | 79 +++++++++++++++++++++++++++++++++++++++++++++
>  configure.ac                | 29 +++++++++++++++++
>  csu/Makefile                | 24 ++++++++++++--
>  csu/libc-start.c            |  2 ++
>  csu/libc-tls.c              |  6 ++--
>  csu/static-reloc.c          | 26 +++++++++++++++
>  elf/Makefile                |  7 ++--
>  elf/dl-reloc-static-pie.c   | 52 +++++++++++++++++++++++++++++
>  elf/dl-support.c            | 11 +++++++
>  elf/dynamic-link.h          |  2 +-
>  elf/get-dynamic-info.h      |  6 ++--
>  gmon/Makefile               | 25 +++++++++++++-
>  gmon/tst-gmon-static-pie.c  |  1 +
>  manual/install.texi         |  9 ++++++
>  sysdeps/generic/ldsodefs.h  | 11 +++++++
>  sysdeps/i386/configure      | 33 +++++++++++++++++++
>  sysdeps/i386/configure.ac   | 23 +++++++++++++
>  sysdeps/mips/Makefile       |  3 ++
>  sysdeps/x86_64/configure    | 33 +++++++++++++++++++
>  sysdeps/x86_64/configure.ac | 25 ++++++++++++++
>  24 files changed, 449 insertions(+), 17 deletions(-)
>  create mode 100644 csu/static-reloc.c
>  create mode 100644 elf/dl-reloc-static-pie.c
>  create mode 100644 gmon/tst-gmon-static-pie.c
> 
> diff --git a/INSTALL b/INSTALL
> index d1a34c2a90..30804eca38 100644
> --- a/INSTALL
> +++ b/INSTALL
> @@ -90,6 +90,15 @@ will be used, and CFLAGS sets optimization options for the compiler.
>       systems support shared libraries; you need ELF support and
>       (currently) the GNU linker.
>  
> +'--enable-static-pie'
> +     Enable static position independent executable (static PIE) support.
> +     Static PIE is similar to static executable, but can be loaded at
> +     any address without help from a dynamic linker.  All static
> +     programs as well as static tests are built as static PIE, except
> +     for those marked with no-pie.  The resulting glibc can be used with
> +     the GCC option, -static-pie, which is available with GCC 8 or
> +     above, to create static PIE.
> +

OK.

>  '--disable-profile'
>       Don't build libraries with profiling information.  You may want to
>       use this option if you don't plan to do profiling.
> diff --git a/Makeconfig b/Makeconfig
> index 1346109ac0..99cc136bfa 100644
> --- a/Makeconfig
> +++ b/Makeconfig
> @@ -352,6 +352,14 @@ ifndef static-start-installed-name
>  static-start-installed-name = $(start-installed-name)
>  endif
>  
> +ifeq (yes,$(enable-static-pie))
> +# Link with rcrt1.o, instead of crt1.o, to call _dl_relocate_static_pie
> +# to relocate static PIE.
> +real-static-start-installed-name = r$(static-start-installed-name)
> +else
> +real-static-start-installed-name = $(static-start-installed-name)
> +endif
> +

OK.

>  ifeq (yesyes,$(build-shared)$(have-z-combreloc))
>  combreloc-LDFLAGS = -Wl,-z,combreloc
>  LDFLAGS.so += $(combreloc-LDFLAGS)
> @@ -371,6 +379,20 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
>  LDFLAGS-rtld += $(hashstyle-LDFLAGS)
>  endif
>  
> +ifeq (yes,$(enable-static-pie))
> +pic-default = -DPIC
> +# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE.
> +pie-default = $(pie-ccflag)
> +ifeq (yes,$(have-static-pie))
> +default-pie-ldflag = -static-pie
> +else
> +# Static PIE can't have dynamic relocations in read-only segments since
> +# static PIE is mapped into memory by kernel.  --eh-frame-hdr is needed
> +# for PIE to support exception.
> +default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text
> +endif
> +endif

OK.

> +
>  # If lazy relocations are disabled, add the -z now flag.  Use
>  # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to
>  # test modules.
> @@ -420,9 +442,9 @@ endif
>  # Command for statically linking programs with the C library.
>  ifndef +link-static
>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
> -	      $(DEFAULT-LDFLAGS-$(@F)) \
> +	      $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \

OK.

>  	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
> -	      $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \
> +	      $(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \

OK.

>  	      $(+preinit) $(+prectorT) \
>  	      $(filter-out $(addprefix $(csu-objpfx),start.o \
>  						     $(start-installed-name))\
> @@ -637,8 +659,14 @@ endif
>  +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o`
>  +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o`
>  # Variants of the two previous definitions for statically linking programs.
> +ifeq (yes,$(enable-static-pie))
> +# Static PIE must use PIE variants.
> ++prectorT = $(+prectorS)
> ++postctorT = $(+postctorS)
> +else
>  +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o`
>  +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o`
> +endif

OK.

>  csu-objpfx = $(common-objpfx)csu/
>  elf-objpfx = $(common-objpfx)elf/
>  
> @@ -959,7 +987,8 @@ libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o))
>  all-object-suffixes := .o .os .oS
>  object-suffixes :=
>  CPPFLAGS-.o = $(pic-default)
> -CFLAGS-.o = $(filter %frame-pointer,$(+cflags))
> +# libc.a must be compiled with -fPIE/-fpie for static PIE.
> +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)

OK.

>  libtype.o := lib%.a
>  object-suffixes += .o
>  ifeq (yes,$(build-shared))
> @@ -984,7 +1013,8 @@ ifeq (yes,$(build-profile))
>  all-object-suffixes += .op
>  object-suffixes += .op
>  CPPFLAGS-.op = -DPROF $(pic-default)
> -CFLAGS-.op = -pg
> +# libc_p.a must be compiled with -fPIE/-fpie for static PIE.
> +CFLAGS-.op = -pg $(pie-default)

OK.

>  libtype.op = lib%_p.a
>  endif
>  
> diff --git a/NEWS b/NEWS
> index 48af4acaea..5b09359f2c 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -9,6 +9,15 @@ Version 2.27
>  
>  Major new features:
>  
> +* The GNU C Library can now be compiled with support for building static
> +  PIE executables (See --enable-static-pie in INSTALL).  These static PIE
> +  exectuables are like static executables but can be loaded at any address
> +  and provide additional security hardening benefits at the cost of some
> +  memory and performance.  When the library is built with --enable-static-pie
> +  the resulting libc.a is usable with GCC 8 and above to create static PIE
> +  executables using the GCC option '-static-pie'.  This feature is currently
> +  supported on i386, x86_64 and x32.

OK.

> +
>  * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan
>    with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel.
>  
> diff --git a/config.h.in b/config.h.in
> index 8d76dadca2..0ecb10939f 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -241,6 +241,9 @@
>  /* Build glibc with tunables support.  */
>  #define HAVE_TUNABLES 0
>  
> +/* Define if static PIE is enabled.  */
> +#define ENABLE_STATIC_PIE 0

OK.

> +
>  /* Some compiler options may now allow to use ebp in __asm__ (used mainly
>     in i386 6 argument syscall issue).  */
>  #define CAN_USE_REGISTER_ASM_EBP 0

[snip configure]

> diff --git a/configure.ac b/configure.ac
> index 9707ae4d8e..78564f3746 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -176,6 +176,11 @@ AC_ARG_ENABLE([profile],
>  			     [build profiled library @<:@default=no@:>@]),
>  	      [profile=$enableval],
>  	      [profile=no])
> +AC_ARG_ENABLE([static-pie],
> +	      AC_HELP_STRING([--enable-static-pie],
> +			     [enable static PIE support and use it in the testsuite @<:@default=no@:>@]),
> +	      [static_pie=$enableval],
> +	      [static_pie=no])
>  AC_ARG_ENABLE([timezone-tools],

OK.

>  	      AC_HELP_STRING([--disable-timezone-tools],
>  			     [do not install timezone tools @<:@default=install@:>@]),
> @@ -1280,6 +1285,19 @@ LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack],
>  		    [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no])
>  AC_SUBST(libc_cv_z_execstack)
>  
> +LIBC_LINKER_FEATURE([--no-dynamic-linker],
> +		    [-Wl,--no-dynamic-linker],
> +		    [libc_cv_no_dynamic_linker=yes],
> +		    [libc_cv_no_dynamic_linker=no])
> +LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker])
> +
> +AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl
> +LIBC_TRY_CC_OPTION([-static-pie],
> +		   [libc_cv_static_pie=yes],
> +		   [libc_cv_static_pie=no])
> +])
> +LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie])
> +

OK.

>  AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl
>  LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no])
>  ])
> @@ -1787,6 +1805,17 @@ AC_SUBST(libc_cv_pie_default)
>  libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
>  AC_SUBST(libc_cv_multidir)
>  
> +if test "$static_pie" = yes; then
> +  # The linker must support --no-dynamic-linker.
> +  if test "$libc_cv_no_dynamic_linker" != yes; then
> +    AC_MSG_ERROR([linker support for --no-dynamic-linker needed])
> +  fi
> +  # Default to PIE.
> +  libc_cv_pie_default=yes
> +  AC_DEFINE(ENABLE_STATIC_PIE)
> +fi
> +LIBC_CONFIG_VAR([enable-static-pie], [$static_pie])
> +

OK.

>  AC_SUBST(profile)
>  AC_SUBST(static_nss)
>  
> diff --git a/csu/Makefile b/csu/Makefile
> index e42a32b3eb..86b95a9759 100644
> --- a/csu/Makefile
> +++ b/csu/Makefile
> @@ -37,7 +37,9 @@ extra-objs = start.o \
>  	     S$(start-installed-name)
>  omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \
>  			     b$(start-installed-name) $(csu-dummies) \
> -			     S$(start-installed-name))
> +			     S$(start-installed-name) \
> +			     r$(start-installed-name) \
> +			     gr$(start-installed-name))

OK.

>  install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies)
>  
>  # No tests are allowed in the csu/ subdirectory because the startup
> @@ -60,10 +62,17 @@ extra-objs += gmon-start.o
>  endif
>  
>  ifneq ($(start-installed-name),$(static-start-installed-name))
> +# FIXME: Only Hurd defines static-start-installed-name.  Hurd needs to
> +# provide special rules to support static PIE.

OK. Thanks for the FIXME comment.

>  extra-objs += $(static-start-installed-name) g$(static-start-installed-name)
>  omit-deps += $(patsubst %.o,%,$(static-start-installed-name) \
>  			     g$(static-start-installed-name))
>  install-lib += $(static-start-installed-name) g$(static-start-installed-name)
> +else
> +ifeq (yes,$(enable-static-pie))
> +extra-objs += r$(start-installed-name) gr$(start-installed-name)
> +install-lib += r$(start-installed-name) gr$(start-installed-name)
> +endif

OK.

>  endif
>  
>  before-compile += $(objpfx)abi-tag.h
> @@ -82,7 +91,10 @@ multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib))
>  extra-objs += $(multilib-extra-objs)
>  endif
>  
> -extra-objs += abi-note.o init.o
> +extra-objs += abi-note.o init.o static-reloc.o
> +ifeq (yes,$(build-shared))
> +extra-objs += static-reloc.os
> +endif
>  asm-CPPFLAGS += -I$(objpfx).
>  
>  # Enable unwinding so backtrace unwinds to __libc_start_main
> @@ -101,6 +113,9 @@ ifndef start-installed-name-rule
>  # We link the ELF startfile along with a SHT_NOTE section indicating
>  # the kernel ABI the binaries linked with this library will require.
>  $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \
> +				  $(objpfx)init.o $(objpfx)static-reloc.o
> +	$(link-relocatable)
> +$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \
>  				  $(objpfx)init.o

OK.

>  	$(link-relocatable)
>  $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \
> @@ -113,7 +128,10 @@ endif
>  # to turn on profiling code at startup.
>  ifeq (yes,$(build-shared))
>  $(objpfx)g$(start-installed-name): \
> -  $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os
> +  $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os
> +	$(link-relocatable)
> +$(objpfx)gr$(start-installed-name): \
> +  $(objpfx)gr%: $(objpfx)r% $(objpfx)gmon-start.o

OK.

>  	$(link-relocatable)
>  ifneq ($(start-installed-name),$(static-start-installed-name))
>  $(objpfx)g$(static-start-installed-name): \
> diff --git a/csu/libc-start.c b/csu/libc-start.c
> index 24c63be02f..34dd125260 100644
> --- a/csu/libc-start.c
> +++ b/csu/libc-start.c
> @@ -141,6 +141,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
>    __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
>  
>  #ifndef SHARED
> +  _dl_relocate_static_pie ();
> +

OK.

>    char **ev = &argv[argc + 1];
>  
>    __environ = ev;
> diff --git a/csu/libc-tls.c b/csu/libc-tls.c
> index 00138eb43a..1f8ddaf543 100644
> --- a/csu/libc-tls.c
> +++ b/csu/libc-tls.c
> @@ -114,6 +114,8 @@ __libc_setup_tls (void)
>    size_t tcb_offset;
>    const ElfW(Phdr) *phdr;
>  
> +  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
> +

OK.

>    /* Look through the TLS segment if there is any.  */
>    if (_dl_phdr != NULL)
>      for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
> @@ -122,7 +124,7 @@ __libc_setup_tls (void)
>  	  /* Remember the values we need.  */
>  	  memsz = phdr->p_memsz;
>  	  filesz = phdr->p_filesz;
> -	  initimage = (void *) phdr->p_vaddr;
> +	  initimage = (void *) phdr->p_vaddr + main_map->l_addr;
>  	  align = phdr->p_align;

OK.

>  	  if (phdr->p_align > max_align)
>  	    max_align = phdr->p_align;
> @@ -163,8 +165,6 @@ __libc_setup_tls (void)
>    _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2;
>    // _dl_static_dtv[1].counter = 0;		would be needed if not already done
>  
> -  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
> -

OK.

>    /* Initialize the TLS block.  */
>  #if TLS_TCB_AT_TP
>    _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
> diff --git a/csu/static-reloc.c b/csu/static-reloc.c
> new file mode 100644
> index 0000000000..37be72c8ea
> --- /dev/null
> +++ b/csu/static-reloc.c
> @@ -0,0 +1,26 @@
> +/* Special startup support for non-PIE static executables.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#if ENABLE_STATIC_PIE
> +#include <ldsodefs.h>
> +
> +void
> +_dl_relocate_static_pie (void)
> +{
> +}
> +#endif

OK.

> diff --git a/elf/Makefile b/elf/Makefile
> index d49fd4673d..4c6f9e0a49 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -24,7 +24,8 @@ include ../Makeconfig
>  headers		= elf.h bits/elfclass.h link.h bits/link.h
>  routines	= $(all-dl-routines) dl-support dl-iteratephdr \
>  		  dl-addr dl-addr-obj enbl-secure dl-profstub \
> -		  dl-origin dl-libc dl-sym dl-sysdep dl-error
> +		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
> +		  dl-reloc-static-pie

OK.

>  
>  # The core dynamic linking functions are in libc for the static and
>  # profiled libraries.
> @@ -52,7 +53,7 @@ endif
>  all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
>  # But they are absent from the shared libc, because that code is in ld.so.
>  elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
> -		    dl-sysdep dl-exception
> +		    dl-sysdep dl-exception dl-reloc-static-pie
>  shared-only-routines += dl-caller
>  
>  # ld.so uses those routines, plus some special stuff for being the program
> @@ -153,7 +154,7 @@ tests-static-internal := tst-tls1-static tst-tls2-static \
>  	       tst-tls1-static-non-pie
>  
>  CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o
> -DEFAULT-LDFLAGS-tst-tls1-static-non-pie = $(no-pie-ldflag)
> +tst-tls1-static-non-pie-no-pie = yes
>  
>  tests := tst-tls9 tst-leaks1 \
>  	tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> new file mode 100644
> index 0000000000..6e43aea76a
> --- /dev/null
> +++ b/elf/dl-reloc-static-pie.c
> @@ -0,0 +1,52 @@
> +/* Support for relocating static PIE.
> +   Copyright (C) 2017 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#if ENABLE_STATIC_PIE
> +#include <unistd.h>
> +#include <ldsodefs.h>
> +#include "dynamic-link.h"
> +
> +/* Relocate static executable with PIE.  */
> +
> +void
> +_dl_relocate_static_pie (void)
> +{
> +  struct link_map *main_map = _dl_get_dl_main_map ();
> +
> +# define STATIC_PIE_BOOTSTRAP
> +# define BOOTSTRAP_MAP (main_map)
> +# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
> +# include "dynamic-link.h"
> +
> +  /* Figure out the run-time load address of static PIE.  */
> +  main_map->l_addr = elf_machine_load_address ();
> +
> +  /* Read our own dynamic section and fill in the info array.  */
> +  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> +  elf_get_dynamic_info (main_map, NULL);
> +
> +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> +  ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info);
> +# endif
> +
> +  /* Relocate ourselves so we can do normal function calls and
> +     data access using the global offset table.  */
> +  ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0);
> +  main_map->l_relocated = 1;

OK.

> +}
> +#endif
> diff --git a/elf/dl-support.c b/elf/dl-support.c
> index 235d3a7f46..b9fc1a66fe 100644
> --- a/elf/dl-support.c
> +++ b/elf/dl-support.c
> @@ -385,3 +385,14 @@ _dl_non_dynamic_init (void)
>  #ifdef DL_SYSINFO_IMPLEMENTATION
>  DL_SYSINFO_IMPLEMENTATION
>  #endif
> +
> +#if ENABLE_STATIC_PIE
> +/* Since relocation to hidden _dl_main_map causes relocation overflow on
> +   aarch64, a function is used to get the address of _dl_main_map.  */
> +
> +struct link_map *
> +_dl_get_dl_main_map (void)
> +{
> +  return &_dl_main_map;
> +}

OK.

> +#endif
> diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
> index ebea7567cd..6278649711 100644
> --- a/elf/dynamic-link.h
> +++ b/elf/dynamic-link.h
> @@ -94,7 +94,7 @@ elf_machine_lazy_rel (struct link_map *map,
>  
>  #ifdef RESOLVE_MAP
>  
> -# ifdef RTLD_BOOTSTRAP
> +# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
>  #  define ELF_DURING_STARTUP (1)
>  # else
>  #  define ELF_DURING_STARTUP (0)
> diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
> index 7525c3a5b2..eb26d23649 100644
> --- a/elf/get-dynamic-info.h
> +++ b/elf/get-dynamic-info.h
> @@ -38,7 +38,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
>    typedef Elf64_Xword d_tag_utype;
>  #endif
>  
> -#ifndef RTLD_BOOTSTRAP
> +#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP
>    if (dyn == NULL)
>      return;
>  #endif
> @@ -139,9 +139,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
>    /* Only the bind now flags are allowed.  */
>    assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
>  	  || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0);
> +  /* Flags must not be set for ld.so.  */
>    assert (info[DT_FLAGS] == NULL
>  	  || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
> -  /* Flags must not be set for ld.so.  */
> +#endif
> +#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
>    assert (info[DT_RUNPATH] == NULL);
>    assert (info[DT_RPATH] == NULL);
>  #else
> diff --git a/gmon/Makefile b/gmon/Makefile
> index 89ab3fc7da..29e746723e 100644
> --- a/gmon/Makefile
> +++ b/gmon/Makefile
> @@ -39,6 +39,10 @@ tests-static += tst-gmon-static
>  ifeq (yesyes,$(have-fpie)$(build-shared))
>  tests += tst-gmon-pie
>  tests-pie += tst-gmon-pie
> +ifeq (yes,$(enable-static-pie))
> +tests += tst-gmon-static-pie
> +tests-static += tst-gmon-static-pie

OK.

> +endif
>  endif
>  
>  # The mcount code won't work without a frame pointer.
> @@ -54,7 +58,7 @@ endif
>  
>  CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
>  CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o
> -DEFAULT-LDFLAGS-tst-gmon-static = $(no-pie-ldflag)
> +tst-gmon-static-no-pie = yes
>  tst-gmon-static-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static.data
>  ifeq ($(run-built-tests),yes)
>  tests-special += $(objpfx)tst-gmon-static-gprof.out
> @@ -67,6 +71,15 @@ ifeq ($(run-built-tests),yes)
>  tests-special += $(objpfx)tst-gmon-pie-gprof.out
>  endif
>  
> +ifeq (yes,$(enable-static-pie))
> +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
> +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o
> +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data
> +ifeq ($(run-built-tests),yes)
> +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out
> +endif
> +endif

OK.

> +
>  
>  include ../Rules
>  
> @@ -111,3 +124,13 @@ clean-tst-gmon-pie-data:
>  $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out
>  	$(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \
>  	$(evaluate-test)
> +
> +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data
> +clean-tst-gmon-static-pie-data:
> +	rm -f $(objpfx)tst-gmon-static-pie.data.*
> +
> +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \
> +					$(objpfx)tst-gmon-static-pie.out
> +	$(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \
> +		$(objpfx)tst-gmon-static-pie.data.* > $@; \
> +	$(evaluate-test)

OK.

> diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c
> new file mode 100644
> index 0000000000..1eef2583b6
> --- /dev/null
> +++ b/gmon/tst-gmon-static-pie.c
> @@ -0,0 +1 @@
> +#include "tst-gmon.c"
> diff --git a/manual/install.texi b/manual/install.texi
> index ea559e4e72..0efa8572df 100644
> --- a/manual/install.texi
> +++ b/manual/install.texi
> @@ -120,6 +120,15 @@ Don't build shared libraries even if it is possible.  Not all systems
>  support shared libraries; you need ELF support and (currently) the GNU
>  linker.
>  
> +@item --enable-static-pie
> +Enable static position independent executable (static PIE) support.
> +Static PIE is similar to static executable, but can be loaded at any
> +address without help from a dynamic linker.  All static programs as
> +well as static tests are built as static PIE, except for those marked
> +with no-pie.  The resulting glibc can be used with the GCC option,
> +-static-pie, which is available with GCC 8 or above, to create static
> +PIE.

OK.

> +
>  @item --disable-profile
>  Don't build libraries with profiling information.  You may want to use
>  this option if you don't plan to do profiling.
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 7a65dc641c..196513851f 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1051,6 +1051,17 @@ extern void _dl_determine_tlsoffset (void) attribute_hidden;
>     stack protector, among other things).  */
>  void __libc_setup_tls (void);
>  
> +# if ENABLE_STATIC_PIE
> +/* Relocate static executable with PIE.  */
> +extern void _dl_relocate_static_pie (void) attribute_hidden;
> +
> +/* Get a pointer to _dl_main_map.  */
> +extern struct link_map * _dl_get_dl_main_map (void)
> +  __attribute__ ((visibility ("hidden")));
> +# else
> +#  define _dl_relocate_static_pie()
> +# endif
> +
>  /* Initialization of libpthread for statically linked applications.
>     If libpthread is not linked in, this is an empty function.  */
>  void __pthread_initialize_minimal (void) weak_function;
> diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure
> index 4cf968d8bc..90c63caf35 100644

[snip configure]

> --- a/sysdeps/i386/configure.ac
> +++ b/sysdeps/i386/configure.ac
> @@ -30,6 +30,29 @@ LIBC_COMPILER_BUILTIN_INLINED(
>  *** Please use host i786, i686, i586, or i486.
>  *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])])
>  
> +dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to
> +dnl "leal main@GOTOFF(%ebx), %eax" for static PIE.
> +if test "$static_pie" = yes; then
> +  AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl
> +cat > conftest.s <<\EOF
> +	.text
> +	.global _start
> +_start:
> +	movl	_start@GOT(%ebx), %eax
> +EOF
> +  libc_cv_pie_option="-Wl,-pie"
> +  libc_cv_ld_static_pie=no
> +  if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then
> +    if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then
> +      libc_cv_ld_static_pie=yes
> +    fi
> +  fi
> +rm -f conftest*])
> +  if test "$libc_cv_ld_static_pie" != yes; then
> +    AC_MSG_ERROR([linker support for static PIE needed])
> +  fi
> +fi
> +

OK.

>  dnl Check whether asm supports Intel MPX
>  AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl
>  cat > conftest.s <<\EOF
> diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile
> index fd891ddf09..7ac6fa5031 100644
> --- a/sysdeps/mips/Makefile
> +++ b/sysdeps/mips/Makefile
> @@ -23,6 +23,9 @@ CPPFLAGS-crtn.S += $(pic-ccflag)
>  endif
>  
>  ASFLAGS-.os += $(pic-ccflag)
> +# libc.a and libc_p.a must be compiled with -fPIE/-fpie for static PIE.
> +ASFLAGS-.o += $(pie-default)
> +ASFLAGS-.op += $(pie-default)
>  
>  ifeq ($(subdir),elf)
>  ifneq ($(o32-fpabi),)
> diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure
> index efef46b1b7..8674d14569 100644
[snip configure]

> diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac
> index fa86e953ee..b7d2c0124f 100644
> --- a/sysdeps/x86_64/configure.ac
> +++ b/sysdeps/x86_64/configure.ac
> @@ -44,6 +44,31 @@ if test x"$build_mathvec" = xnotset; then
>    build_mathvec=yes
>  fi
>  
> +dnl Check if linker supports static PIE with the fix for
> +dnl
> +dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782
> +dnl
> +if test "$static_pie" = yes; then
> +  AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl
> +cat > conftest.s <<\EOF
> +	.text
> +	.global _start
> +	.weak foo
> +_start:
> +	leaq	foo(%rip), %rax
> +EOF
> +  libc_cv_pie_option="-Wl,-pie"
> +  if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then
> +    libc_cv_ld_static_pie=yes
> +  else
> +    libc_cv_ld_static_pie=no
> +  fi
> +rm -f conftest*])
> +  if test "$libc_cv_ld_static_pie" != yes; then
> +    AC_MSG_ERROR([linker support for static PIE needed])
> +  fi
> +fi

OK.

> +
>  dnl It is always possible to access static and hidden symbols in an
>  dnl position independent way.
>  AC_DEFINE(PI_STATIC_AND_HIDDEN)
> -- 2.14.3
H.J. Lu - Dec. 16, 2017, 2:03 a.m.
On Fri, Dec 15, 2017 at 1:19 PM, Carlos O'Donell <carlos@redhat.com> wrote:
> On 12/01/2017 10:24 AM, H.J. Lu wrote:
>> On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>>> H.J.,
>>>
>>> High Level:
>>>
>>> At a high level I have no objection with the idea of static PIE executables,
>>> it makes sense to support such things.
>> Thanks for your feedbacks.
>
> Thank you for putting together a v2, sorry it took me a while to review.
>
> This version looks good to me, it cleans up the outstanding issues with the
> implementation, and you have answered my questions about testing in the design.
> The firstword hack is removed in the implementation and that was the only thing
> that needed cleanup.
>
> Looks good to me. Please feel free to commit.

Thanks for your time.  I checked it in with the updated commit log.
I also updated

https://sourceware.org/glibc/wiki/PortStatus

for static PIE status.  Should build-many-glibcs.py be updated to also
build static
PIE for i386, x86_64 and x32?  We can't build it by default since the
recent linker
is needed.
Carlos O'Donell - Dec. 16, 2017, 3:05 a.m.
On 12/15/2017 06:03 PM, H.J. Lu wrote:
> On Fri, Dec 15, 2017 at 1:19 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>> On 12/01/2017 10:24 AM, H.J. Lu wrote:
>>> On Thu, Nov 30, 2017 at 1:44 PM, Carlos O'Donell <carlos@redhat.com> wrote:
>>>> H.J.,
>>>>
>>>> High Level:
>>>>
>>>> At a high level I have no objection with the idea of static PIE executables,
>>>> it makes sense to support such things.
>>> Thanks for your feedbacks.
>>
>> Thank you for putting together a v2, sorry it took me a while to review.
>>
>> This version looks good to me, it cleans up the outstanding issues with the
>> implementation, and you have answered my questions about testing in the design.
>> The firstword hack is removed in the implementation and that was the only thing
>> that needed cleanup.
>>
>> Looks good to me. Please feel free to commit.
> 
> Thanks for your time.  I checked it in with the updated commit log.
> I also updated
> 
> https://sourceware.org/glibc/wiki/PortStatus
> 
> for static PIE status.  Should build-many-glibcs.py be updated to also
> build static
> PIE for i386, x86_64 and x32?  We can't build it by default since the
> recent linker
> is needed.

It couldn't hurt to enable an extra build for i386, x86_64, and x32 with
static PIE, that way we get better coverage.

However, I defer this decision to Joseph Myers, if he thinks this would
add value without adding too much cost to the build, then I'm happy to see
it enabled.

Personally I think static PIE should *always* be used since it hardens
static executables in ways which are useful. Static executables should be
special tools which are always present on the system, and hardening them
from attack is important.

Patch

From 86d8013ccc24e4c07fdc6da04dac0448c4f5fc29 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 17 Jul 2017 08:17:32 -0700
Subject: [PATCH] Add --enable-static-pie configure option to build static PIE
 [BZ #19574]

Dynamic linker, ld.so, is a standalone program which can be loaded at
any address.  This patch adds a configure option, --enable-static-pie,
to embed the part of ld.so in static executable to create static position
independent executable (static PIE).  A static PIE is similar to static
executable, but can be loaded at any address without help from a dynamic
linker.  When --enable-static-pie is used to configure glibc, libc.a is
built as PIE and all static executables, including tests, are built as
static PIE.  The resulting libc.a can be used together with GCC 8 or
above to build static PIE with the compiler option, -static-pie.  But
GCC 8 isn't required to build glibc with --enable-static-pie.  Only GCC
with PIE support is needed.  When an older GCC is used to build glibc
with --enable-static-pie, proper input files are passed to linker to
create static executables as static PIE, together with "-z text" to
prevent dynamic relocations in read-only segments, which are not allowed
in static PIE.

Static PIE extends address space layout randomization to static
executables.  It provides additional security hardening benefits at
the cost of some memory and performance.

The following changes are made for static PIE:

1. Add a new function, _dl_relocate_static_pie, to:
   a. Get the run-time load address.
   b. Read the dynamic section.
   c. Perform dynamic relocations.
Dynamic linker also performs these steps.  But static PIE doesn't load
any shared objects.
2. Call _dl_relocate_static_pie at entrance of LIBC_START_MAIN in
libc.a.  crt1.o, which is used to create dynamic and non-PIE static
executables, is updated to include a dummy _dl_relocate_static_pie.
rcrt1.o is added to create static PIE, which will link in the real
_dl_relocate_static_pie.  grcrt1.o is also added to create static PIE
with -pg.  GCC 8 has been updated to support rcrt1.o and grcrt1.o for
static PIE.

Static PIE can work on all architectures which support PIE, provided:

1. Target must support accessing of local functions without dynamic
relocations, which is needed in start.S to call __libc_start_main with
function addresses of __libc_csu_init, __libc_csu_fini and main.  All
functions in static PIE are local functions.  If PIE start.S can't reach
main () defined in a shared object, the code sequence:

	pass addess of local_main to __libc_start_main
	...

local_main:
	tail call to main via PLT

can be used.
2. start.S is updated to check PIC instead SHARED for PIC code path and
avoid dynamic relocation, when PIC is defined and SHARED isn't defined,
to support static PIE.  Patches are submitted for aarch64, hppa, m68k,
microblaze and sparc.
3. All assembly codes are updated check PIC instead SHARED for PIC code
path to avoid dynamic relocations in read-only sections.
4. All assembly codes are updated check SHARED instead PIC for static
symbol name.  A patch is submitted for tile.
5. elf_machine_load_address in dl-machine.h are updated to support static
PIE.  Patches are submitted for aarch64, s390 and sh.
6. __brk works without TLS nor dynamic relocations in read-only section
so that it can be used by __libc_setup_tls to initializes TLS in static
PIE.

NB: When glibc is built with GCC defaulted to PIE, libc.a is compiled
with -fPIE, regardless if --enable-static-pie is used to configure glibc.
When glibc is configured with --enable-static-pie, libc.a is compiled
with -fPIE, regardless wether GCC defaults to PIE or not.  The same libc.a
can be used to build both static executable and static PIE.  There is no
need for separate PIE copy of libc.a.

On x86-64, the normal static sln:

   text	   data	    bss	    dec	    hex	filename
 625425	   8284	   5456	 639165	  9c0bd	elf/sln

the static PIE sln:

   text	   data	    bss	    dec	    hex	filename
 657626	  20636	   5392	 683654	  a6e86	elf/sln

The code size is increased by 5% and the binary size is increased by 7%.

Linker requirements to build glibc with --enable-static-pie:

1. Linker supports --no-dynamic-linker to remove PT_INTERP segment from
static PIE.
2. Linker can create working static PIE.  The x86-64 linker needs the
fix for

https://sourceware.org/bugzilla/show_bug.cgi?id=21782

The i386 linker needs to be able to convert "movl main@GOT(%ebx), %eax"
to "leal main@GOTOFF(%ebx), %eax" if main is defined locally.

Binutils 2.29 or above are OK for i686 and x86-64.  But linker status for
other targets need to be verified.

3. Linker should resolve undefined weak symbols to 0 in static PIE:

https://sourceware.org/bugzilla/show_bug.cgi?id=22269

4. Many ELF backend linkers incorrectly check bfd_link_pic for TLS
relocations, which should check bfd_link_executable instead:

https://sourceware.org/bugzilla/show_bug.cgi?id=22263

Tested on aarch64, i686 and x86-64.

Using GCC 7 and binutils master branch, build-many-glibcs.py with
--enable-static-pie with all patches for static PIE applied have the
following build successes:

PASS: glibcs-aarch64_be-linux-gnu build
PASS: glibcs-aarch64-linux-gnu build
PASS: glibcs-armeb-linux-gnueabi-be8 build
PASS: glibcs-armeb-linux-gnueabi build
PASS: glibcs-armeb-linux-gnueabihf-be8 build
PASS: glibcs-armeb-linux-gnueabihf build
PASS: glibcs-arm-linux-gnueabi build
PASS: glibcs-arm-linux-gnueabihf build
PASS: glibcs-arm-linux-gnueabihf-v7a build
PASS: glibcs-arm-linux-gnueabihf-v7a-disable-multi-arch build
PASS: glibcs-m68k-linux-gnu build
PASS: glibcs-microblazeel-linux-gnu build
PASS: glibcs-microblaze-linux-gnu build
PASS: glibcs-mips64el-linux-gnu-n32 build
PASS: glibcs-mips64el-linux-gnu-n32-nan2008 build
PASS: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
PASS: glibcs-mips64el-linux-gnu-n32-soft build
PASS: glibcs-mips64el-linux-gnu-n64 build
PASS: glibcs-mips64el-linux-gnu-n64-nan2008 build
PASS: glibcs-mips64el-linux-gnu-n64-nan2008-soft build
PASS: glibcs-mips64el-linux-gnu-n64-soft build
PASS: glibcs-mips64-linux-gnu-n32 build
PASS: glibcs-mips64-linux-gnu-n32-nan2008 build
PASS: glibcs-mips64-linux-gnu-n32-nan2008-soft build
PASS: glibcs-mips64-linux-gnu-n32-soft build
PASS: glibcs-mips64-linux-gnu-n64 build
PASS: glibcs-mips64-linux-gnu-n64-nan2008 build
PASS: glibcs-mips64-linux-gnu-n64-nan2008-soft build
PASS: glibcs-mips64-linux-gnu-n64-soft build
PASS: glibcs-mipsel-linux-gnu build
PASS: glibcs-mipsel-linux-gnu-nan2008 build
PASS: glibcs-mipsel-linux-gnu-nan2008-soft build
PASS: glibcs-mipsel-linux-gnu-soft build
PASS: glibcs-mips-linux-gnu build
PASS: glibcs-mips-linux-gnu-nan2008 build
PASS: glibcs-mips-linux-gnu-nan2008-soft build
PASS: glibcs-mips-linux-gnu-soft build
PASS: glibcs-nios2-linux-gnu build
PASS: glibcs-powerpc64le-linux-gnu build
PASS: glibcs-powerpc64-linux-gnu build
PASS: glibcs-tilegxbe-linux-gnu-32 build
PASS: glibcs-tilegxbe-linux-gnu build
PASS: glibcs-tilegx-linux-gnu-32 build
PASS: glibcs-tilegx-linux-gnu build
PASS: glibcs-tilepro-linux-gnu build

and the following build failures:

FAIL: glibcs-alpha-linux-gnu build

elf/sln is failed to link due to:

assertion fail bfd/elf64-alpha.c:4125

This is caused by linker bug and/or non-PIC code in PIE libc.a.

FAIL: glibcs-hppa-linux-gnu build

elf/sln is failed to link due to:

collect2: fatal error: ld terminated with signal 11 [Segmentation fault]

https://sourceware.org/bugzilla/show_bug.cgi?id=22537

FAIL: glibcs-ia64-linux-gnu build

elf/sln is failed to link due to:

collect2: fatal error: ld terminated with signal 11 [Segmentation fault]

FAIL: glibcs-powerpc-linux-gnu build
FAIL: glibcs-powerpc-linux-gnu-soft build
FAIL: glibcs-powerpc-linux-gnuspe build
FAIL: glibcs-powerpc-linux-gnuspe-e500v1 build

elf/sln is failed to link due to:

ld: read-only segment has dynamic relocations.

This is caused by linker bug and/or non-PIC code in PIE libc.a.  See:

https://sourceware.org/bugzilla/show_bug.cgi?id=22264

FAIL: glibcs-powerpc-linux-gnu-power4 build

elf/sln is failed to link due to:

findlocale.c:96:(.text+0x22c): @local call to ifunc memchr

This is caused by linker bug and/or non-PIC code in PIE libc.a.

FAIL: glibcs-s390-linux-gnu build

elf/sln is failed to link due to:

collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped

assertion fail bfd/elflink.c:14299

This is caused by linker bug and/or non-PIC code in PIE libc.a.

FAIL: glibcs-sh3eb-linux-gnu build
FAIL: glibcs-sh3-linux-gnu build
FAIL: glibcs-sh4eb-linux-gnu build
FAIL: glibcs-sh4eb-linux-gnu-soft build
FAIL: glibcs-sh4-linux-gnu build
FAIL: glibcs-sh4-linux-gnu-soft build

elf/sln is failed to link due to:

ld: read-only segment has dynamic relocations.

This is caused by linker bug and/or non-PIC code in PIE libc.a.  See:

https://sourceware.org/bugzilla/show_bug.cgi?id=22263

Also TLS code sequence in SH assembly syscalls in glibc doesn't match TLS
code sequence expected by ld:

https://sourceware.org/bugzilla/show_bug.cgi?id=22270

FAIL: glibcs-sparc64-linux-gnu build
FAIL: glibcs-sparcv9-linux-gnu build
FAIL: glibcs-tilegxbe-linux-gnu build
FAIL: glibcs-tilegxbe-linux-gnu-32 build
FAIL: glibcs-tilegx-linux-gnu build
FAIL: glibcs-tilegx-linux-gnu-32 build
FAIL: glibcs-tilepro-linux-gnu build

elf/sln is failed to link due to:

ld: read-only segment has dynamic relocations.

This is caused by linker bug and/or non-PIC code in PIE libc.a.  See:

https://sourceware.org/bugzilla/show_bug.cgi?id=22263

	[BZ #19574]
	* INSTALL: Regenerated.
	* Makeconfig (real-static-start-installed-name): New.
	(pic-default): Updated for --enable-static-pie.
	(pie-default): New for --enable-static-pie.
	(default-pie-ldflag): Likewise.
	(+link-static-before-libc): Replace $(DEFAULT-LDFLAGS-$(@F))
	with $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)).
	Replace $(static-start-installed-name) with
	$(real-static-start-installed-name).
	(+prectorT): Updated for --enable-static-pie.
	(+postctorT): Likewise.
	(CFLAGS-.o): Add $(pie-default).
	(CFLAGS-.op): Likewise.
	* NEWS: Mention --enable-static-pie.
	* config.h.in (ENABLE_STATIC_PIE): New.
	* configure.ac (--enable-static-pie): New configure option.
	(have-no-dynamic-linker): New LIBC_CONFIG_VAR.
	(have-static-pie): Likewise.
	Enable static PIE if linker supports --no-dynamic-linker.
	(ENABLE_STATIC_PIE): New AC_DEFINE.
	(enable-static-pie): New LIBC_CONFIG_VAR.
	* configure: Regenerated.
	* csu/Makefile (omit-deps): Add r$(start-installed-name) and
	gr$(start-installed-name) for --enable-static-pie.
	(extra-objs): Likewise.
	(install-lib): Likewise.
	(extra-objs): Add static-reloc.o and static-reloc.os
	($(objpfx)$(start-installed-name)): Also depend on
	$(objpfx)static-reloc.o.
	($(objpfx)r$(start-installed-name)): New.
	($(objpfx)g$(start-installed-name)): Also depend on
	$(objpfx)static-reloc.os.
	($(objpfx)gr$(start-installed-name)): New.
	* csu/libc-start.c (LIBC_START_MAIN): Call _dl_relocate_static_pie
	in libc.a.
	* csu/libc-tls.c (__libc_setup_tls): Add main_map->l_addr to
	initimage.
	* csu/static-reloc.c: New file.
	* elf/Makefile (routines): Add dl-reloc-static-pie.
	(elide-routines.os): Likewise.
	(DEFAULT-LDFLAGS-tst-tls1-static-non-pie): Removed.
	(tst-tls1-static-non-pie-no-pie): New.
	* elf/dl-reloc-static-pie.c: New file.
	* elf/dl-support.c (_dl_get_dl_main_map): New function.
	* elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
	STATIC_PIE_BOOTSTRAP.
	* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
	* gmon/Makefile (tests): Add tst-gmon-static-pie.
	(tests-static): Likewise.
	(DEFAULT-LDFLAGS-tst-gmon-static): Removed.
	(tst-gmon-static-no-pie): New.
	(CFLAGS-tst-gmon-static-pie.c): Likewise.
	(CRT-tst-gmon-static-pie): Likewise.
	(tst-gmon-static-pie-ENV): Likewise.
	(tests-special): Likewise.
	($(objpfx)tst-gmon-static-pie.out): Likewise.
	(clean-tst-gmon-static-pie-data): Likewise.
	($(objpfx)tst-gmon-static-pie-gprof.out): Likewise.
	* gmon/tst-gmon-static-pie.c: New file.
	* manual/install.texi: Document --enable-static-pie.
	* sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
	(_dl_get_dl_main_map): Likewise.
	* sysdeps/i386/configure.ac: Check if linker supports static PIE.
	* sysdeps/x86_64/configure.ac: Likewise.
	* sysdeps/i386/configure: Regenerated.
	* sysdeps/x86_64/configure: Likewise.
	* sysdeps/mips/Makefile (ASFLAGS-.o): Add $(pie-default).
	(ASFLAGS-.op): Likewise.
---
 INSTALL                     |  9 ++++++
 Makeconfig                  | 38 +++++++++++++++++++---
 NEWS                        |  9 ++++++
 config.h.in                 |  3 ++
 configure                   | 79 +++++++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 29 +++++++++++++++++
 csu/Makefile                | 24 ++++++++++++--
 csu/libc-start.c            |  2 ++
 csu/libc-tls.c              |  6 ++--
 csu/static-reloc.c          | 26 +++++++++++++++
 elf/Makefile                |  7 ++--
 elf/dl-reloc-static-pie.c   | 52 +++++++++++++++++++++++++++++
 elf/dl-support.c            | 11 +++++++
 elf/dynamic-link.h          |  2 +-
 elf/get-dynamic-info.h      |  6 ++--
 gmon/Makefile               | 25 +++++++++++++-
 gmon/tst-gmon-static-pie.c  |  1 +
 manual/install.texi         |  9 ++++++
 sysdeps/generic/ldsodefs.h  | 11 +++++++
 sysdeps/i386/configure      | 33 +++++++++++++++++++
 sysdeps/i386/configure.ac   | 23 +++++++++++++
 sysdeps/mips/Makefile       |  3 ++
 sysdeps/x86_64/configure    | 33 +++++++++++++++++++
 sysdeps/x86_64/configure.ac | 25 ++++++++++++++
 24 files changed, 449 insertions(+), 17 deletions(-)
 create mode 100644 csu/static-reloc.c
 create mode 100644 elf/dl-reloc-static-pie.c
 create mode 100644 gmon/tst-gmon-static-pie.c

diff --git a/INSTALL b/INSTALL
index d1a34c2a90..30804eca38 100644
--- a/INSTALL
+++ b/INSTALL
@@ -90,6 +90,15 @@  will be used, and CFLAGS sets optimization options for the compiler.
      systems support shared libraries; you need ELF support and
      (currently) the GNU linker.
 
+'--enable-static-pie'
+     Enable static position independent executable (static PIE) support.
+     Static PIE is similar to static executable, but can be loaded at
+     any address without help from a dynamic linker.  All static
+     programs as well as static tests are built as static PIE, except
+     for those marked with no-pie.  The resulting glibc can be used with
+     the GCC option, -static-pie, which is available with GCC 8 or
+     above, to create static PIE.
+
 '--disable-profile'
      Don't build libraries with profiling information.  You may want to
      use this option if you don't plan to do profiling.
diff --git a/Makeconfig b/Makeconfig
index 1346109ac0..99cc136bfa 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -352,6 +352,14 @@  ifndef static-start-installed-name
 static-start-installed-name = $(start-installed-name)
 endif
 
+ifeq (yes,$(enable-static-pie))
+# Link with rcrt1.o, instead of crt1.o, to call _dl_relocate_static_pie
+# to relocate static PIE.
+real-static-start-installed-name = r$(static-start-installed-name)
+else
+real-static-start-installed-name = $(static-start-installed-name)
+endif
+
 ifeq (yesyes,$(build-shared)$(have-z-combreloc))
 combreloc-LDFLAGS = -Wl,-z,combreloc
 LDFLAGS.so += $(combreloc-LDFLAGS)
@@ -371,6 +379,20 @@  LDFLAGS.so += $(hashstyle-LDFLAGS)
 LDFLAGS-rtld += $(hashstyle-LDFLAGS)
 endif
 
+ifeq (yes,$(enable-static-pie))
+pic-default = -DPIC
+# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE.
+pie-default = $(pie-ccflag)
+ifeq (yes,$(have-static-pie))
+default-pie-ldflag = -static-pie
+else
+# Static PIE can't have dynamic relocations in read-only segments since
+# static PIE is mapped into memory by kernel.  --eh-frame-hdr is needed
+# for PIE to support exception.
+default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text
+endif
+endif
+
 # If lazy relocations are disabled, add the -z now flag.  Use
 # LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to
 # test modules.
@@ -420,9 +442,9 @@  endif
 # Command for statically linking programs with the C library.
 ifndef +link-static
 +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
-	      $(DEFAULT-LDFLAGS-$(@F)) \
+	      $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
 	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
-	      $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \
+	      $(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \
 	      $(+preinit) $(+prectorT) \
 	      $(filter-out $(addprefix $(csu-objpfx),start.o \
 						     $(start-installed-name))\
@@ -637,8 +659,14 @@  endif
 +prectorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginS.o`
 +postctorS = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtendS.o`
 # Variants of the two previous definitions for statically linking programs.
+ifeq (yes,$(enable-static-pie))
+# Static PIE must use PIE variants.
++prectorT = $(+prectorS)
++postctorT = $(+postctorS)
+else
 +prectorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtbeginT.o`
 +postctorT = `$(CC) $(sysdep-LDFLAGS) --print-file-name=crtend.o`
+endif
 csu-objpfx = $(common-objpfx)csu/
 elf-objpfx = $(common-objpfx)elf/
 
@@ -959,7 +987,8 @@  libtypes = $(foreach o,$(object-suffixes-for-libc),$(libtype$o))
 all-object-suffixes := .o .os .oS
 object-suffixes :=
 CPPFLAGS-.o = $(pic-default)
-CFLAGS-.o = $(filter %frame-pointer,$(+cflags))
+# libc.a must be compiled with -fPIE/-fpie for static PIE.
+CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
 libtype.o := lib%.a
 object-suffixes += .o
 ifeq (yes,$(build-shared))
@@ -984,7 +1013,8 @@  ifeq (yes,$(build-profile))
 all-object-suffixes += .op
 object-suffixes += .op
 CPPFLAGS-.op = -DPROF $(pic-default)
-CFLAGS-.op = -pg
+# libc_p.a must be compiled with -fPIE/-fpie for static PIE.
+CFLAGS-.op = -pg $(pie-default)
 libtype.op = lib%_p.a
 endif
 
diff --git a/NEWS b/NEWS
index 48af4acaea..5b09359f2c 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,15 @@  Version 2.27
 
 Major new features:
 
+* The GNU C Library can now be compiled with support for building static
+  PIE executables (See --enable-static-pie in INSTALL).  These static PIE
+  exectuables are like static executables but can be loaded at any address
+  and provide additional security hardening benefits at the cost of some
+  memory and performance.  When the library is built with --enable-static-pie
+  the resulting libc.a is usable with GCC 8 and above to create static PIE
+  executables using the GCC option '-static-pie'.  This feature is currently
+  supported on i386, x86_64 and x32.
+
 * Optimized x86-64 asin, atan2, exp, expf, log, pow, atan, sin and tan
   with FMA, contributed by Arjan van de Ven and H.J. Lu from Intel.
 
diff --git a/config.h.in b/config.h.in
index 8d76dadca2..0ecb10939f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -241,6 +241,9 @@ 
 /* Build glibc with tunables support.  */
 #define HAVE_TUNABLES 0
 
+/* Define if static PIE is enabled.  */
+#define ENABLE_STATIC_PIE 0
+
 /* Some compiler options may now allow to use ebp in __asm__ (used mainly
    in i386 6 argument syscall issue).  */
 #define CAN_USE_REGISTER_ASM_EBP 0
diff --git a/configure b/configure
index caba102846..d4dfb90a38 100755
--- a/configure
+++ b/configure
@@ -765,6 +765,7 @@  with_default_link
 enable_sanity_checks
 enable_shared
 enable_profile
+enable_static_pie
 enable_timezone_tools
 enable_hardcoded_path_in_tests
 enable_stackguard_randomization
@@ -1420,6 +1421,8 @@  Optional Features:
                           in special situations) [default=yes]
   --enable-shared         build shared library [default=yes if GNU ld]
   --enable-profile        build profiled library [default=no]
+  --enable-static-pie     enable static PIE support and use it in the
+                          testsuite [default=no]
   --disable-timezone-tools
                           do not install timezone tools [default=install]
   --enable-hardcoded-path-in-tests
@@ -3365,6 +3368,13 @@  else
   profile=no
 fi
 
+# Check whether --enable-static-pie was given.
+if test "${enable_static_pie+set}" = set; then :
+  enableval=$enable_static_pie; static_pie=$enableval
+else
+  static_pie=no
+fi
+
 # Check whether --enable-timezone-tools was given.
 if test "${enable_timezone_tools+set}" = set; then :
   enableval=$enable_timezone_tools; enable_timezone_tools=$enableval
@@ -5805,6 +5815,62 @@  fi
 $as_echo "$libc_linker_feature" >&6; }
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5
+$as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; }
+libc_linker_feature=no
+if test x"$gnu_ld" = x"yes"; then
+  libc_linker_check=`$LD -v --help 2>/dev/null | grep "\--no-dynamic-linker"`
+  if test -n "$libc_linker_check"; then
+    cat > conftest.c <<EOF
+int _start (void) { return 42; }
+EOF
+    if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
+				-Wl,--no-dynamic-linker -nostdlib -nostartfiles
+				-fPIC -shared -o conftest.so conftest.c
+				1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+      libc_linker_feature=yes
+    fi
+    rm -f conftest*
+  fi
+fi
+if test $libc_linker_feature = yes; then
+  libc_cv_no_dynamic_linker=yes
+else
+  libc_cv_no_dynamic_linker=no
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
+$as_echo "$libc_linker_feature" >&6; }
+config_vars="$config_vars
+have-no-dynamic-linker = $libc_cv_no_dynamic_linker"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -static-pie" >&5
+$as_echo_n "checking for -static-pie... " >&6; }
+if ${libc_cv_static_pie+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if { ac_try='${CC-cc} -static-pie -xc /dev/null -S -o /dev/null'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  libc_cv_static_pie=yes
+else
+  libc_cv_static_pie=no
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie" >&5
+$as_echo "$libc_cv_static_pie" >&6; }
+config_vars="$config_vars
+have-static-pie = $libc_cv_static_pie"
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fpie" >&5
 $as_echo_n "checking for -fpie... " >&6; }
 if ${libc_cv_fpie+:} false; then :
@@ -6704,6 +6770,19 @@  $as_echo "$libc_cv_pie_default" >&6; }
 libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
 
 
+if test "$static_pie" = yes; then
+  # The linker must support --no-dynamic-linker.
+  if test "$libc_cv_no_dynamic_linker" != yes; then
+    as_fn_error $? "linker support for --no-dynamic-linker needed" "$LINENO" 5
+  fi
+  # Default to PIE.
+  libc_cv_pie_default=yes
+  $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h
+
+fi
+config_vars="$config_vars
+enable-static-pie = $static_pie"
+
 
 
 
diff --git a/configure.ac b/configure.ac
index 9707ae4d8e..78564f3746 100644
--- a/configure.ac
+++ b/configure.ac
@@ -176,6 +176,11 @@  AC_ARG_ENABLE([profile],
 			     [build profiled library @<:@default=no@:>@]),
 	      [profile=$enableval],
 	      [profile=no])
+AC_ARG_ENABLE([static-pie],
+	      AC_HELP_STRING([--enable-static-pie],
+			     [enable static PIE support and use it in the testsuite @<:@default=no@:>@]),
+	      [static_pie=$enableval],
+	      [static_pie=no])
 AC_ARG_ENABLE([timezone-tools],
 	      AC_HELP_STRING([--disable-timezone-tools],
 			     [do not install timezone tools @<:@default=install@:>@]),
@@ -1280,6 +1285,19 @@  LIBC_LINKER_FEATURE([-z execstack], [-Wl,-z,execstack],
 		    [libc_cv_z_execstack=yes], [libc_cv_z_execstack=no])
 AC_SUBST(libc_cv_z_execstack)
 
+LIBC_LINKER_FEATURE([--no-dynamic-linker],
+		    [-Wl,--no-dynamic-linker],
+		    [libc_cv_no_dynamic_linker=yes],
+		    [libc_cv_no_dynamic_linker=no])
+LIBC_CONFIG_VAR([have-no-dynamic-linker], [$libc_cv_no_dynamic_linker])
+
+AC_CACHE_CHECK(for -static-pie, libc_cv_static_pie, [dnl
+LIBC_TRY_CC_OPTION([-static-pie],
+		   [libc_cv_static_pie=yes],
+		   [libc_cv_static_pie=no])
+])
+LIBC_CONFIG_VAR([have-static-pie], [$libc_cv_static_pie])
+
 AC_CACHE_CHECK(for -fpie, libc_cv_fpie, [dnl
 LIBC_TRY_CC_OPTION([-fpie], [libc_cv_fpie=yes], [libc_cv_fpie=no])
 ])
@@ -1787,6 +1805,17 @@  AC_SUBST(libc_cv_pie_default)
 libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
 AC_SUBST(libc_cv_multidir)
 
+if test "$static_pie" = yes; then
+  # The linker must support --no-dynamic-linker.
+  if test "$libc_cv_no_dynamic_linker" != yes; then
+    AC_MSG_ERROR([linker support for --no-dynamic-linker needed])
+  fi
+  # Default to PIE.
+  libc_cv_pie_default=yes
+  AC_DEFINE(ENABLE_STATIC_PIE)
+fi
+LIBC_CONFIG_VAR([enable-static-pie], [$static_pie])
+
 AC_SUBST(profile)
 AC_SUBST(static_nss)
 
diff --git a/csu/Makefile b/csu/Makefile
index e42a32b3eb..86b95a9759 100644
--- a/csu/Makefile
+++ b/csu/Makefile
@@ -37,7 +37,9 @@  extra-objs = start.o \
 	     S$(start-installed-name)
 omit-deps = $(patsubst %.o,%,$(start-installed-name) g$(start-installed-name) \
 			     b$(start-installed-name) $(csu-dummies) \
-			     S$(start-installed-name))
+			     S$(start-installed-name) \
+			     r$(start-installed-name) \
+			     gr$(start-installed-name))
 install-lib = $(start-installed-name) g$(start-installed-name) $(csu-dummies)
 
 # No tests are allowed in the csu/ subdirectory because the startup
@@ -60,10 +62,17 @@  extra-objs += gmon-start.o
 endif
 
 ifneq ($(start-installed-name),$(static-start-installed-name))
+# FIXME: Only Hurd defines static-start-installed-name.  Hurd needs to
+# provide special rules to support static PIE.
 extra-objs += $(static-start-installed-name) g$(static-start-installed-name)
 omit-deps += $(patsubst %.o,%,$(static-start-installed-name) \
 			     g$(static-start-installed-name))
 install-lib += $(static-start-installed-name) g$(static-start-installed-name)
+else
+ifeq (yes,$(enable-static-pie))
+extra-objs += r$(start-installed-name) gr$(start-installed-name)
+install-lib += r$(start-installed-name) gr$(start-installed-name)
+endif
 endif
 
 before-compile += $(objpfx)abi-tag.h
@@ -82,7 +91,10 @@  multilib-extra-objs = $(addprefix $(multidir)/, $(install-lib))
 extra-objs += $(multilib-extra-objs)
 endif
 
-extra-objs += abi-note.o init.o
+extra-objs += abi-note.o init.o static-reloc.o
+ifeq (yes,$(build-shared))
+extra-objs += static-reloc.os
+endif
 asm-CPPFLAGS += -I$(objpfx).
 
 # Enable unwinding so backtrace unwinds to __libc_start_main
@@ -101,6 +113,9 @@  ifndef start-installed-name-rule
 # We link the ELF startfile along with a SHT_NOTE section indicating
 # the kernel ABI the binaries linked with this library will require.
 $(objpfx)$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \
+				  $(objpfx)init.o $(objpfx)static-reloc.o
+	$(link-relocatable)
+$(objpfx)r$(start-installed-name): $(objpfx)start.o $(objpfx)abi-note.o \
 				  $(objpfx)init.o
 	$(link-relocatable)
 $(objpfx)S$(start-installed-name): $(objpfx)start.os $(objpfx)abi-note.o \
@@ -113,7 +128,10 @@  endif
 # to turn on profiling code at startup.
 ifeq (yes,$(build-shared))
 $(objpfx)g$(start-installed-name): \
-  $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os
+  $(objpfx)g%: $(objpfx)S% $(objpfx)gmon-start.os $(objpfx)static-reloc.os
+	$(link-relocatable)
+$(objpfx)gr$(start-installed-name): \
+  $(objpfx)gr%: $(objpfx)r% $(objpfx)gmon-start.o
 	$(link-relocatable)
 ifneq ($(start-installed-name),$(static-start-installed-name))
 $(objpfx)g$(static-start-installed-name): \
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 24c63be02f..34dd125260 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -141,6 +141,8 @@  LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
 
 #ifndef SHARED
+  _dl_relocate_static_pie ();
+
   char **ev = &argv[argc + 1];
 
   __environ = ev;
diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index 00138eb43a..1f8ddaf543 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -114,6 +114,8 @@  __libc_setup_tls (void)
   size_t tcb_offset;
   const ElfW(Phdr) *phdr;
 
+  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+
   /* Look through the TLS segment if there is any.  */
   if (_dl_phdr != NULL)
     for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
@@ -122,7 +124,7 @@  __libc_setup_tls (void)
 	  /* Remember the values we need.  */
 	  memsz = phdr->p_memsz;
 	  filesz = phdr->p_filesz;
-	  initimage = (void *) phdr->p_vaddr;
+	  initimage = (void *) phdr->p_vaddr + main_map->l_addr;
 	  align = phdr->p_align;
 	  if (phdr->p_align > max_align)
 	    max_align = phdr->p_align;
@@ -163,8 +165,6 @@  __libc_setup_tls (void)
   _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2;
   // _dl_static_dtv[1].counter = 0;		would be needed if not already done
 
-  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
-
   /* Initialize the TLS block.  */
 #if TLS_TCB_AT_TP
   _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
diff --git a/csu/static-reloc.c b/csu/static-reloc.c
new file mode 100644
index 0000000000..37be72c8ea
--- /dev/null
+++ b/csu/static-reloc.c
@@ -0,0 +1,26 @@ 
+/* Special startup support for non-PIE static executables.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if ENABLE_STATIC_PIE
+#include <ldsodefs.h>
+
+void
+_dl_relocate_static_pie (void)
+{
+}
+#endif
diff --git a/elf/Makefile b/elf/Makefile
index d49fd4673d..4c6f9e0a49 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -24,7 +24,8 @@  include ../Makeconfig
 headers		= elf.h bits/elfclass.h link.h bits/link.h
 routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 		  dl-addr dl-addr-obj enbl-secure dl-profstub \
-		  dl-origin dl-libc dl-sym dl-sysdep dl-error
+		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
+		  dl-reloc-static-pie
 
 # The core dynamic linking functions are in libc for the static and
 # profiled libraries.
@@ -52,7 +53,7 @@  endif
 all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
 # But they are absent from the shared libc, because that code is in ld.so.
 elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
-		    dl-sysdep dl-exception
+		    dl-sysdep dl-exception dl-reloc-static-pie
 shared-only-routines += dl-caller
 
 # ld.so uses those routines, plus some special stuff for being the program
@@ -153,7 +154,7 @@  tests-static-internal := tst-tls1-static tst-tls2-static \
 	       tst-tls1-static-non-pie
 
 CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o
-DEFAULT-LDFLAGS-tst-tls1-static-non-pie = $(no-pie-ldflag)
+tst-tls1-static-non-pie-no-pie = yes
 
 tests := tst-tls9 tst-leaks1 \
 	tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
new file mode 100644
index 0000000000..6e43aea76a
--- /dev/null
+++ b/elf/dl-reloc-static-pie.c
@@ -0,0 +1,52 @@ 
+/* Support for relocating static PIE.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if ENABLE_STATIC_PIE
+#include <unistd.h>
+#include <ldsodefs.h>
+#include "dynamic-link.h"
+
+/* Relocate static executable with PIE.  */
+
+void
+_dl_relocate_static_pie (void)
+{
+  struct link_map *main_map = _dl_get_dl_main_map ();
+
+# define STATIC_PIE_BOOTSTRAP
+# define BOOTSTRAP_MAP (main_map)
+# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
+# include "dynamic-link.h"
+
+  /* Figure out the run-time load address of static PIE.  */
+  main_map->l_addr = elf_machine_load_address ();
+
+  /* Read our own dynamic section and fill in the info array.  */
+  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
+  elf_get_dynamic_info (main_map, NULL);
+
+# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+  ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info);
+# endif
+
+  /* Relocate ourselves so we can do normal function calls and
+     data access using the global offset table.  */
+  ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0);
+  main_map->l_relocated = 1;
+}
+#endif
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 235d3a7f46..b9fc1a66fe 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -385,3 +385,14 @@  _dl_non_dynamic_init (void)
 #ifdef DL_SYSINFO_IMPLEMENTATION
 DL_SYSINFO_IMPLEMENTATION
 #endif
+
+#if ENABLE_STATIC_PIE
+/* Since relocation to hidden _dl_main_map causes relocation overflow on
+   aarch64, a function is used to get the address of _dl_main_map.  */
+
+struct link_map *
+_dl_get_dl_main_map (void)
+{
+  return &_dl_main_map;
+}
+#endif
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index ebea7567cd..6278649711 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -94,7 +94,7 @@  elf_machine_lazy_rel (struct link_map *map,
 
 #ifdef RESOLVE_MAP
 
-# ifdef RTLD_BOOTSTRAP
+# if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
 #  define ELF_DURING_STARTUP (1)
 # else
 #  define ELF_DURING_STARTUP (0)
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index 7525c3a5b2..eb26d23649 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -38,7 +38,7 @@  elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
   typedef Elf64_Xword d_tag_utype;
 #endif
 
-#ifndef RTLD_BOOTSTRAP
+#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP
   if (dyn == NULL)
     return;
 #endif
@@ -139,9 +139,11 @@  elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
   /* Only the bind now flags are allowed.  */
   assert (info[VERSYMIDX (DT_FLAGS_1)] == NULL
 	  || (info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val & ~DF_1_NOW) == 0);
+  /* Flags must not be set for ld.so.  */
   assert (info[DT_FLAGS] == NULL
 	  || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
-  /* Flags must not be set for ld.so.  */
+#endif
+#if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP
   assert (info[DT_RUNPATH] == NULL);
   assert (info[DT_RPATH] == NULL);
 #else
diff --git a/gmon/Makefile b/gmon/Makefile
index 89ab3fc7da..29e746723e 100644
--- a/gmon/Makefile
+++ b/gmon/Makefile
@@ -39,6 +39,10 @@  tests-static += tst-gmon-static
 ifeq (yesyes,$(have-fpie)$(build-shared))
 tests += tst-gmon-pie
 tests-pie += tst-gmon-pie
+ifeq (yes,$(enable-static-pie))
+tests += tst-gmon-static-pie
+tests-static += tst-gmon-static-pie
+endif
 endif
 
 # The mcount code won't work without a frame pointer.
@@ -54,7 +58,7 @@  endif
 
 CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
 CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o
-DEFAULT-LDFLAGS-tst-gmon-static = $(no-pie-ldflag)
+tst-gmon-static-no-pie = yes
 tst-gmon-static-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static.data
 ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-gmon-static-gprof.out
@@ -67,6 +71,15 @@  ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-gmon-pie-gprof.out
 endif
 
+ifeq (yes,$(enable-static-pie))
+CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
+CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o
+tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-gmon-static-pie-gprof.out
+endif
+endif
+
 
 include ../Rules
 
@@ -111,3 +124,13 @@  clean-tst-gmon-pie-data:
 $(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out
 	$(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \
 	$(evaluate-test)
+
+$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data
+clean-tst-gmon-static-pie-data:
+	rm -f $(objpfx)tst-gmon-static-pie.data.*
+
+$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \
+					$(objpfx)tst-gmon-static-pie.out
+	$(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \
+		$(objpfx)tst-gmon-static-pie.data.* > $@; \
+	$(evaluate-test)
diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c
new file mode 100644
index 0000000000..1eef2583b6
--- /dev/null
+++ b/gmon/tst-gmon-static-pie.c
@@ -0,0 +1 @@ 
+#include "tst-gmon.c"
diff --git a/manual/install.texi b/manual/install.texi
index ea559e4e72..0efa8572df 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -120,6 +120,15 @@  Don't build shared libraries even if it is possible.  Not all systems
 support shared libraries; you need ELF support and (currently) the GNU
 linker.
 
+@item --enable-static-pie
+Enable static position independent executable (static PIE) support.
+Static PIE is similar to static executable, but can be loaded at any
+address without help from a dynamic linker.  All static programs as
+well as static tests are built as static PIE, except for those marked
+with no-pie.  The resulting glibc can be used with the GCC option,
+-static-pie, which is available with GCC 8 or above, to create static
+PIE.
+
 @item --disable-profile
 Don't build libraries with profiling information.  You may want to use
 this option if you don't plan to do profiling.
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 7a65dc641c..196513851f 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1051,6 +1051,17 @@  extern void _dl_determine_tlsoffset (void) attribute_hidden;
    stack protector, among other things).  */
 void __libc_setup_tls (void);
 
+# if ENABLE_STATIC_PIE
+/* Relocate static executable with PIE.  */
+extern void _dl_relocate_static_pie (void) attribute_hidden;
+
+/* Get a pointer to _dl_main_map.  */
+extern struct link_map * _dl_get_dl_main_map (void)
+  __attribute__ ((visibility ("hidden")));
+# else
+#  define _dl_relocate_static_pie()
+# endif
+
 /* Initialization of libpthread for statically linked applications.
    If libpthread is not linked in, this is an empty function.  */
 void __pthread_initialize_minimal (void) weak_function;
diff --git a/sysdeps/i386/configure b/sysdeps/i386/configure
index 4cf968d8bc..90c63caf35 100644
--- a/sysdeps/i386/configure
+++ b/sysdeps/i386/configure
@@ -50,6 +50,39 @@  fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_compiler_builtin_inlined" >&5
 $as_echo "$libc_compiler_builtin_inlined" >&6; }
 
+if test "$static_pie" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5
+$as_echo_n "checking for linker static PIE support... " >&6; }
+if ${libc_cv_ld_static_pie+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.s <<\EOF
+	.text
+	.global _start
+_start:
+	movl	_start@GOT(%ebx), %eax
+EOF
+  libc_cv_pie_option="-Wl,-pie"
+  libc_cv_ld_static_pie=no
+  if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then
+      libc_cv_ld_static_pie=yes
+    fi
+  fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5
+$as_echo "$libc_cv_ld_static_pie" >&6; }
+  if test "$libc_cv_ld_static_pie" != yes; then
+    as_fn_error $? "linker support for static PIE needed" "$LINENO" 5
+  fi
+fi
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Intel MPX support" >&5
 $as_echo_n "checking for Intel MPX support... " >&6; }
 if ${libc_cv_asm_mpx+:} false; then :
diff --git a/sysdeps/i386/configure.ac b/sysdeps/i386/configure.ac
index b598b120bc..6d2068d2b3 100644
--- a/sysdeps/i386/configure.ac
+++ b/sysdeps/i386/configure.ac
@@ -30,6 +30,29 @@  LIBC_COMPILER_BUILTIN_INLINED(
 *** Please use host i786, i686, i586, or i486.
 *** For example: /source/glibc/configure CFLAGS='-O2 -march=i686' ...])])
 
+dnl Check if linker can convert "movl main@GOT(%ebx), %eax" to
+dnl "leal main@GOTOFF(%ebx), %eax" for static PIE.
+if test "$static_pie" = yes; then
+  AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl
+cat > conftest.s <<\EOF
+	.text
+	.global _start
+_start:
+	movl	_start@GOT(%ebx), %eax
+EOF
+  libc_cv_pie_option="-Wl,-pie"
+  libc_cv_ld_static_pie=no
+  if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then
+    if $READELF -r conftest | grep 'There are no relocations in this file.' > /dev/null; then
+      libc_cv_ld_static_pie=yes
+    fi
+  fi
+rm -f conftest*])
+  if test "$libc_cv_ld_static_pie" != yes; then
+    AC_MSG_ERROR([linker support for static PIE needed])
+  fi
+fi
+
 dnl Check whether asm supports Intel MPX
 AC_CACHE_CHECK(for Intel MPX support, libc_cv_asm_mpx, [dnl
 cat > conftest.s <<\EOF
diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile
index fd891ddf09..7ac6fa5031 100644
--- a/sysdeps/mips/Makefile
+++ b/sysdeps/mips/Makefile
@@ -23,6 +23,9 @@  CPPFLAGS-crtn.S += $(pic-ccflag)
 endif
 
 ASFLAGS-.os += $(pic-ccflag)
+# libc.a and libc_p.a must be compiled with -fPIE/-fpie for static PIE.
+ASFLAGS-.o += $(pie-default)
+ASFLAGS-.op += $(pie-default)
 
 ifeq ($(subdir),elf)
 ifneq ($(o32-fpabi),)
diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure
index efef46b1b7..8674d14569 100644
--- a/sysdeps/x86_64/configure
+++ b/sysdeps/x86_64/configure
@@ -85,6 +85,39 @@  if test x"$build_mathvec" = xnotset; then
   build_mathvec=yes
 fi
 
+if test "$static_pie" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5
+$as_echo_n "checking for linker static PIE support... " >&6; }
+if ${libc_cv_ld_static_pie+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.s <<\EOF
+	.text
+	.global _start
+	.weak foo
+_start:
+	leaq	foo(%rip), %rax
+EOF
+  libc_cv_pie_option="-Wl,-pie"
+  if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    libc_cv_ld_static_pie=yes
+  else
+    libc_cv_ld_static_pie=no
+  fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5
+$as_echo "$libc_cv_ld_static_pie" >&6; }
+  if test "$libc_cv_ld_static_pie" != yes; then
+    as_fn_error $? "linker support for static PIE needed" "$LINENO" 5
+  fi
+fi
+
 $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h
 
 
diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac
index fa86e953ee..b7d2c0124f 100644
--- a/sysdeps/x86_64/configure.ac
+++ b/sysdeps/x86_64/configure.ac
@@ -44,6 +44,31 @@  if test x"$build_mathvec" = xnotset; then
   build_mathvec=yes
 fi
 
+dnl Check if linker supports static PIE with the fix for
+dnl
+dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782
+dnl
+if test "$static_pie" = yes; then
+  AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl
+cat > conftest.s <<\EOF
+	.text
+	.global _start
+	.weak foo
+_start:
+	leaq	foo(%rip), %rax
+EOF
+  libc_cv_pie_option="-Wl,-pie"
+  if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then
+    libc_cv_ld_static_pie=yes
+  else
+    libc_cv_ld_static_pie=no
+  fi
+rm -f conftest*])
+  if test "$libc_cv_ld_static_pie" != yes; then
+    AC_MSG_ERROR([linker support for static PIE needed])
+  fi
+fi
+
 dnl It is always possible to access static and hidden symbols in an
 dnl position independent way.
 AC_DEFINE(PI_STATIC_AND_HIDDEN)
-- 
2.14.3