public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* PING: [PATCH] Add --enable-static-pie to build static PIE
@ 2017-09-11 16:47 H.J. Lu
  2017-09-26 22:51 ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-09-11 16:47 UTC (permalink / raw)
  To: GNU C Library

On Fri, Sep 1, 2017 at 10:49 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> --enable-static-pie configures glibc to compile libc.a as PIE and
> creates static executables as PIE.  A static position independent
> executable (static PIE) is similar to static executable, but can be
> loaded at any address without help from a dynamic linker.  All linker
> input files must be compiled with -fpie or -fPIE.  "-z text" is also
> passed to linker to prevent dynamic relocations in read-only segments.
> It passes -static-pie to the GCC driver with the patch:
>
> https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01455.html
>
> This patch requires:
>
> 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
>
> Binutils 2.29 or above are OK.
>
> Tested on i686 and x86-64.
>
> OK for master?
>
> H.J.
> ---
>         * Makeconfig (pic-default): Updated for --enable-static-pie.
>         (pie-default): New for --enable-static-pie.
>         (default-pie-ldflag): Likewise.
>         (+link-static-before-libc): Add $(default-pie-ldflag).
>         (+prectorT): Updated for --enable-static-pie.
>         (+postctorT): Likewise.
>         (CFLAGS-.o): Add $(pie-default).
>         (CFLAGS-.op): Likewise.
>         * 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/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.
>         * elf/dl-support.c: Include "dynamic-link.h" and don't include
>         "get-dynamic-info.h" for --enable-static-pie.
>         (_dl_relocate_static_pie): New function for --enable-static-pie.
>         (STATIC_PIE_BOOTSTRAP): New for --enable-static-pie.
>         (RESOLVE_MAP): Likewise.
>         * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
>         STATIC_PIE_BOOTSTRAP.
>         * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
>         * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
>         * sysdeps/x86_64/configure.ac: Check if linker supports static PIE.
>         * sysdeps/x86_64/configure: Regenerated.
> ---
>  Makeconfig                  | 20 ++++++++++--
>  config.h.in                 |  3 ++
>  configure                   | 78 +++++++++++++++++++++++++++++++++++++++++++++
>  configure.ac                | 29 +++++++++++++++++
>  csu/libc-start.c            |  2 ++
>  csu/libc-tls.c              |  6 ++--
>  elf/dl-support.c            | 39 +++++++++++++++++++++--
>  elf/dynamic-link.h          |  2 +-
>  elf/get-dynamic-info.h      |  6 ++--
>  sysdeps/generic/ldsodefs.h  |  7 ++++
>  sysdeps/x86_64/configure    | 33 +++++++++++++++++++
>  sysdeps/x86_64/configure.ac | 22 +++++++++++++
>  12 files changed, 237 insertions(+), 10 deletions(-)
>
> diff --git a/Makeconfig b/Makeconfig
> index b51904b797..b45209fe5f 100644
> --- a/Makeconfig
> +++ b/Makeconfig
> @@ -386,6 +386,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
>  LDFLAGS-rtld += $(hashstyle-LDFLAGS)
>  endif
>
> +ifeq (yes,$(enable-static-pie))
> +pic-default = -DPIC
> +pie-default = $(pie-ccflag)
> +ifeq (yes,$(have-static-pie))
> +default-pie-ldflag = -static-pie
> +else
> +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.
> @@ -435,6 +445,7 @@ endif
>  # Command for statically linking programs with the C library.
>  ifndef +link-static
>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
> +             $(default-pie-ldflag) \
>               $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
>               $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
>               $(+preinit) $(+prectorT) \
> @@ -651,8 +662,13 @@ 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))
> ++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/
>
> @@ -973,7 +989,7 @@ 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))
> +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
>  libtype.o := lib%.a
>  object-suffixes += .o
>  ifeq (yes,$(build-shared))
> @@ -998,7 +1014,7 @@ ifeq (yes,$(build-profile))
>  all-object-suffixes += .op
>  object-suffixes += .op
>  CPPFLAGS-.op = -DPROF $(pic-default)
> -CFLAGS-.op = -pg
> +CFLAGS-.op = -pg $(pie-default)
>  libtype.op = lib%_p.a
>  endif
>
> diff --git a/config.h.in b/config.h.in
> index 014fb4ea0e..26ed7865ef 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -236,6 +236,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 5cb5210107..a04c59bacd 100755
> --- a/configure
> +++ b/configure
> @@ -767,6 +767,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
> @@ -1424,6 +1425,7 @@ 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     build static executables as PIE [default=no]
>    --disable-timezone-tools
>                            do not install timezone tools [default=install]
>    --enable-hardcoded-path-in-tests
> @@ -3372,6 +3374,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
> @@ -5994,6 +6003,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 :
> @@ -6888,6 +6953,19 @@ fi
>  $as_echo "$libc_cv_pie_default" >&6; }
>
>
> +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 2c6308883c..96af835ce8 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@:>@]),
> +             [static_pie=$enableval],
> +             [static_pie=no])
>  AC_ARG_ENABLE([timezone-tools],
>               AC_HELP_STRING([--disable-timezone-tools],
>                              [do not install timezone tools @<:@default=install@:>@]),
> @@ -1460,6 +1465,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])
>  ])
> @@ -1962,6 +1980,17 @@ fi
>  rm -f conftest.*])
>  AC_SUBST(libc_cv_pie_default)
>
> +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/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/elf/dl-support.c b/elf/dl-support.c
> index 48340f7959..09b2229d48 100644
> --- a/elf/dl-support.c
> +++ b/elf/dl-support.c
> @@ -26,7 +26,11 @@
>  #include <sys/param.h>
>  #include <stdint.h>
>  #include <ldsodefs.h>
> -#include <dl-machine.h>
> +#if ENABLE_STATIC_PIE
> +# include "dynamic-link.h"
> +#else
> +# include <dl-machine.h>
> +#endif
>  #include <libc-lock.h>
>  #include <dl-cache.h>
>  #include <dl-librecon.h>
> @@ -199,7 +203,9 @@ const ElfW(Ehdr) *_dl_sysinfo_dso;
>
>  struct link_map *_dl_sysinfo_map;
>
> -# include "get-dynamic-info.h"
> +# if !ENABLE_STATIC_PIE
> +#  include "get-dynamic-info.h"
> +# endif
>  #endif
>  #include "setup-vdso.h"
>
> @@ -303,6 +309,35 @@ _dl_aux_init (ElfW(auxv_t) *av)
>  }
>  #endif
>
> +#if ENABLE_STATIC_PIE
> +/* Relocate static executable with PIE.  */
> +
> +void
> +_dl_relocate_static_pie (void)
> +{
> +# define STATIC_PIE_BOOTSTRAP
> +# define RESOLVE_MAP(sym, version, flags) (&_dl_main_map)
> +# include "dynamic-link.h"
> +
> +  /* Figure out the run-time load addres of static PIE.  */
> +  _dl_main_map.l_addr = elf_machine_load_address ();
> +
> +  /* Read our own dynamic section and fill in the info array.  */
> +  _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr
> +                      + elf_machine_dynamic ());
> +  elf_get_dynamic_info (&_dl_main_map, NULL);
> +
> +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> +  ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0);
> +  _dl_main_map.l_relocated = 1;
> +}
> +#endif
> +
>
>  void
>  internal_function
> diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
> index 60f2d91151..d3935f7da7 100644
> --- a/elf/dynamic-link.h
> +++ b/elf/dynamic-link.h
> @@ -95,7 +95,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/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index 49e673dd24..83791103cf 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1069,6 +1069,13 @@ extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden;
>     stack protector, among other things).  */
>  void __libc_setup_tls (void);
>
> +# if ENABLE_STATIC_PIE
> +/* Relocate static executable with PIE.  */
> +void _dl_relocate_static_pie (void) attribute_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/x86_64/configure b/sysdeps/x86_64/configure
> index efef46b1b7..8ee15b8a25 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 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..c2d7cf3e61 100644
> --- a/sysdeps/x86_64/configure.ac
> +++ b/sysdeps/x86_64/configure.ac
> @@ -44,6 +44,28 @@ if test x"$build_mathvec" = xnotset; then
>    build_mathvec=yes
>  fi
>
> +dnl Check if linker supports 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
> +       .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 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.13.5
>

Any comments?

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-11 16:47 PING: [PATCH] Add --enable-static-pie to build static PIE H.J. Lu
@ 2017-09-26 22:51 ` H.J. Lu
  2017-09-26 23:11   ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-09-26 22:51 UTC (permalink / raw)
  To: GNU C Library

On 9/11/17, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Sep 1, 2017 at 10:49 AM, H.J. Lu <hongjiu.lu@intel.com> wrote:
>> --enable-static-pie configures glibc to compile libc.a as PIE and
>> creates static executables as PIE.  A static position independent
>> executable (static PIE) is similar to static executable, but can be
>> loaded at any address without help from a dynamic linker.  All linker
>> input files must be compiled with -fpie or -fPIE.  "-z text" is also
>> passed to linker to prevent dynamic relocations in read-only segments.
>> It passes -static-pie to the GCC driver with the patch:
>>
>> https://gcc.gnu.org/ml/gcc-patches/2017-08/msg01455.html
>>
>> This patch requires:
>>
>> 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
>>
>> Binutils 2.29 or above are OK.
>>
>> Tested on i686 and x86-64.
>>
>> OK for master?
>>
>> H.J.
>> ---
>>         * Makeconfig (pic-default): Updated for --enable-static-pie.
>>         (pie-default): New for --enable-static-pie.
>>         (default-pie-ldflag): Likewise.
>>         (+link-static-before-libc): Add $(default-pie-ldflag).
>>         (+prectorT): Updated for --enable-static-pie.
>>         (+postctorT): Likewise.
>>         (CFLAGS-.o): Add $(pie-default).
>>         (CFLAGS-.op): Likewise.
>>         * 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/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.
>>         * elf/dl-support.c: Include "dynamic-link.h" and don't include
>>         "get-dynamic-info.h" for --enable-static-pie.
>>         (_dl_relocate_static_pie): New function for --enable-static-pie.
>>         (STATIC_PIE_BOOTSTRAP): New for --enable-static-pie.
>>         (RESOLVE_MAP): Likewise.
>>         * elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
>>         STATIC_PIE_BOOTSTRAP.
>>         * elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
>>         * sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
>>         * sysdeps/x86_64/configure.ac: Check if linker supports static
>> PIE.
>>         * sysdeps/x86_64/configure: Regenerated.
>> ---
>>  Makeconfig                  | 20 ++++++++++--
>>  config.h.in                 |  3 ++
>>  configure                   | 78
>> +++++++++++++++++++++++++++++++++++++++++++++
>>  configure.ac                | 29 +++++++++++++++++
>>  csu/libc-start.c            |  2 ++
>>  csu/libc-tls.c              |  6 ++--
>>  elf/dl-support.c            | 39 +++++++++++++++++++++--
>>  elf/dynamic-link.h          |  2 +-
>>  elf/get-dynamic-info.h      |  6 ++--
>>  sysdeps/generic/ldsodefs.h  |  7 ++++
>>  sysdeps/x86_64/configure    | 33 +++++++++++++++++++
>>  sysdeps/x86_64/configure.ac | 22 +++++++++++++
>>  12 files changed, 237 insertions(+), 10 deletions(-)
>>
>> diff --git a/Makeconfig b/Makeconfig
>> index b51904b797..b45209fe5f 100644
>> --- a/Makeconfig
>> +++ b/Makeconfig
>> @@ -386,6 +386,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
>>  LDFLAGS-rtld += $(hashstyle-LDFLAGS)
>>  endif
>>
>> +ifeq (yes,$(enable-static-pie))
>> +pic-default = -DPIC
>> +pie-default = $(pie-ccflag)
>> +ifeq (yes,$(have-static-pie))
>> +default-pie-ldflag = -static-pie
>> +else
>> +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.
>> @@ -435,6 +445,7 @@ endif
>>  # Command for statically linking programs with the C library.
>>  ifndef +link-static
>>  +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
>> +             $(default-pie-ldflag) \
>>               $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
>>               $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
>>               $(+preinit) $(+prectorT) \
>> @@ -651,8 +662,13 @@ 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))
>> ++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/
>>
>> @@ -973,7 +989,7 @@ 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))
>> +CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
>>  libtype.o := lib%.a
>>  object-suffixes += .o
>>  ifeq (yes,$(build-shared))
>> @@ -998,7 +1014,7 @@ ifeq (yes,$(build-profile))
>>  all-object-suffixes += .op
>>  object-suffixes += .op
>>  CPPFLAGS-.op = -DPROF $(pic-default)
>> -CFLAGS-.op = -pg
>> +CFLAGS-.op = -pg $(pie-default)
>>  libtype.op = lib%_p.a
>>  endif
>>
>> diff --git a/config.h.in b/config.h.in
>> index 014fb4ea0e..26ed7865ef 100644
>> --- a/config.h.in
>> +++ b/config.h.in
>> @@ -236,6 +236,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 5cb5210107..a04c59bacd 100755
>> --- a/configure
>> +++ b/configure
>> @@ -767,6 +767,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
>> @@ -1424,6 +1425,7 @@ 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     build static executables as PIE [default=no]
>>    --disable-timezone-tools
>>                            do not install timezone tools
>> [default=install]
>>    --enable-hardcoded-path-in-tests
>> @@ -3372,6 +3374,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
>> @@ -5994,6 +6003,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 :
>> @@ -6888,6 +6953,19 @@ fi
>>  $as_echo "$libc_cv_pie_default" >&6; }
>>
>>
>> +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 2c6308883c..96af835ce8 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@:>@]),
>> +             [static_pie=$enableval],
>> +             [static_pie=no])
>>  AC_ARG_ENABLE([timezone-tools],
>>               AC_HELP_STRING([--disable-timezone-tools],
>>                              [do not install timezone tools
>> @<:@default=install@:>@]),
>> @@ -1460,6 +1465,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])
>>  ])
>> @@ -1962,6 +1980,17 @@ fi
>>  rm -f conftest.*])
>>  AC_SUBST(libc_cv_pie_default)
>>
>> +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/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/elf/dl-support.c b/elf/dl-support.c
>> index 48340f7959..09b2229d48 100644
>> --- a/elf/dl-support.c
>> +++ b/elf/dl-support.c
>> @@ -26,7 +26,11 @@
>>  #include <sys/param.h>
>>  #include <stdint.h>
>>  #include <ldsodefs.h>
>> -#include <dl-machine.h>
>> +#if ENABLE_STATIC_PIE
>> +# include "dynamic-link.h"
>> +#else
>> +# include <dl-machine.h>
>> +#endif
>>  #include <libc-lock.h>
>>  #include <dl-cache.h>
>>  #include <dl-librecon.h>
>> @@ -199,7 +203,9 @@ const ElfW(Ehdr) *_dl_sysinfo_dso;
>>
>>  struct link_map *_dl_sysinfo_map;
>>
>> -# include "get-dynamic-info.h"
>> +# if !ENABLE_STATIC_PIE
>> +#  include "get-dynamic-info.h"
>> +# endif
>>  #endif
>>  #include "setup-vdso.h"
>>
>> @@ -303,6 +309,35 @@ _dl_aux_init (ElfW(auxv_t) *av)
>>  }
>>  #endif
>>
>> +#if ENABLE_STATIC_PIE
>> +/* Relocate static executable with PIE.  */
>> +
>> +void
>> +_dl_relocate_static_pie (void)
>> +{
>> +# define STATIC_PIE_BOOTSTRAP
>> +# define RESOLVE_MAP(sym, version, flags) (&_dl_main_map)
>> +# include "dynamic-link.h"
>> +
>> +  /* Figure out the run-time load addres of static PIE.  */
>> +  _dl_main_map.l_addr = elf_machine_load_address ();
>> +
>> +  /* Read our own dynamic section and fill in the info array.  */
>> +  _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr
>> +                      + elf_machine_dynamic ());
>> +  elf_get_dynamic_info (&_dl_main_map, NULL);
>> +
>> +# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>> +  ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0);
>> +  _dl_main_map.l_relocated = 1;
>> +}
>> +#endif
>> +
>>
>>  void
>>  internal_function
>> diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
>> index 60f2d91151..d3935f7da7 100644
>> --- a/elf/dynamic-link.h
>> +++ b/elf/dynamic-link.h
>> @@ -95,7 +95,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/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
>> index 49e673dd24..83791103cf 100644
>> --- a/sysdeps/generic/ldsodefs.h
>> +++ b/sysdeps/generic/ldsodefs.h
>> @@ -1069,6 +1069,13 @@ extern void _dl_determine_tlsoffset (void)
>> internal_function attribute_hidden;
>>     stack protector, among other things).  */
>>  void __libc_setup_tls (void);
>>
>> +# if ENABLE_STATIC_PIE
>> +/* Relocate static executable with PIE.  */
>> +void _dl_relocate_static_pie (void) attribute_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/x86_64/configure b/sysdeps/x86_64/configure
>> index efef46b1b7..8ee15b8a25 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 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..c2d7cf3e61 100644
>> --- a/sysdeps/x86_64/configure.ac
>> +++ b/sysdeps/x86_64/configure.ac
>> @@ -44,6 +44,28 @@ if test x"$build_mathvec" = xnotset; then
>>    build_mathvec=yes
>>  fi
>>
>> +dnl Check if linker supports 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
>> +       .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 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.13.5
>>
>
> Any comments?
>

Any objections?

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-26 22:51 ` H.J. Lu
@ 2017-09-26 23:11   ` Joseph Myers
  2017-09-27  8:30     ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-09-26 23:11 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library

On Tue, 26 Sep 2017, H.J. Lu wrote:

> Any objections?

This is a complicated feature; it clearly needs someone to do a detailed 
technical review before it can go in, however long that takes.  It's only 
borderline-obvious patches one might consider committing after a while in 
the absence of objections but without review or relevant maintainership.

Perhaps you could expand more on the design and the rationale for the 
choices made?  Why are x86_64 configure changes needed, for example?  
What changes might other architectures need to support this feature (when 
would an architecture need or not need architecture-specific configure 
changes, etc.), and have you tried a build-many-glibcs.py run with this 
option passed to all the builds to see how other architectures do?  Why 
build libc.a with -fPIE rather than building a separate PIE copy of libc.a 
(i.e., making this a bit more like --enable-profile as an option to build 
an additional library variant) and making GCC use that separate copy in 
the static-PIE case?

The patch is missing documentation in install.texi of the new configure 
option and associated regeneration of INSTALL.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-26 23:11   ` Joseph Myers
@ 2017-09-27  8:30     ` H.J. Lu
  2017-09-27  9:43       ` Szabolcs Nagy
                         ` (3 more replies)
  0 siblings, 4 replies; 28+ messages in thread
From: H.J. Lu @ 2017-09-27  8:30 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 2137 bytes --]

On 9/26/17, Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 26 Sep 2017, H.J. Lu wrote:
>
>> Any objections?
>
> This is a complicated feature; it clearly needs someone to do a detailed
> technical review before it can go in, however long that takes.  It's only
> borderline-obvious patches one might consider committing after a while in
> the absence of objections but without review or relevant maintainership.
>
> Perhaps you could expand more on the design and the rationale for the

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).

> choices made?  Why are x86_64 configure changes needed, for example?

This checks for linker fix:

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

> What changes might other architectures need to support this feature (when

Static PIE should work on all architectures which support PIE.

> would an architecture need or not need architecture-specific configure
> changes, etc.), and have you tried a build-many-glibcs.py run with this
> option passed to all the builds to see how other architectures do?  Why

build-many-glibcs.py has no regressions.  But I didn't try --enable-static-pie
with build-many-glibcs.py.  I encourage target maintainers to give
hjl/pie/static
branch a try.

> build libc.a with -fPIE rather than building a separate PIE copy of libc.a
> (i.e., making this a bit more like --enable-profile as an option to build
> an additional library variant) and making GCC use that separate copy in
> the static-PIE case?
>

No separate PIE copy of libc.a, is used for static PIE to minimize
GCC driver change.  To improve system security, glibc can be built with
--enable-static-pie, and the same libc.a can be used to build both static
executable and static PIE.

> The patch is missing documentation in install.texi of the new configure
> option and associated regeneration of INSTALL.

Done.  I also updated NEWS.

Here is the updated patch.

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --]
[-- Type: text/x-patch, Size: 21614 bytes --]

From f39009437f70000675460313c20b597ac3675e37 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

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.  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.

Static PIE should work on all architectures which support PIE.

NB: No separate PIE copy of libc.a, is used for static PIE to minimize
GCC driver change.  To improve system security, glibc can be built with
--enable-static-pie, and the same libc.a can be used to build both static
executable and static PIE.

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

Binutils 2.29 or above are OK.

Tested on i686 and x86-64.

	* INSTALL: Regenerated.
	* Makeconfig (pic-default): Updated for --enable-static-pie.
	(pie-default): New for --enable-static-pie.
	(default-pie-ldflag): Likewise.
	(+link-static-before-libc): Add $(default-pie-ldflag).
	(+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/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.
	* elf/dl-support.c: Include "dynamic-link.h" and don't include
	"get-dynamic-info.h" for --enable-static-pie.
	(_dl_relocate_static_pie): New function for --enable-static-pie.
	(STATIC_PIE_BOOTSTRAP): New for --enable-static-pie.
	(RESOLVE_MAP): Likewise.
	* elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
	STATIC_PIE_BOOTSTRAP.
	* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
	* manual/install.texi: Document --enable-static-pie.
	* sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
	* sysdeps/x86_64/configure.ac: Check if linker supports static PIE.
	* sysdeps/x86_64/configure: Regenerated.
---
 INSTALL                     |  5 +++
 Makeconfig                  | 20 ++++++++++--
 NEWS                        |  2 ++
 config.h.in                 |  3 ++
 configure                   | 78 +++++++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 29 +++++++++++++++++
 csu/libc-start.c            |  2 ++
 csu/libc-tls.c              |  6 ++--
 elf/dl-support.c            | 39 +++++++++++++++++++++--
 elf/dynamic-link.h          |  2 +-
 elf/get-dynamic-info.h      |  6 ++--
 manual/install.texi         |  5 +++
 sysdeps/generic/ldsodefs.h  |  7 ++++
 sysdeps/x86_64/configure    | 33 +++++++++++++++++++
 sysdeps/x86_64/configure.ac | 25 +++++++++++++++
 15 files changed, 252 insertions(+), 10 deletions(-)

diff --git a/INSTALL b/INSTALL
index 4d9024c667..67a0083b88 100644
--- a/INSTALL
+++ b/INSTALL
@@ -106,6 +106,11 @@ 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'
+     Build static executables 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.
+
 '--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 b51904b797..b45209fe5f 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -386,6 +386,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
 LDFLAGS-rtld += $(hashstyle-LDFLAGS)
 endif
 
+ifeq (yes,$(enable-static-pie))
+pic-default = -DPIC
+pie-default = $(pie-ccflag)
+ifeq (yes,$(have-static-pie))
+default-pie-ldflag = -static-pie
+else
+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.
@@ -435,6 +445,7 @@ endif
 # Command for statically linking programs with the C library.
 ifndef +link-static
 +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
+	      $(default-pie-ldflag) \
 	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
 	      $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
 	      $(+preinit) $(+prectorT) \
@@ -651,8 +662,13 @@ 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))
++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/
 
@@ -973,7 +989,7 @@ 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))
+CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
 libtype.o := lib%.a
 object-suffixes += .o
 ifeq (yes,$(build-shared))
@@ -998,7 +1014,7 @@ ifeq (yes,$(build-profile))
 all-object-suffixes += .op
 object-suffixes += .op
 CPPFLAGS-.op = -DPROF $(pic-default)
-CFLAGS-.op = -pg
+CFLAGS-.op = -pg $(pie-default)
 libtype.op = lib%_p.a
 endif
 
diff --git a/NEWS b/NEWS
index e346d2afe6..fcdef4385f 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ Version 2.27
 
 Major new features:
 
+* Add --enable-static-pie configure option to build static PIE.
+
 * 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 014fb4ea0e..26ed7865ef 100644
--- a/config.h.in
+++ b/config.h.in
@@ -236,6 +236,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 067d92d2ba..cd5cf5729f 100755
--- a/configure
+++ b/configure
@@ -767,6 +767,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
@@ -1424,6 +1425,7 @@ 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     build static executables as PIE [default=no]
   --disable-timezone-tools
                           do not install timezone tools [default=install]
   --enable-hardcoded-path-in-tests
@@ -3372,6 +3374,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
@@ -5994,6 +6003,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 :
@@ -6888,6 +6953,19 @@ fi
 $as_echo "$libc_cv_pie_default" >&6; }
 
 
+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 d412104d8c..09e1c7f23b 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@:>@]),
+	      [static_pie=$enableval],
+	      [static_pie=no])
 AC_ARG_ENABLE([timezone-tools],
 	      AC_HELP_STRING([--disable-timezone-tools],
 			     [do not install timezone tools @<:@default=install@:>@]),
@@ -1460,6 +1465,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])
 ])
@@ -1962,6 +1980,17 @@ fi
 rm -f conftest.*])
 AC_SUBST(libc_cv_pie_default)
 
+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/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/elf/dl-support.c b/elf/dl-support.c
index 5e3de90598..4e1e37072b 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -26,7 +26,11 @@
 #include <sys/param.h>
 #include <stdint.h>
 #include <ldsodefs.h>
-#include <dl-machine.h>
+#if ENABLE_STATIC_PIE
+# include "dynamic-link.h"
+#else
+# include <dl-machine.h>
+#endif
 #include <libc-lock.h>
 #include <dl-cache.h>
 #include <dl-librecon.h>
@@ -199,7 +203,9 @@ const ElfW(Ehdr) *_dl_sysinfo_dso;
 
 struct link_map *_dl_sysinfo_map;
 
-# include "get-dynamic-info.h"
+# if !ENABLE_STATIC_PIE
+#  include "get-dynamic-info.h"
+# endif
 #endif
 #include "setup-vdso.h"
 
@@ -302,6 +308,35 @@ _dl_aux_init (ElfW(auxv_t) *av)
 }
 #endif
 
+#if ENABLE_STATIC_PIE
+/* Relocate static executable with PIE.  */
+
+void
+_dl_relocate_static_pie (void)
+{
+# define STATIC_PIE_BOOTSTRAP
+# define RESOLVE_MAP(sym, version, flags) (&_dl_main_map)
+# include "dynamic-link.h"
+
+  /* Figure out the run-time load addres of static PIE.  */
+  _dl_main_map.l_addr = elf_machine_load_address ();
+
+  /* Read our own dynamic section and fill in the info array.  */
+  _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr
+		       + elf_machine_dynamic ());
+  elf_get_dynamic_info (&_dl_main_map, NULL);
+
+# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+  ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0);
+  _dl_main_map.l_relocated = 1;
+}
+#endif
+
 
 void
 _dl_non_dynamic_init (void)
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/manual/install.texi b/manual/install.texi
index 35948b1bbb..e09fb2a4db 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -136,6 +136,11 @@ 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
+Build static executables 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.
+
 @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 1a4449eeb3..b4c032a06c 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1048,6 +1048,13 @@ 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.  */
+void _dl_relocate_static_pie (void) attribute_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/x86_64/configure b/sysdeps/x86_64/configure
index efef46b1b7..8ee15b8a25 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 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..53e4a8277c 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 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.13.5


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27  8:30     ` H.J. Lu
@ 2017-09-27  9:43       ` Szabolcs Nagy
  2017-09-27 21:12         ` H.J. Lu
  2017-09-27 10:55       ` Florian Weimer
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 28+ messages in thread
From: Szabolcs Nagy @ 2017-09-27  9:43 UTC (permalink / raw)
  To: H.J. Lu, Joseph Myers; +Cc: nd, GNU C Library

On 27/09/17 09:30, H.J. Lu wrote:
> On 9/26/17, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Tue, 26 Sep 2017, H.J. Lu wrote:
>>
>>> Any objections?
>>
>> This is a complicated feature; it clearly needs someone to do a detailed
>> technical review before it can go in, however long that takes.  It's only
>> borderline-obvious patches one might consider committing after a while in
>> the absence of objections but without review or relevant maintainership.
>>
>> Perhaps you could expand more on the design and the rationale for the
> 
> 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).
> 

can it be too late to do the relocation in __libc_start_main?

that comes after the crt1 startup code and an arch specific wrapper
which may end up having R_*_RELATIVE relocs for various function
pointers (including __libc_start_main itself and its arguments)

what guarantees that __libc_start_main can always be called
without relocations (pc relative calls have limits on some
targets)?

i'd expect the relocation to happen in the crt1.o startup code.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27  8:30     ` H.J. Lu
  2017-09-27  9:43       ` Szabolcs Nagy
@ 2017-09-27 10:55       ` Florian Weimer
  2017-09-27 11:09         ` Szabolcs Nagy
  2017-09-27 21:14         ` H.J. Lu
  2017-09-27 12:41       ` Joseph Myers
  2017-09-28  9:37       ` Markus Trippelsdorf
  3 siblings, 2 replies; 28+ messages in thread
From: Florian Weimer @ 2017-09-27 10:55 UTC (permalink / raw)
  To: H.J. Lu, Joseph Myers; +Cc: GNU C Library

On 09/27/2017 10:30 AM, H.J. Lu wrote:
>> would an architecture need or not need architecture-specific configure
>> changes, etc.), and have you tried a build-many-glibcs.py run with this
>> option passed to all the builds to see how other architectures do?  Why

> build-many-glibcs.py has no regressions.

On which tree?  I think commit 6cd380dd366d728da9f579eeb9f7f4c47f48e474 
added absolute relocations to the startup code, which I expect will not 
work for static PIE.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27 10:55       ` Florian Weimer
@ 2017-09-27 11:09         ` Szabolcs Nagy
  2017-09-27 21:16           ` H.J. Lu
  2017-09-27 21:14         ` H.J. Lu
  1 sibling, 1 reply; 28+ messages in thread
From: Szabolcs Nagy @ 2017-09-27 11:09 UTC (permalink / raw)
  To: Florian Weimer, H.J. Lu, Joseph Myers; +Cc: nd, GNU C Library

On 27/09/17 11:55, Florian Weimer wrote:
> On 09/27/2017 10:30 AM, H.J. Lu wrote:
>>> would an architecture need or not need architecture-specific configure
>>> changes, etc.), and have you tried a build-many-glibcs.py run with this
>>> option passed to all the builds to see how other architectures do?  Why
> 
>> build-many-glibcs.py has no regressions.
> 
> On which tree?  I think commit 6cd380dd366d728da9f579eeb9f7f4c47f48e474 added absolute relocations to the
> startup code, which I expect will not work for static PIE.
> 

i'd expect the Scrt1.o to be used for PIE which have no ABS relocs
however it can have RELATIVE relocs if GOT entries are used i think
(even on x86_64).

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27  8:30     ` H.J. Lu
  2017-09-27  9:43       ` Szabolcs Nagy
  2017-09-27 10:55       ` Florian Weimer
@ 2017-09-27 12:41       ` Joseph Myers
  2017-09-27 21:28         ` H.J. Lu
  2017-09-28  9:37       ` Markus Trippelsdorf
  3 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-09-27 12:41 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library

On Wed, 27 Sep 2017, H.J. Lu wrote:

> > would an architecture need or not need architecture-specific configure
> > changes, etc.), and have you tried a build-many-glibcs.py run with this
> > option passed to all the builds to see how other architectures do?  Why
> 
> build-many-glibcs.py has no regressions.  But I didn't try --enable-static-pie
> with build-many-glibcs.py.  I encourage target maintainers to give
> hjl/pie/static
> branch a try.

I think the most useful test for this purpose (of assessing architecture 
support) is adding --enable-static-pie alongside --enable-profile in 
build-many-glibcs.py and seeing how the build goes.

> No separate PIE copy of libc.a, is used for static PIE to minimize
> GCC driver change.  To improve system security, glibc can be built with

The question should be what's best for the GNU system and the GNU 
toolchain as a whole, rather than minimizing the GCC driver changes.

> > The patch is missing documentation in install.texi of the new configure
> > option and associated regeneration of INSTALL.
> 
> Done.  I also updated NEWS.

To me, both the install.texi and NEWS changes read as saying that programs 
such as ldconfig are built as PIEs.  That's a separate matter from 
supporting user programs built as static PIEs.  I'd have thought the main 
point of this feature, which is the one that NEWS and install.texi should 
emphasize, is the support for user programs built as static PIEs.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27  9:43       ` Szabolcs Nagy
@ 2017-09-27 21:12         ` H.J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2017-09-27 21:12 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Joseph Myers, nd, GNU C Library

On 9/27/17, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
> On 27/09/17 09:30, H.J. Lu wrote:
>> On 9/26/17, Joseph Myers <joseph@codesourcery.com> wrote:
>>> On Tue, 26 Sep 2017, H.J. Lu wrote:
>>>
>>>> Any objections?
>>>
>>> This is a complicated feature; it clearly needs someone to do a detailed
>>> technical review before it can go in, however long that takes.  It's
>>> only
>>> borderline-obvious patches one might consider committing after a while
>>> in
>>> the absence of objections but without review or relevant maintainership.
>>>
>>> Perhaps you could expand more on the design and the rationale for the
>>
>> 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).
>>
>
> can it be too late to do the relocation in __libc_start_main?
>
> that comes after the crt1 startup code and an arch specific wrapper
> which may end up having R_*_RELATIVE relocs for various function
> pointers (including __libc_start_main itself and its arguments)
>
> what guarantees that __libc_start_main can always be called
> without relocations (pc relative calls have limits on some
> targets)?
>
> i'd expect the relocation to happen in the crt1.o startup code.
>

I expect that all relocations before __libc_start_main should be
resolved by linker.

For x86, I did

commit 5b736bc9b55115e67129e77db4de6cf193054cd2
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Aug 2 10:27:14 2017 -0700

    x86-64: Check PIC instead of SHARED in start.S

    Since start.o may be compiled as PIC, we should check PIC instead of
    SHARED.

            * sysdeps/x86_64/start.S (_start): Check PIC instead of SHARED.

 commit 1e8e527dd9718eaebe8417b73befb0c821b7b327
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Aug 4 12:59:35 2017 -0700

    i386: Support static PIE in start.S

    Since start.o may be compiled as PIC, we should check PIC instead of
    SHARED.  Also avoid dynamic relocation against main in static PIE since
    _start is the entry point before the executable is relocated.

            * sysdeps/i386/start.S (_start): Check Check PIC instead of
            SHARED.  Avoid dynamic relocation against main in static PIE.

I expected other targets can be fixed similarly.

H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27 10:55       ` Florian Weimer
  2017-09-27 11:09         ` Szabolcs Nagy
@ 2017-09-27 21:14         ` H.J. Lu
  1 sibling, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2017-09-27 21:14 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Joseph Myers, GNU C Library

On 9/27/17, Florian Weimer <fweimer@redhat.com> wrote:
> On 09/27/2017 10:30 AM, H.J. Lu wrote:
>>> would an architecture need or not need architecture-specific configure
>>> changes, etc.), and have you tried a build-many-glibcs.py run with this
>>> option passed to all the builds to see how other architectures do?  Why
>
>> build-many-glibcs.py has no regressions.
>
> On which tree?  I think commit 6cd380dd366d728da9f579eeb9f7f4c47f48e474

I used hjl/pie/static branch.

> added absolute relocations to the startup code, which I expect will not
> work for static PIE.
>

It may need something like

commit 1e8e527dd9718eaebe8417b73befb0c821b7b327
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Aug 4 12:59:35 2017 -0700

    i386: Support static PIE in start.S

    Since start.o may be compiled as PIC, we should check PIC instead of
    SHARED.  Also avoid dynamic relocation against main in static PIE since
    _start is the entry point before the executable is relocated.

            * sysdeps/i386/start.S (_start): Check Check PIC instead of

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27 11:09         ` Szabolcs Nagy
@ 2017-09-27 21:16           ` H.J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2017-09-27 21:16 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Florian Weimer, Joseph Myers, nd, GNU C Library

On 9/27/17, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
> On 27/09/17 11:55, Florian Weimer wrote:
>> On 09/27/2017 10:30 AM, H.J. Lu wrote:
>>>> would an architecture need or not need architecture-specific configure
>>>> changes, etc.), and have you tried a build-many-glibcs.py run with this
>>>> option passed to all the builds to see how other architectures do?  Why
>>
>>> build-many-glibcs.py has no regressions.
>>
>> On which tree?  I think commit 6cd380dd366d728da9f579eeb9f7f4c47f48e474
>> added absolute relocations to the
>> startup code, which I expect will not work for static PIE.
>>
>
> i'd expect the Scrt1.o to be used for PIE which have no ABS relocs
> however it can have RELATIVE relocs if GOT entries are used i think
> (even on x86_64).

x86--64 and i686 are OK.  You may need to update your start.S to avoid
dynamic relocations in static PIE.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27 12:41       ` Joseph Myers
@ 2017-09-27 21:28         ` H.J. Lu
  2017-09-28  0:49           ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-09-27 21:28 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

On 9/27/17, Joseph Myers <joseph@codesourcery.com> wrote:
> On Wed, 27 Sep 2017, H.J. Lu wrote:
>
>> > would an architecture need or not need architecture-specific configure
>> > changes, etc.), and have you tried a build-many-glibcs.py run with this
>> > option passed to all the builds to see how other architectures do?  Why
>>
>> build-many-glibcs.py has no regressions.  But I didn't try
>> --enable-static-pie
>> with build-many-glibcs.py.  I encourage target maintainers to give
>> hjl/pie/static
>> branch a try.
>
> I think the most useful test for this purpose (of assessing architecture
> support) is adding --enable-static-pie alongside --enable-profile in
> build-many-glibcs.py and seeing how the build goes.

I will do that.

>> No separate PIE copy of libc.a, is used for static PIE to minimize
>> GCC driver change.  To improve system security, glibc can be built with
>
> The question should be what's best for the GNU system and the GNU
> toolchain as a whole, rather than minimizing the GCC driver changes.

PIE libc.a can be used to create both static executable and static PIE.
Also CCC from some OSVs are now default to PIE.  There libc.a is built
with PIE today.  We are discourage static executables.  I don't see the
need for a separate PIE copy of libc.a.  That is OSV has a choice to
either have PIE libc.a or non-PIE libc.a.  I am expecting PIE libc.a
is provided by more OSVs.

>> > The patch is missing documentation in install.texi of the new configure
>> > option and associated regeneration of INSTALL.
>>
>> Done.  I also updated NEWS.
>
> To me, both the install.texi and NEWS changes read as saying that programs
> such as ldconfig are built as PIEs.  That's a separate matter from

All static executables, including tests,  within glibc are built as
static PIE when
 --enable-static-pie is used.  That is how I noticed that
--eh-frame-hdr is needed
for static PIE.

> supporting user programs built as static PIEs.  I'd have thought the main
> point of this feature, which is the one that NEWS and install.texi should
> emphasize, is the support for user programs built as static PIEs.
>


-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27 21:28         ` H.J. Lu
@ 2017-09-28  0:49           ` Joseph Myers
  2017-09-28  2:21             ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-09-28  0:49 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library

On Wed, 27 Sep 2017, H.J. Lu wrote:

> > I think the most useful test for this purpose (of assessing architecture
> > support) is adding --enable-static-pie alongside --enable-profile in
> > build-many-glibcs.py and seeing how the build goes.
> 
> I will do that.

Thanks.  To be clear, I don't think such a build-many-glibcs.py change 
would be appropriate for mainline (given a version of --enable-static-pie 
that changes how libc.a is built rather than enabling building additional 
static-PIE libraries) - although adding one or two additional static-PIE 
configurations to build-many-glibcs.py might be - but for testing purposes 
it's very useful to understand how widely this option works (or at least 
builds) for other architectures.

> > To me, both the install.texi and NEWS changes read as saying that programs
> > such as ldconfig are built as PIEs.  That's a separate matter from
> 
> All static executables, including tests,  within glibc are built as
> static PIE when
>  --enable-static-pie is used.  That is how I noticed that
> --eh-frame-hdr is needed
> for static PIE.

My point is that NEWS and the install.texi text are for users of glibc, 
and I think it's more significant for users that they can build *their 
own* programs as static PIEs, than that ldconfig and sln are static PIEs.  
So the NEWS and install.texi text should talk about the effects of the 
option on what users can do with the resulting glibc.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-28  0:49           ` Joseph Myers
@ 2017-09-28  2:21             ` H.J. Lu
  2017-09-28 13:03               ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-09-28  2:21 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 2586 bytes --]

On 9/27/17, Joseph Myers <joseph@codesourcery.com> wrote:
> On Wed, 27 Sep 2017, H.J. Lu wrote:
>
>> > I think the most useful test for this purpose (of assessing
>> > architecture
>> > support) is adding --enable-static-pie alongside --enable-profile in
>> > build-many-glibcs.py and seeing how the build goes.
>>
>> I will do that.
>
> Thanks.  To be clear, I don't think such a build-many-glibcs.py change
> would be appropriate for mainline (given a version of --enable-static-pie
> that changes how libc.a is built rather than enabling building additional

I used this:

commit b4be70c3844abd4612973cb2556887aa6de89321 (HEAD -> hjl/pie/static)
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Sep 27 16:47:29 2017 -0700

    Add --enable-static-pie to build-many-glibcs.py

diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py
index 8ce1c6f7f9..013c96d194 100755
--- a/scripts/build-many-glibcs.py
+++ b/scripts/build-many-glibcs.py
@@ -1343,6 +1343,7 @@ class Glibc(object):
         cfg_cmd = [os.path.join(srcdir_copy, 'configure'),
                    '--prefix=/usr',
                    '--enable-add-ons',
+                   '--enable-static-pie',
                    '--enable-profile',
                    '--build=%s' % self.ctx.build_triplet,
                    '--host=%s' % self.triplet,

for testing.

> static-PIE libraries) - although adding one or two additional static-PIE
> configurations to build-many-glibcs.py might be - but for testing purposes
> it's very useful to understand how widely this option works (or at least
> builds) for other architectures.

Many architectures failed to build static PIE due to asm statements in
elf_machine_dynamic and elf_machine_load_address.   I didn't check
start.S which will fail at run-time if there are any dynamic relocations.

>> > To me, both the install.texi and NEWS changes read as saying that
>> > programs
>> > such as ldconfig are built as PIEs.  That's a separate matter from
>>
>> All static executables, including tests,  within glibc are built as
>> static PIE when
>>  --enable-static-pie is used.  That is how I noticed that
>> --eh-frame-hdr is needed
>> for static PIE.
>
> My point is that NEWS and the install.texi text are for users of glibc,
> and I think it's more significant for users that they can build *their
> own* programs as static PIEs, than that ldconfig and sln are static PIEs.
> So the NEWS and install.texi text should talk about the effects of the
> option on what users can do with the resulting glibc.

Done.

Here is the updated patch.

Thanks.

-- 
H.J.

[-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --]
[-- Type: text/x-patch, Size: 23907 bytes --]

From 89cd185bfd43f5c24de59aee985bc4c66077bed4 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

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.

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

1. 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, like

commit 1e8e527dd9718eaebe8417b73befb0c821b7b327
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Aug 4 12:59:35 2017 -0700

    i386: Support static PIE in start.S

    Since start.o may be compiled as PIC, we should check PIC instead of
    SHARED.  Also avoid dynamic relocation against main in static PIE since
    _start is the entry point before the executable is relocated.

2. elf_machine_dynamic and elf_machine_load_address in dl-machine.h are
updated to support static PIE, similar to x86_64 dl-machine.h:

/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
   first element of the GOT.  This must be inlined in a function which
   uses global data.  */
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_dynamic (void)
{
  /* This produces an IP-relative reloc which is resolved at link time. */
  extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
  return _GLOBAL_OFFSET_TABLE_[0];
}

/* Return the run-time load address of the shared object.  */
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_load_address (void)
{
  /* Compute the difference between the runtime address of _DYNAMIC as seen
     by an IP-relative reference, and the link-time address found in the
     special unrelocated first GOT entry.  */
  extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
  return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
}

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.

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

Binutils 2.29 or above are OK.

Tested on i686 and x86-64.

	* INSTALL: Regenerated.
	* Makeconfig (pic-default): Updated for --enable-static-pie.
	(pie-default): New for --enable-static-pie.
	(default-pie-ldflag): Likewise.
	(+link-static-before-libc): Add $(default-pie-ldflag).
	(+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/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.
	* elf/dl-support.c: Include "dynamic-link.h" and don't include
	"get-dynamic-info.h" for --enable-static-pie.
	(_dl_relocate_static_pie): New function for --enable-static-pie.
	(STATIC_PIE_BOOTSTRAP): New for --enable-static-pie.
	(RESOLVE_MAP): Likewise.
	* elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
	STATIC_PIE_BOOTSTRAP.
	* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
	* manual/install.texi: Document --enable-static-pie.
	* sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
	* sysdeps/x86_64/configure.ac: Check if linker supports static PIE.
	* sysdeps/x86_64/configure: Regenerated.
---
 INSTALL                     |  7 ++++
 Makeconfig                  | 20 ++++++++++--
 NEWS                        |  5 +++
 config.h.in                 |  3 ++
 configure                   | 78 +++++++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 29 +++++++++++++++++
 csu/libc-start.c            |  2 ++
 csu/libc-tls.c              |  6 ++--
 elf/dl-support.c            | 39 +++++++++++++++++++++--
 elf/dynamic-link.h          |  2 +-
 elf/get-dynamic-info.h      |  6 ++--
 manual/install.texi         |  7 ++++
 sysdeps/generic/ldsodefs.h  |  7 ++++
 sysdeps/x86_64/configure    | 33 +++++++++++++++++++
 sysdeps/x86_64/configure.ac | 25 +++++++++++++++
 15 files changed, 259 insertions(+), 10 deletions(-)

diff --git a/INSTALL b/INSTALL
index 4d9024c667..862544f144 100644
--- a/INSTALL
+++ b/INSTALL
@@ -106,6 +106,13 @@ 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'
+     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.
+
 '--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 b51904b797..b45209fe5f 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -386,6 +386,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
 LDFLAGS-rtld += $(hashstyle-LDFLAGS)
 endif
 
+ifeq (yes,$(enable-static-pie))
+pic-default = -DPIC
+pie-default = $(pie-ccflag)
+ifeq (yes,$(have-static-pie))
+default-pie-ldflag = -static-pie
+else
+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.
@@ -435,6 +445,7 @@ endif
 # Command for statically linking programs with the C library.
 ifndef +link-static
 +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
+	      $(default-pie-ldflag) \
 	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
 	      $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
 	      $(+preinit) $(+prectorT) \
@@ -651,8 +662,13 @@ 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))
++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/
 
@@ -973,7 +989,7 @@ 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))
+CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
 libtype.o := lib%.a
 object-suffixes += .o
 ifeq (yes,$(build-shared))
@@ -998,7 +1014,7 @@ ifeq (yes,$(build-profile))
 all-object-suffixes += .op
 object-suffixes += .op
 CPPFLAGS-.op = -DPROF $(pic-default)
-CFLAGS-.op = -pg
+CFLAGS-.op = -pg $(pie-default)
 libtype.op = lib%_p.a
 endif
 
diff --git a/NEWS b/NEWS
index e346d2afe6..681ba8ce89 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).
+
 * 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 014fb4ea0e..26ed7865ef 100644
--- a/config.h.in
+++ b/config.h.in
@@ -236,6 +236,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 067d92d2ba..cd5cf5729f 100755
--- a/configure
+++ b/configure
@@ -767,6 +767,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
@@ -1424,6 +1425,7 @@ 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     build static executables as PIE [default=no]
   --disable-timezone-tools
                           do not install timezone tools [default=install]
   --enable-hardcoded-path-in-tests
@@ -3372,6 +3374,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
@@ -5994,6 +6003,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 :
@@ -6888,6 +6953,19 @@ fi
 $as_echo "$libc_cv_pie_default" >&6; }
 
 
+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 d412104d8c..09e1c7f23b 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@:>@]),
+	      [static_pie=$enableval],
+	      [static_pie=no])
 AC_ARG_ENABLE([timezone-tools],
 	      AC_HELP_STRING([--disable-timezone-tools],
 			     [do not install timezone tools @<:@default=install@:>@]),
@@ -1460,6 +1465,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])
 ])
@@ -1962,6 +1980,17 @@ fi
 rm -f conftest.*])
 AC_SUBST(libc_cv_pie_default)
 
+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/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/elf/dl-support.c b/elf/dl-support.c
index 5e3de90598..4e1e37072b 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -26,7 +26,11 @@
 #include <sys/param.h>
 #include <stdint.h>
 #include <ldsodefs.h>
-#include <dl-machine.h>
+#if ENABLE_STATIC_PIE
+# include "dynamic-link.h"
+#else
+# include <dl-machine.h>
+#endif
 #include <libc-lock.h>
 #include <dl-cache.h>
 #include <dl-librecon.h>
@@ -199,7 +203,9 @@ const ElfW(Ehdr) *_dl_sysinfo_dso;
 
 struct link_map *_dl_sysinfo_map;
 
-# include "get-dynamic-info.h"
+# if !ENABLE_STATIC_PIE
+#  include "get-dynamic-info.h"
+# endif
 #endif
 #include "setup-vdso.h"
 
@@ -302,6 +308,35 @@ _dl_aux_init (ElfW(auxv_t) *av)
 }
 #endif
 
+#if ENABLE_STATIC_PIE
+/* Relocate static executable with PIE.  */
+
+void
+_dl_relocate_static_pie (void)
+{
+# define STATIC_PIE_BOOTSTRAP
+# define RESOLVE_MAP(sym, version, flags) (&_dl_main_map)
+# include "dynamic-link.h"
+
+  /* Figure out the run-time load addres of static PIE.  */
+  _dl_main_map.l_addr = elf_machine_load_address ();
+
+  /* Read our own dynamic section and fill in the info array.  */
+  _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr
+		       + elf_machine_dynamic ());
+  elf_get_dynamic_info (&_dl_main_map, NULL);
+
+# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+  ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0);
+  _dl_main_map.l_relocated = 1;
+}
+#endif
+
 
 void
 _dl_non_dynamic_init (void)
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/manual/install.texi b/manual/install.texi
index 35948b1bbb..2a2a430550 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -136,6 +136,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
+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.
+
 @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 1a4449eeb3..b4c032a06c 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1048,6 +1048,13 @@ 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.  */
+void _dl_relocate_static_pie (void) attribute_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/x86_64/configure b/sysdeps/x86_64/configure
index efef46b1b7..8ee15b8a25 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 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..53e4a8277c 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 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.13.5


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-27  8:30     ` H.J. Lu
                         ` (2 preceding siblings ...)
  2017-09-27 12:41       ` Joseph Myers
@ 2017-09-28  9:37       ` Markus Trippelsdorf
  2017-09-28 12:26         ` H.J. Lu
  3 siblings, 1 reply; 28+ messages in thread
From: Markus Trippelsdorf @ 2017-09-28  9:37 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Joseph Myers, GNU C Library

On 2017.09.27 at 01:30 -0700, H.J. Lu wrote:
> No separate PIE copy of libc.a, is used for static PIE to minimize
> GCC driver change.  To improve system security, glibc can be built with
> --enable-static-pie, and the same libc.a can be used to build both static
> executable and static PIE.

It doesn't work:

 ~ % echo "int main(){}" | gcc -x c - -static
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o): In function `elf_machine_load_address':
/home/markus/glibc/elf/../sysdeps/x86_64/dl-machine.h:59: undefined reference to `_DYNAMIC'
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o): In function `elf_get_dynamic_info':
/home/markus/glibc/elf/get-dynamic-info.h:48: undefined reference to `_DYNAMIC'
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: a.out: hidden symbol `_DYNAMIC' isn't defined
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

-- 
Markus

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-28  9:37       ` Markus Trippelsdorf
@ 2017-09-28 12:26         ` H.J. Lu
  2017-09-28 13:25           ` Markus Trippelsdorf
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-09-28 12:26 UTC (permalink / raw)
  To: Markus Trippelsdorf; +Cc: Joseph Myers, GNU C Library

[-- Attachment #1: Type: text/plain, Size: 1267 bytes --]

On 9/28/17, Markus Trippelsdorf <markus@trippelsdorf.de> wrote:
> On 2017.09.27 at 01:30 -0700, H.J. Lu wrote:
>> No separate PIE copy of libc.a, is used for static PIE to minimize
>> GCC driver change.  To improve system security, glibc can be built with
>> --enable-static-pie, and the same libc.a can be used to build both static
>> executable and static PIE.
>
> It doesn't work:
>
>  ~ % echo "int main(){}" | gcc -x c - -static
> /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o):
> In function `elf_machine_load_address':
> /home/markus/glibc/elf/../sysdeps/x86_64/dl-machine.h:59: undefined
> reference to `_DYNAMIC'
> /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o):
> In function `elf_get_dynamic_info':
> /home/markus/glibc/elf/get-dynamic-info.h:48: undefined reference to
> `_DYNAMIC'
> /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld:
> a.out: hidden symbol `_DYNAMIC' isn't defined
> /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld:
> final link failed: Bad value
> collect2: error: ld returned 1 exit status
>

Thanks for your test.   Fixed on hjl/pie/static branch.  I am
enclosing the updated
--enable-static-pie patch.


-- 
H.J.

[-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --]
[-- Type: text/x-patch, Size: 24392 bytes --]

From f09a1df2e8d57577daaf8b8cce10da007de26597 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

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.

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

1. 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, like

commit 1e8e527dd9718eaebe8417b73befb0c821b7b327
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Aug 4 12:59:35 2017 -0700

    i386: Support static PIE in start.S

    Since start.o may be compiled as PIC, we should check PIC instead of
    SHARED.  Also avoid dynamic relocation against main in static PIE since
    _start is the entry point before the executable is relocated.

2. elf_machine_dynamic and elf_machine_load_address in dl-machine.h are
updated to support static PIE, similar to x86_64 dl-machine.h:

/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
   first element of the GOT.  This must be inlined in a function which
   uses global data.  */
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_dynamic (void)
{
  /* This produces an IP-relative reloc which is resolved at link time. */
  extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
  return _GLOBAL_OFFSET_TABLE_[0];
}

/* Return the run-time load address of the shared object.  */
static inline ElfW(Addr) __attribute__ ((unused))
elf_machine_load_address (void)
{
  /* Compute the difference between the runtime address of _DYNAMIC as seen
     by an IP-relative reference, and the link-time address found in the
     special unrelocated first GOT entry.  */
 #ifdef SHARED
  extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
  return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
 #else
  extern ElfW(Dyn) _DYNAMIC[] __attribute__((weak, visibility ("hidden")));
  if (_DYNAMIC)
    {
      /* The address of dynamic must be taken as non-weak to avoid
         dynamic relocation.  */
      extern ElfW(Dyn) dynamic[] asm ("_DYNAMIC") attribute_hidden;
      return (ElfW(Addr)) &dynamic - elf_machine_dynamic ();
    }
  else
    return 0;
 #endif
}

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.

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

Binutils 2.29 or above are OK.

Tested on i686 and x86-64.

	* INSTALL: Regenerated.
	* Makeconfig (pic-default): Updated for --enable-static-pie.
	(pie-default): New for --enable-static-pie.
	(default-pie-ldflag): Likewise.
	(+link-static-before-libc): Add $(default-pie-ldflag).
	(+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/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.
	* elf/dl-support.c: Include "dynamic-link.h" and don't include
	"get-dynamic-info.h" for --enable-static-pie.
	(_dl_relocate_static_pie): New function for --enable-static-pie.
	(STATIC_PIE_BOOTSTRAP): New for --enable-static-pie.
	(RESOLVE_MAP): Likewise.
	* elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
	STATIC_PIE_BOOTSTRAP.
	* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
	* manual/install.texi: Document --enable-static-pie.
	* sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
	* sysdeps/x86_64/configure.ac: Check if linker supports static PIE.
	* sysdeps/x86_64/configure: Regenerated.
---
 INSTALL                     |  7 ++++
 Makeconfig                  | 20 ++++++++++--
 NEWS                        |  5 +++
 config.h.in                 |  3 ++
 configure                   | 78 +++++++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 29 +++++++++++++++++
 csu/libc-start.c            |  2 ++
 csu/libc-tls.c              |  6 ++--
 elf/dl-support.c            | 43 +++++++++++++++++++++++--
 elf/dynamic-link.h          |  2 +-
 elf/get-dynamic-info.h      |  6 ++--
 manual/install.texi         |  7 ++++
 sysdeps/generic/ldsodefs.h  |  7 ++++
 sysdeps/x86_64/configure    | 33 +++++++++++++++++++
 sysdeps/x86_64/configure.ac | 25 +++++++++++++++
 15 files changed, 263 insertions(+), 10 deletions(-)

diff --git a/INSTALL b/INSTALL
index 4d9024c667..862544f144 100644
--- a/INSTALL
+++ b/INSTALL
@@ -106,6 +106,13 @@ 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'
+     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.
+
 '--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 b51904b797..b45209fe5f 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -386,6 +386,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
 LDFLAGS-rtld += $(hashstyle-LDFLAGS)
 endif
 
+ifeq (yes,$(enable-static-pie))
+pic-default = -DPIC
+pie-default = $(pie-ccflag)
+ifeq (yes,$(have-static-pie))
+default-pie-ldflag = -static-pie
+else
+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.
@@ -435,6 +445,7 @@ endif
 # Command for statically linking programs with the C library.
 ifndef +link-static
 +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
+	      $(default-pie-ldflag) \
 	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
 	      $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
 	      $(+preinit) $(+prectorT) \
@@ -651,8 +662,13 @@ 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))
++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/
 
@@ -973,7 +989,7 @@ 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))
+CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
 libtype.o := lib%.a
 object-suffixes += .o
 ifeq (yes,$(build-shared))
@@ -998,7 +1014,7 @@ ifeq (yes,$(build-profile))
 all-object-suffixes += .op
 object-suffixes += .op
 CPPFLAGS-.op = -DPROF $(pic-default)
-CFLAGS-.op = -pg
+CFLAGS-.op = -pg $(pie-default)
 libtype.op = lib%_p.a
 endif
 
diff --git a/NEWS b/NEWS
index e346d2afe6..681ba8ce89 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).
+
 * 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 014fb4ea0e..26ed7865ef 100644
--- a/config.h.in
+++ b/config.h.in
@@ -236,6 +236,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 067d92d2ba..cd5cf5729f 100755
--- a/configure
+++ b/configure
@@ -767,6 +767,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
@@ -1424,6 +1425,7 @@ 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     build static executables as PIE [default=no]
   --disable-timezone-tools
                           do not install timezone tools [default=install]
   --enable-hardcoded-path-in-tests
@@ -3372,6 +3374,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
@@ -5994,6 +6003,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 :
@@ -6888,6 +6953,19 @@ fi
 $as_echo "$libc_cv_pie_default" >&6; }
 
 
+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 d412104d8c..09e1c7f23b 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@:>@]),
+	      [static_pie=$enableval],
+	      [static_pie=no])
 AC_ARG_ENABLE([timezone-tools],
 	      AC_HELP_STRING([--disable-timezone-tools],
 			     [do not install timezone tools @<:@default=install@:>@]),
@@ -1460,6 +1465,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])
 ])
@@ -1962,6 +1980,17 @@ fi
 rm -f conftest.*])
 AC_SUBST(libc_cv_pie_default)
 
+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/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/elf/dl-support.c b/elf/dl-support.c
index 5e3de90598..dc994629e7 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -26,7 +26,11 @@
 #include <sys/param.h>
 #include <stdint.h>
 #include <ldsodefs.h>
-#include <dl-machine.h>
+#if ENABLE_STATIC_PIE
+# include "dynamic-link.h"
+#else
+# include <dl-machine.h>
+#endif
 #include <libc-lock.h>
 #include <dl-cache.h>
 #include <dl-librecon.h>
@@ -199,7 +203,9 @@ const ElfW(Ehdr) *_dl_sysinfo_dso;
 
 struct link_map *_dl_sysinfo_map;
 
-# include "get-dynamic-info.h"
+# if !ENABLE_STATIC_PIE
+#  include "get-dynamic-info.h"
+# endif
 #endif
 #include "setup-vdso.h"
 
@@ -302,6 +308,39 @@ _dl_aux_init (ElfW(auxv_t) *av)
 }
 #endif
 
+#if ENABLE_STATIC_PIE
+/* Relocate static executable with PIE.  */
+
+void
+_dl_relocate_static_pie (void)
+{
+# define STATIC_PIE_BOOTSTRAP
+# define RESOLVE_MAP(sym, version, flags) (&_dl_main_map)
+# include "dynamic-link.h"
+
+  /* Figure out the run-time load addres of static PIE.  */
+  _dl_main_map.l_addr = elf_machine_load_address ();
+
+  /* Skip if this is a non-PIE static executable.  */
+  if (!_dl_main_map.l_addr)
+    return;
+
+  /* Read our own dynamic section and fill in the info array.  */
+  _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr
+		       + elf_machine_dynamic ());
+  elf_get_dynamic_info (&_dl_main_map, NULL);
+
+# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+  ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0);
+  _dl_main_map.l_relocated = 1;
+}
+#endif
+
 
 void
 _dl_non_dynamic_init (void)
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/manual/install.texi b/manual/install.texi
index 35948b1bbb..2a2a430550 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -136,6 +136,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
+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.
+
 @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 1a4449eeb3..b4c032a06c 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1048,6 +1048,13 @@ 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.  */
+void _dl_relocate_static_pie (void) attribute_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/x86_64/configure b/sysdeps/x86_64/configure
index efef46b1b7..8ee15b8a25 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 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..53e4a8277c 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 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.13.5


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-28  2:21             ` H.J. Lu
@ 2017-09-28 13:03               ` Joseph Myers
  2017-09-29 21:49                 ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-09-28 13:03 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library

On Wed, 27 Sep 2017, H.J. Lu wrote:

> > static-PIE libraries) - although adding one or two additional static-PIE
> > configurations to build-many-glibcs.py might be - but for testing purposes
> > it's very useful to understand how widely this option works (or at least
> > builds) for other architectures.
> 
> Many architectures failed to build static PIE due to asm statements in
> elf_machine_dynamic and elf_machine_load_address.   I didn't check
> start.S which will fail at run-time if there are any dynamic relocations.

In that case: (a) the install.texi / NEWS entries need to make clear the 
limited nature of architecture support for this feature; (b) if the 
feature achieves consensus to go in mainline at all, 
<https://sourceware.org/glibc/wiki/PortStatus> will need updating with a 
list of all the architectures lacking support and detailed information for 
architecture maintainers regarding how to make the feature work on their 
architectures and how to tell whether it is working.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-28 12:26         ` H.J. Lu
@ 2017-09-28 13:25           ` Markus Trippelsdorf
  0 siblings, 0 replies; 28+ messages in thread
From: Markus Trippelsdorf @ 2017-09-28 13:25 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Joseph Myers, GNU C Library

On 2017.09.28 at 05:26 -0700, H.J. Lu wrote:
> On 9/28/17, Markus Trippelsdorf <markus@trippelsdorf.de> wrote:
> > On 2017.09.27 at 01:30 -0700, H.J. Lu wrote:
> >> No separate PIE copy of libc.a, is used for static PIE to minimize
> >> GCC driver change.  To improve system security, glibc can be built with
> >> --enable-static-pie, and the same libc.a can be used to build both static
> >> executable and static PIE.
> >
> > It doesn't work:
> >
> >  ~ % echo "int main(){}" | gcc -x c - -static
> > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o):
> > In function `elf_machine_load_address':
> > /home/markus/glibc/elf/../sysdeps/x86_64/dl-machine.h:59: undefined
> > reference to `_DYNAMIC'
> > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../lib64/libc.a(dl-support.o):
> > In function `elf_get_dynamic_info':
> > /home/markus/glibc/elf/get-dynamic-info.h:48: undefined reference to
> > `_DYNAMIC'
> > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld:
> > a.out: hidden symbol `_DYNAMIC' isn't defined
> > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/../../../../x86_64-pc-linux-gnu/bin/ld:
> > final link failed: Bad value
> > collect2: error: ld returned 1 exit status
> >
>
> Thanks for your test.   Fixed on hjl/pie/static branch.

Thanks. It now works fine. 

This has nothing to do with your patch, however valgrind reports (also for
-static-pie):

 ~ % echo "int main(){}" | gcc -x c - -static
 ~ % valgrind ./a.out
==15601== Memcheck, a memory error detector
==15601== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15601== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==15601== Command: ./a.out
==15601== 
==15601== Conditional jump or move depends on uninitialised value(s)
==15601==    at 0x422849: __libc_malloc (malloc.c:3032)
==15601==    by 0x422849: malloc_hook_ini (hooks.c:32)
==15601==    by 0x465CD1: _dl_get_origin (dl-origin.c:50)
==15601==    by 0x432FCE: _dl_non_dynamic_init (dl-support.c:348)
==15601==    by 0x434760: __libc_init_first (init-first.c:74)
==15601==    by 0x4044DE: (below main) (libc-start.c:244)
==15601== 
==15601== Conditional jump or move depends on uninitialised value(s)
==15601==    at 0x422941: tcache_init (malloc.c:2981)
==15601==    by 0x422941: __libc_malloc (malloc.c:3032)
==15601==    by 0x422941: malloc_hook_ini (hooks.c:32)
==15601==    by 0x465CD1: _dl_get_origin (dl-origin.c:50)
==15601==    by 0x432FCE: _dl_non_dynamic_init (dl-support.c:348)
==15601==    by 0x434760: __libc_init_first (init-first.c:74)
==15601==    by 0x4044DE: (below main) (libc-start.c:244)
==15601== 
==15601== Conditional jump or move depends on uninitialised value(s)
==15601==    at 0x421BC8: _int_malloc (malloc.c:3673)
==15601==    by 0x421BC8: tcache_init.part.9 (malloc.c:2985)
==15601==    by 0x42294B: tcache_init (malloc.c:2981)
==15601==    by 0x42294B: __libc_malloc (malloc.c:3032)
==15601==    by 0x42294B: malloc_hook_ini (hooks.c:32)
==15601==    by 0x465CD1: _dl_get_origin (dl-origin.c:50)
==15601==    by 0x432FCE: _dl_non_dynamic_init (dl-support.c:348)
==15601==    by 0x434760: __libc_init_first (init-first.c:74)
==15601==    by 0x4044DE: (below main) (libc-start.c:244)

-- 
Markus

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-28 13:03               ` Joseph Myers
@ 2017-09-29 21:49                 ` H.J. Lu
  2017-10-05 13:12                   ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-09-29 21:49 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 5987 bytes --]

On 9/28/17, Joseph Myers <joseph@codesourcery.com> wrote:
> On Wed, 27 Sep 2017, H.J. Lu wrote:
>
>> > static-PIE libraries) - although adding one or two additional
>> > static-PIE
>> > configurations to build-many-glibcs.py might be - but for testing
>> > purposes
>> > it's very useful to understand how widely this option works (or at
>> > least
>> > builds) for other architectures.
>>
>> Many architectures failed to build static PIE due to asm statements in
>> elf_machine_dynamic and elf_machine_load_address.   I didn't check
>> start.S which will fail at run-time if there are any dynamic relocations.
>
> In that case: (a) the install.texi / NEWS entries need to make clear the
> limited nature of architecture support for this feature; (b) if the
> feature achieves consensus to go in mainline at all,
> <https://sourceware.org/glibc/wiki/PortStatus> will need updating with a
> list of all the architectures lacking support and detailed information for
> architecture maintainers regarding how to make the feature work on their
> architectures and how to tell whether it is working.
>

I submitted patches for other targets to address obvious issues with static
PIE.  Build results of build-many-glibcs.py with --enable-static-pie with all
patches for static PIE applied are

PASS: glibcs-aarch64_be-linux-gnu build
PASS: glibcs-aarch64-linux-gnu build
PASS: glibcs-armeb-linux-gnueabi build
PASS: glibcs-armeb-linux-gnueabi-be8 build
PASS: glibcs-armeb-linux-gnueabihf build
PASS: glibcs-armeb-linux-gnueabihf-be8 build
PASS: glibcs-arm-linux-gnueabi build
PASS: glibcs-arm-linux-gnueabihf build
PASS: glibcs-hppa-linux-gnu build
PASS: glibcs-i486-linux-gnu build
PASS: glibcs-i586-linux-gnu build
PASS: glibcs-i686-linux-gnu build
PASS: glibcs-i686-linux-gnu-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-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-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-nios2-linux-gnu build
PASS: glibcs-powerpc64le-linux-gnu build
PASS: glibcs-powerpc64-linux-gnu build
PASS: glibcs-s390x-linux-gnu build
PASS: glibcs-x86_64-linux-gnu build
PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build
PASS: glibcs-x86_64-linux-gnu-x32 build

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-ia64-linux-gnu build

elf/sln is failed to link due to:

libc.a(sched_yield.o): non-pic code with imm relocation against
dynamic symbol `_dl_sysinfo'

This is caused by non-PICi version of DO_CALL macro in ia64 sysdep.h.  PIE
libc.a should use PIC version of DO_CALL, except during startup in static
PIE.  An ia64 startup.h, similar to i386 startup.h, is needed to handle
this.

FAIL: glibcs-mips64el-linux-gnu-n32 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64el-linux-gnu-n32-soft build
FAIL: glibcs-mips64-linux-gnu-n32 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64-linux-gnu-n32-soft build
FAIL: glibcs-mipsel-linux-gnu build
FAIL: glibcs-mipsel-linux-gnu-nan2008 build
FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build
FAIL: glibcs-mipsel-linux-gnu-soft build
FAIL: glibcs-mips-linux-gnu build
FAIL: glibcs-mips-linux-gnu-nan2008 build
FAIL: glibcs-mips-linux-gnu-nan2008-soft build
FAIL: glibcs-mips-linux-gnu-soft build

elf/sln is failed to link due to:

crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when
making a shared object; recompile with -fPIC

This is caused by linker bug and/or non-PIC code in crt1.o.

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.

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:14242

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.

FAIL: glibcs-sparc64-linux-gnu build
FAIL: glibcs-sparcv9-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.

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.

Here is the updated patch to state that i686, x86-64 and x32 targets
are verified to work.  I encourage target maintainers to try hjl/pie/static
branch to verify if static PIE works for your targets.

Thanks.

-- 
H.J.

[-- Attachment #2: 0003-Add-enable-static-pie-configure-option-to-build-stat.patch --]
[-- Type: text/x-patch, Size: 28031 bytes --]

From 6a63037b178d88e07dccc371ab6611395e173b9a 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

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.

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

1. 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, arm, hppa,
m68k, microblaze and sparc.
2. All assembly codes are updated check PIC instead SHARED for PIC code
path to avoid dynamic relocations in read-only sections.
3. All assembly codes are updated check SHARED instead PIC for static
symbol name.  A patch is submitted for tile.
4. elf_machine_load_address in dl-machine.h are updated to support static
PIE.  Patches are submitted for aarch64, arm, hppa, ia64, m68k, microblaze,
mips, nios2, powerpc, s390, sh, sparc and tile.

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.

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

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

Tested on i686 and x86-64.

Build results of build-many-glibcs.py with --enable-static-pie with all
patches for static PIE applied are

PASS: glibcs-aarch64_be-linux-gnu build
PASS: glibcs-aarch64-linux-gnu build
PASS: glibcs-armeb-linux-gnueabi build
PASS: glibcs-armeb-linux-gnueabi-be8 build
PASS: glibcs-armeb-linux-gnueabihf build
PASS: glibcs-armeb-linux-gnueabihf-be8 build
PASS: glibcs-arm-linux-gnueabi build
PASS: glibcs-arm-linux-gnueabihf build
PASS: glibcs-hppa-linux-gnu build
PASS: glibcs-i486-linux-gnu build
PASS: glibcs-i586-linux-gnu build
PASS: glibcs-i686-linux-gnu build
PASS: glibcs-i686-linux-gnu-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-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-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-nios2-linux-gnu build
PASS: glibcs-powerpc64le-linux-gnu build
PASS: glibcs-powerpc64-linux-gnu build
PASS: glibcs-s390x-linux-gnu build
PASS: glibcs-x86_64-linux-gnu build
PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build
PASS: glibcs-x86_64-linux-gnu-x32 build

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-ia64-linux-gnu build

elf/sln is failed to link due to:

libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo'

This is caused by non-PICi version of DO_CALL macro in ia64 sysdep.h.  PIE
libc.a should use PIC version of DO_CALL, except during startup in static
PIE.  An ia64 startup.h, similar to i386 startup.h, is needed to handle
this.

FAIL: glibcs-mips64el-linux-gnu-n32 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64el-linux-gnu-n32-soft build
FAIL: glibcs-mips64-linux-gnu-n32 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64-linux-gnu-n32-soft build
FAIL: glibcs-mipsel-linux-gnu build
FAIL: glibcs-mipsel-linux-gnu-nan2008 build
FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build
FAIL: glibcs-mipsel-linux-gnu-soft build
FAIL: glibcs-mips-linux-gnu build
FAIL: glibcs-mips-linux-gnu-nan2008 build
FAIL: glibcs-mips-linux-gnu-nan2008-soft build
FAIL: glibcs-mips-linux-gnu-soft build

elf/sln is failed to link due to:

crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC

This is caused by linker bug and/or non-PIC code in crt1.o.

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.

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:14242

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.

FAIL: glibcs-sparc64-linux-gnu build
FAIL: glibcs-sparcv9-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.

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.

	* INSTALL: Regenerated.
	* Makeconfig (pic-default): Updated for --enable-static-pie.
	(pie-default): New for --enable-static-pie.
	(default-pie-ldflag): Likewise.
	(+link-static-before-libc): Add $(default-pie-ldflag).
	(+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/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.
	* elf/dl-support.c: Include "dynamic-link.h" and don't include
	"get-dynamic-info.h" for --enable-static-pie.
	(_dl_relocate_static_pie): New function for --enable-static-pie.
	(STATIC_PIE_BOOTSTRAP): New for --enable-static-pie.
	(BOOTSTRAP_MAP): Likewise.
	(RESOLVE_MAP): Likewise.
	* elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
	STATIC_PIE_BOOTSTRAP.
	* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
	* manual/install.texi: Document --enable-static-pie.
	* sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
	* sysdeps/x86_64/configure.ac: Check if linker supports static PIE.
	* sysdeps/x86_64/configure: Regenerated.
---
 INSTALL                     |  8 +++++
 Makeconfig                  | 20 ++++++++++--
 NEWS                        |  6 ++++
 config.h.in                 |  3 ++
 configure                   | 78 +++++++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 29 +++++++++++++++++
 csu/libc-start.c            |  2 ++
 csu/libc-tls.c              |  6 ++--
 elf/dl-support.c            | 44 +++++++++++++++++++++++--
 elf/dynamic-link.h          |  2 +-
 elf/get-dynamic-info.h      |  6 ++--
 manual/install.texi         |  8 +++++
 sysdeps/generic/ldsodefs.h  |  7 ++++
 sysdeps/x86_64/configure    | 33 +++++++++++++++++++
 sysdeps/x86_64/configure.ac | 25 +++++++++++++++
 15 files changed, 267 insertions(+), 10 deletions(-)

diff --git a/INSTALL b/INSTALL
index 4d9024c667..55361a0fd3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -106,6 +106,14 @@ 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'
+     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. Only
+     i686, x86-64 and x32 targets are verified to work.
+
 '--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 b51904b797..b45209fe5f 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -386,6 +386,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
 LDFLAGS-rtld += $(hashstyle-LDFLAGS)
 endif
 
+ifeq (yes,$(enable-static-pie))
+pic-default = -DPIC
+pie-default = $(pie-ccflag)
+ifeq (yes,$(have-static-pie))
+default-pie-ldflag = -static-pie
+else
+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.
@@ -435,6 +445,7 @@ endif
 # Command for statically linking programs with the C library.
 ifndef +link-static
 +link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \
+	      $(default-pie-ldflag) \
 	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
 	      $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
 	      $(+preinit) $(+prectorT) \
@@ -651,8 +662,13 @@ 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))
++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/
 
@@ -973,7 +989,7 @@ 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))
+CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
 libtype.o := lib%.a
 object-suffixes += .o
 ifeq (yes,$(build-shared))
@@ -998,7 +1014,7 @@ ifeq (yes,$(build-profile))
 all-object-suffixes += .op
 object-suffixes += .op
 CPPFLAGS-.op = -DPROF $(pic-default)
-CFLAGS-.op = -pg
+CFLAGS-.op = -pg $(pie-default)
 libtype.op = lib%_p.a
 endif
 
diff --git a/NEWS b/NEWS
index f5821411ca..60f5def617 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,12 @@ 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).  Only i686, x86-64 and x32 targets are verified
+  to work.
+
 * 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 014fb4ea0e..26ed7865ef 100644
--- a/config.h.in
+++ b/config.h.in
@@ -236,6 +236,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 067d92d2ba..cd5cf5729f 100755
--- a/configure
+++ b/configure
@@ -767,6 +767,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
@@ -1424,6 +1425,7 @@ 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     build static executables as PIE [default=no]
   --disable-timezone-tools
                           do not install timezone tools [default=install]
   --enable-hardcoded-path-in-tests
@@ -3372,6 +3374,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
@@ -5994,6 +6003,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 :
@@ -6888,6 +6953,19 @@ fi
 $as_echo "$libc_cv_pie_default" >&6; }
 
 
+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 d412104d8c..09e1c7f23b 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@:>@]),
+	      [static_pie=$enableval],
+	      [static_pie=no])
 AC_ARG_ENABLE([timezone-tools],
 	      AC_HELP_STRING([--disable-timezone-tools],
 			     [do not install timezone tools @<:@default=install@:>@]),
@@ -1460,6 +1465,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])
 ])
@@ -1962,6 +1980,17 @@ fi
 rm -f conftest.*])
 AC_SUBST(libc_cv_pie_default)
 
+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/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/elf/dl-support.c b/elf/dl-support.c
index 5e3de90598..150ec00f9d 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -26,7 +26,11 @@
 #include <sys/param.h>
 #include <stdint.h>
 #include <ldsodefs.h>
-#include <dl-machine.h>
+#if ENABLE_STATIC_PIE
+# include "dynamic-link.h"
+#else
+# include <dl-machine.h>
+#endif
 #include <libc-lock.h>
 #include <dl-cache.h>
 #include <dl-librecon.h>
@@ -199,7 +203,9 @@ const ElfW(Ehdr) *_dl_sysinfo_dso;
 
 struct link_map *_dl_sysinfo_map;
 
-# include "get-dynamic-info.h"
+# if !ENABLE_STATIC_PIE
+#  include "get-dynamic-info.h"
+# endif
 #endif
 #include "setup-vdso.h"
 
@@ -302,6 +308,40 @@ _dl_aux_init (ElfW(auxv_t) *av)
 }
 #endif
 
+#if ENABLE_STATIC_PIE
+/* Relocate static executable with PIE.  */
+
+void
+_dl_relocate_static_pie (void)
+{
+# define STATIC_PIE_BOOTSTRAP
+# define BOOTSTRAP_MAP (&_dl_main_map)
+# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
+# include "dynamic-link.h"
+
+  /* Figure out the run-time load addres of static PIE.  */
+  _dl_main_map.l_addr = elf_machine_load_address ();
+
+  /* Skip if this is a non-PIE static executable.  */
+  if (!_dl_main_map.l_addr)
+    return;
+
+  /* Read our own dynamic section and fill in the info array.  */
+  _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr
+		       + elf_machine_dynamic ());
+  elf_get_dynamic_info (&_dl_main_map, NULL);
+
+# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+  ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0);
+  _dl_main_map.l_relocated = 1;
+}
+#endif
+
 
 void
 _dl_non_dynamic_init (void)
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/manual/install.texi b/manual/install.texi
index 35948b1bbb..54df6abb97 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -136,6 +136,14 @@ 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
+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.  Only i686, x86-64
+and x32 targets are verified to work.
+
 @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 1a4449eeb3..b4c032a06c 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1048,6 +1048,13 @@ 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.  */
+void _dl_relocate_static_pie (void) attribute_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/x86_64/configure b/sysdeps/x86_64/configure
index efef46b1b7..8ee15b8a25 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 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..53e4a8277c 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 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.13.6


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-09-29 21:49                 ` H.J. Lu
@ 2017-10-05 13:12                   ` H.J. Lu
  2017-10-05 15:22                     ` Szabolcs Nagy
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-10-05 13:12 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 6549 bytes --]

On 9/29/17, H.J. Lu <hjl.tools@gmail.com> wrote:
> On 9/28/17, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Wed, 27 Sep 2017, H.J. Lu wrote:
>>
>>> > static-PIE libraries) - although adding one or two additional
>>> > static-PIE
>>> > configurations to build-many-glibcs.py might be - but for testing
>>> > purposes
>>> > it's very useful to understand how widely this option works (or at
>>> > least
>>> > builds) for other architectures.
>>>
>>> Many architectures failed to build static PIE due to asm statements in
>>> elf_machine_dynamic and elf_machine_load_address.   I didn't check
>>> start.S which will fail at run-time if there are any dynamic
>>> relocations.
>>
>> In that case: (a) the install.texi / NEWS entries need to make clear the
>> limited nature of architecture support for this feature; (b) if the
>> feature achieves consensus to go in mainline at all,
>> <https://sourceware.org/glibc/wiki/PortStatus> will need updating with a
>> list of all the architectures lacking support and detailed information
>> for
>> architecture maintainers regarding how to make the feature work on their
>> architectures and how to tell whether it is working.
>>
>
> I submitted patches for other targets to address obvious issues with static
> PIE.  Build results of build-many-glibcs.py with --enable-static-pie with
> all
> patches for static PIE applied are
>
> PASS: glibcs-aarch64_be-linux-gnu build
> PASS: glibcs-aarch64-linux-gnu build
> PASS: glibcs-armeb-linux-gnueabi build
> PASS: glibcs-armeb-linux-gnueabi-be8 build
> PASS: glibcs-armeb-linux-gnueabihf build
> PASS: glibcs-armeb-linux-gnueabihf-be8 build
> PASS: glibcs-arm-linux-gnueabi build
> PASS: glibcs-arm-linux-gnueabihf build
> PASS: glibcs-hppa-linux-gnu build
> PASS: glibcs-i486-linux-gnu build
> PASS: glibcs-i586-linux-gnu build
> PASS: glibcs-i686-linux-gnu build
> PASS: glibcs-i686-linux-gnu-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-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-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-nios2-linux-gnu build
> PASS: glibcs-powerpc64le-linux-gnu build
> PASS: glibcs-powerpc64-linux-gnu build
> PASS: glibcs-s390x-linux-gnu build
> PASS: glibcs-x86_64-linux-gnu build
> PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build
> PASS: glibcs-x86_64-linux-gnu-x32 build
>
> 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-ia64-linux-gnu build
>
> elf/sln is failed to link due to:
>
> libc.a(sched_yield.o): non-pic code with imm relocation against
> dynamic symbol `_dl_sysinfo'
>
> This is caused by non-PICi version of DO_CALL macro in ia64 sysdep.h.  PIE
> libc.a should use PIC version of DO_CALL, except during startup in static
> PIE.  An ia64 startup.h, similar to i386 startup.h, is needed to handle
> this.
>
> FAIL: glibcs-mips64el-linux-gnu-n32 build
> FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build
> FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
> FAIL: glibcs-mips64el-linux-gnu-n32-soft build
> FAIL: glibcs-mips64-linux-gnu-n32 build
> FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build
> FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build
> FAIL: glibcs-mips64-linux-gnu-n32-soft build
> FAIL: glibcs-mipsel-linux-gnu build
> FAIL: glibcs-mipsel-linux-gnu-nan2008 build
> FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build
> FAIL: glibcs-mipsel-linux-gnu-soft build
> FAIL: glibcs-mips-linux-gnu build
> FAIL: glibcs-mips-linux-gnu-nan2008 build
> FAIL: glibcs-mips-linux-gnu-nan2008-soft build
> FAIL: glibcs-mips-linux-gnu-soft build
>
> elf/sln is failed to link due to:
>
> crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when
> making a shared object; recompile with -fPIC
>
> This is caused by linker bug and/or non-PIC code in crt1.o.
>
> 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.
>
> 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:14242
>
> 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.
>
> FAIL: glibcs-sparc64-linux-gnu build
> FAIL: glibcs-sparcv9-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.
>
> 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.
>
> Here is the updated patch to state that i686, x86-64 and x32 targets
> are verified to work.  I encourage target maintainers to try hjl/pie/static
> branch to verify if static PIE works for your targets.
>

Here is the updated patch.   The related glibc/binutils bugs are:

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


-- 
H.J.

[-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --]
[-- Type: text/x-patch, Size: 38594 bytes --]

From c9972a39895ce2aeb19d0f783569aea750f1698f 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 01/11] 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.

crt1.o, which is used to create dynamic and non-PIE static executables,
is updated to include a dummy _dl_relocate_static_pie.  Pcrt1.o is added
to create static PIE, which will link in the real _dl_relocate_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 statice 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, m68k, s390 and sh.

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.

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.

Tested on i686 and x86-64.

Build results of build-many-glibcs.py with --enable-static-pie with all
patches for static PIE applied are

PASS: glibcs-aarch64_be-linux-gnu build
PASS: glibcs-aarch64-linux-gnu build
PASS: glibcs-armeb-linux-gnueabi build
PASS: glibcs-armeb-linux-gnueabi-be8 build
PASS: glibcs-armeb-linux-gnueabihf build
PASS: glibcs-armeb-linux-gnueabihf-be8 build
PASS: glibcs-arm-linux-gnueabi build
PASS: glibcs-arm-linux-gnueabihf build
PASS: glibcs-hppa-linux-gnu build
PASS: glibcs-i486-linux-gnu build
PASS: glibcs-i586-linux-gnu build
PASS: glibcs-i686-linux-gnu build
PASS: glibcs-i686-linux-gnu-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-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-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-nios2-linux-gnu build
PASS: glibcs-powerpc64le-linux-gnu build
PASS: glibcs-powerpc64-linux-gnu build
PASS: glibcs-s390x-linux-gnu build
PASS: glibcs-x86_64-linux-gnu build
PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build
PASS: glibcs-x86_64-linux-gnu-x32 build

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-ia64-linux-gnu build

elf/sln is failed to link due to:

libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo'

This is caused by non-PIC version of DO_CALL macro in ia64 sysdep.h.  PIE
libc.a should use PIC version of DO_CALL, except during startup in static
PIE.  An ia64 startup.h, similar to i386 startup.h, is needed to handle
this.

FAIL: glibcs-mips64el-linux-gnu-n32 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64el-linux-gnu-n32-soft build
FAIL: glibcs-mips64-linux-gnu-n32 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64-linux-gnu-n32-soft build
FAIL: glibcs-mipsel-linux-gnu build
FAIL: glibcs-mipsel-linux-gnu-nan2008 build
FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build
FAIL: glibcs-mipsel-linux-gnu-soft build
FAIL: glibcs-mips-linux-gnu build
FAIL: glibcs-mips-linux-gnu-nan2008 build
FAIL: glibcs-mips-linux-gnu-nan2008-soft build
FAIL: glibcs-mips-linux-gnu-soft build

elf/sln is failed to link due to:

crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC

This is caused by linker bug and/or non-PIC code in crt1.o.

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:14242

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.

FAIL: glibcs-sparc64-linux-gnu build
FAIL: glibcs-sparcv9-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=20179

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 (static-start-installed-name): Add the `P' prefix
	for --enable-static-pie.
	(pic-default): Updated for --enable-static-pie.
	(pie-default): New for --enable-static-pie.
	(default-pie-ldflag): Likewise.
	(+link-static-before-libc): Use the first of $(DEFAULT-LDFLAGS-$(@F))
	and $(default-pie-ldflag).  Use the first of $(CRT-$(@F)) and
	$(csu-objpfx)$(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 P$(start-installed-name) for
	--enable-static-pie.
	(extra-objs): Likewise.
	(install-lib): Likewise.
	Don't add gPcrt1.o.
	(extra-objs): Add static-reloc.o.
	($(objpfx)$(start-installed-name)): Include $(objpfx)static-reloc.o.
	($(objpfx)P$(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.
	* dl-reloc-static-pie.c: New file.
	* elf/dl-support.c (_dl_main_map): Make it hidden global.
	* elf/dynamic-link.h (ELF_DURING_STARTUP): Also check
	STATIC_PIE_BOOTSTRAP.
	* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
	* manual/install.texi: Document --enable-static-pie.
	* sysdeps/generic/ldsodefs.h (_dl_relocate_static_pie): New.
	* 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.
---
 INSTALL                     |  8 +++++
 Makeconfig                  | 27 +++++++++++++---
 NEWS                        |  6 ++++
 config.h.in                 |  3 ++
 configure                   | 78 +++++++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 29 +++++++++++++++++
 csu/Makefile                | 16 ++++++++--
 csu/libc-start.c            |  2 ++
 csu/libc-tls.c              |  6 ++--
 csu/static-reloc.c          | 26 +++++++++++++++
 elf/Makefile                |  5 +--
 elf/dl-reloc-static-pie.c   | 53 ++++++++++++++++++++++++++++++
 elf/dl-support.c            |  2 +-
 elf/dynamic-link.h          |  2 +-
 elf/get-dynamic-info.h      |  6 ++--
 manual/install.texi         |  8 +++++
 sysdeps/generic/ldsodefs.h  |  7 ++++
 sysdeps/i386/configure      | 33 +++++++++++++++++++
 sysdeps/i386/configure.ac   | 23 +++++++++++++
 sysdeps/x86_64/configure    | 33 +++++++++++++++++++
 sysdeps/x86_64/configure.ac | 25 +++++++++++++++
 21 files changed, 383 insertions(+), 15 deletions(-)
 create mode 100644 csu/static-reloc.c
 create mode 100644 elf/dl-reloc-static-pie.c

diff --git a/INSTALL b/INSTALL
index 4d9024c667..55361a0fd3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -106,6 +106,14 @@ 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'
+     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. Only
+     i686, x86-64 and x32 targets are verified to work.
+
 '--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 0ceff92a3d..ac79083912 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -367,6 +367,10 @@ ifndef static-start-installed-name
 static-start-installed-name = $(start-installed-name)
 endif
 
+ifeq (yes,$(enable-static-pie))
+static-start-installed-name := P$(static-start-installed-name)
+endif
+
 ifeq (yesyes,$(build-shared)$(have-z-combreloc))
 combreloc-LDFLAGS = -Wl,-z,combreloc
 LDFLAGS.so += $(combreloc-LDFLAGS)
@@ -386,6 +390,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
 LDFLAGS-rtld += $(hashstyle-LDFLAGS)
 endif
 
+ifeq (yes,$(enable-static-pie))
+pic-default = -DPIC
+pie-default = $(pie-ccflag)
+ifeq (yes,$(have-static-pie))
+default-pie-ldflag = -static-pie
+else
+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.
@@ -435,9 +449,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)) \
+	      $(firstword $(DEFAULT-LDFLAGS-$(@F)) $(default-pie-ldflag)) \
 	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
-	      $(addprefix $(csu-objpfx),$(static-start-installed-name)) \
+	      $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \
 	      $(+preinit) $(+prectorT) \
 	      $(filter-out $(addprefix $(csu-objpfx),start.o \
 						     $(start-installed-name))\
@@ -652,8 +666,13 @@ 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))
++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/
 
@@ -974,7 +993,7 @@ 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))
+CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
 libtype.o := lib%.a
 object-suffixes += .o
 ifeq (yes,$(build-shared))
@@ -999,7 +1018,7 @@ ifeq (yes,$(build-profile))
 all-object-suffixes += .op
 object-suffixes += .op
 CPPFLAGS-.op = -DPROF $(pic-default)
-CFLAGS-.op = -pg
+CFLAGS-.op = -pg $(pie-default)
 libtype.op = lib%_p.a
 endif
 
diff --git a/NEWS b/NEWS
index f5821411ca..60f5def617 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,12 @@ 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).  Only i686, x86-64 and x32 targets are verified
+  to work.
+
 * 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 c140ff3ecb..f7db916711 100644
--- a/config.h.in
+++ b/config.h.in
@@ -244,6 +244,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 a7c72eaaa6..6bf3c6c1af 100755
--- a/configure
+++ b/configure
@@ -767,6 +767,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
@@ -1424,6 +1425,7 @@ 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     build static executables as PIE [default=no]
   --disable-timezone-tools
                           do not install timezone tools [default=install]
   --enable-hardcoded-path-in-tests
@@ -3372,6 +3374,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
@@ -5998,6 +6007,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 :
@@ -6892,6 +6957,19 @@ fi
 $as_echo "$libc_cv_pie_default" >&6; }
 
 
+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 4b83ae5a09..b2f727224f 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@:>@]),
+	      [static_pie=$enableval],
+	      [static_pie=no])
 AC_ARG_ENABLE([timezone-tools],
 	      AC_HELP_STRING([--disable-timezone-tools],
 			     [do not install timezone tools @<:@default=install@:>@]),
@@ -1464,6 +1469,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])
 ])
@@ -1966,6 +1984,17 @@ fi
 rm -f conftest.*])
 AC_SUBST(libc_cv_pie_default)
 
+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 fd668a5d00..e342a19956 100644
--- a/csu/Makefile
+++ b/csu/Makefile
@@ -37,7 +37,8 @@ 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) \
+			     P$(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
@@ -55,16 +56,24 @@ extra-objs += gmon-start.o
 endif
 install-lib += S$(start-installed-name)
 generated += start.os
+ifeq (yes,$(enable-static-pie))
+extra-objs += P$(start-installed-name)
+install-lib += P$(start-installed-name)
+endif
 else
 extra-objs += gmon-start.o
 endif
 
 ifneq ($(start-installed-name),$(static-start-installed-name))
+# FIXME: If we want to support profiling static PIE, we need to create
+# and install gPcrt1.o.
+ifneq (P$(start-installed-name),$(static-start-installed-name))
 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)
 endif
+endif
 
 before-compile += $(objpfx)abi-tag.h
 generated += abi-tag.h
@@ -77,7 +86,7 @@ crtstuff = crti crtn
 install-lib += $(crtstuff:=.o)
 extra-objs += $(crtstuff:=.o)
 
-extra-objs += abi-note.o init.o
+extra-objs += abi-note.o init.o static-reloc.o
 asm-CPPFLAGS += -I$(objpfx).
 
 # Enable unwinding so backtrace unwinds to __libc_start_main
@@ -96,6 +105,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)P$(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 \
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 a31fb72498..cb035e63aa 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
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
new file mode 100644
index 0000000000..630482a28a
--- /dev/null
+++ b/elf/dl-reloc-static-pie.c
@@ -0,0 +1,53 @@
+/* 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.  */
+
+extern struct link_map _dl_main_map __attribute__((visibility ("hidden")));
+
+void
+_dl_relocate_static_pie (void)
+{
+# define STATIC_PIE_BOOTSTRAP
+# define BOOTSTRAP_MAP (&_dl_main_map)
+# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
+# include "dynamic-link.h"
+
+  /* Figure out the run-time load addres of static PIE.  */
+  _dl_main_map.l_addr = elf_machine_load_address ();
+
+  /* Read our own dynamic section and fill in the info array.  */
+  _dl_main_map.l_ld = ((void *) _dl_main_map.l_addr
+		       + elf_machine_dynamic ());
+  elf_get_dynamic_info (&_dl_main_map, NULL);
+
+# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+  ELF_MACHINE_BEFORE_RTLD_RELOC (_dl_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 (&_dl_main_map, 0, 0, 0);
+  _dl_main_map.l_relocated = 1;
+}
+#endif
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 5e3de90598..99ad0f1781 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -72,7 +72,7 @@ int _dl_bind_not;
 
 /* A dummy link map for the executable, used by dlopen to access the global
    scope.  We don't export any symbols ourselves, so this can be minimal.  */
-static struct link_map _dl_main_map =
+struct link_map _dl_main_map __attribute__((visibility ("hidden"))) =
   {
     .l_name = (char *) "",
     .l_real = &_dl_main_map,
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/manual/install.texi b/manual/install.texi
index 35948b1bbb..54df6abb97 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -136,6 +136,14 @@ 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
+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.  Only i686, x86-64
+and x32 targets are verified to work.
+
 @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 5efae2d96d..dbcc1ec766 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1048,6 +1048,13 @@ 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.  */
+void _dl_relocate_static_pie (void) attribute_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/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.13.6


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-10-05 13:12                   ` H.J. Lu
@ 2017-10-05 15:22                     ` Szabolcs Nagy
  2017-10-05 23:36                       ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Szabolcs Nagy @ 2017-10-05 15:22 UTC (permalink / raw)
  To: H.J. Lu, Joseph Myers; +Cc: nd, GNU C Library

On 05/10/17 14:11, H.J. Lu wrote:
> On 9/29/17, H.J. Lu <hjl.tools@gmail.com> wrote:
>> I submitted patches for other targets to address obvious issues with static
>> PIE.  Build results of build-many-glibcs.py with --enable-static-pie with
>> all
>> patches for static PIE applied are
>>
>> PASS: glibcs-aarch64_be-linux-gnu build
>> PASS: glibcs-aarch64-linux-gnu build

can you tell me the binutils version used?

building fails with recent binutils master:

builddir/libc.a(dl-reloc-static-pie.o): In function `elf_get_dynamic_info':
srcdir/elf/get-dynamic-info.h:73:(.text+0x4c): relocation truncated to fit: R_AARCH64_ADR_PREL_PG_HI21 against
symbol `_dl_main_map' defined in .data.rel.local section in builddir/libc.a(dl-support.o)
srcdir/elf/get-dynamic-info.h:70:(.text+0x50): relocation truncated to fit: R_AARCH64_ADR_PREL_PG_HI21 against
symbol `_dl_main_map' defined in .data.rel.local section in builddir/libc.a(dl-support.o)

and

$ objdump -t builddir/elf/dl-support.o
...
0000000000000000 g     O .data.rel.local	0000000000000468 .hidden _dl_main_map
...
$ objdump -r builddir/elf/dl-reloc-static-pie.o
...
000000000000004c R_AARCH64_ADR_PREL_PG_HI21  _dl_main_map+0x000000037ffffa40
0000000000000050 R_AARCH64_ADR_PREL_PG_HI21  _dl_main_map+0x000000037ffff1e0
...

those offsets look wrong, i'll need to investigate

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-10-05 15:22                     ` Szabolcs Nagy
@ 2017-10-05 23:36                       ` H.J. Lu
  2017-10-12 22:07                         ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-10-05 23:36 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Joseph Myers, nd, GNU C Library

On 10/5/17, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
> On 05/10/17 14:11, H.J. Lu wrote:
>> On 9/29/17, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> I submitted patches for other targets to address obvious issues with
>>> static
>>> PIE.  Build results of build-many-glibcs.py with --enable-static-pie
>>> with
>>> all
>>> patches for static PIE applied are
>>>
>>> PASS: glibcs-aarch64_be-linux-gnu build
>>> PASS: glibcs-aarch64-linux-gnu build
>
> can you tell me the binutils version used?
> building fails with recent binutils master:
>
> builddir/libc.a(dl-reloc-static-pie.o): In function `elf_get_dynamic_info':
> srcdir/elf/get-dynamic-info.h:73:(.text+0x4c): relocation truncated to fit:
> R_AARCH64_ADR_PREL_PG_HI21 against
> symbol `_dl_main_map' defined in .data.rel.local section in
> builddir/libc.a(dl-support.o)
> srcdir/elf/get-dynamic-info.h:70:(.text+0x50): relocation truncated to fit:
> R_AARCH64_ADR_PREL_PG_HI21 against
> symbol `_dl_main_map' defined in .data.rel.local section in
> builddir/libc.a(dl-support.o)
>
> and
>
> $ objdump -t builddir/elf/dl-support.o
> ...
> 0000000000000000 g     O .data.rel.local	0000000000000468 .hidden
> _dl_main_map
> ...
> $ objdump -r builddir/elf/dl-reloc-static-pie.o
> ...
> 000000000000004c R_AARCH64_ADR_PREL_PG_HI21
> _dl_main_map+0x000000037ffffa40
> 0000000000000050 R_AARCH64_ADR_PREL_PG_HI21
> _dl_main_map+0x000000037ffff1e0
> ...
>
> those offsets look wrong, i'll need to investigate
>
>

Did you mean addend?  In any case, I checked a workaround
into hjl/pie/static.  Please give it a try,

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-10-05 23:36                       ` H.J. Lu
@ 2017-10-12 22:07                         ` H.J. Lu
  2017-10-12 22:16                           ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-10-12 22:07 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Joseph Myers, nd, GNU C Library

[-- Attachment #1: Type: text/plain, Size: 1809 bytes --]

On 10/5/17, H.J. Lu <hjl.tools@gmail.com> wrote:
> On 10/5/17, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
>> On 05/10/17 14:11, H.J. Lu wrote:
>>> On 9/29/17, H.J. Lu <hjl.tools@gmail.com> wrote:
>>>> I submitted patches for other targets to address obvious issues with
>>>> static
>>>> PIE.  Build results of build-many-glibcs.py with --enable-static-pie
>>>> with
>>>> all
>>>> patches for static PIE applied are
>>>>
>>>> PASS: glibcs-aarch64_be-linux-gnu build
>>>> PASS: glibcs-aarch64-linux-gnu build
>>
>> can you tell me the binutils version used?
>> building fails with recent binutils master:
>>
>> builddir/libc.a(dl-reloc-static-pie.o): In function
>> `elf_get_dynamic_info':
>> srcdir/elf/get-dynamic-info.h:73:(.text+0x4c): relocation truncated to
>> fit:
>> R_AARCH64_ADR_PREL_PG_HI21 against
>> symbol `_dl_main_map' defined in .data.rel.local section in
>> builddir/libc.a(dl-support.o)
>> srcdir/elf/get-dynamic-info.h:70:(.text+0x50): relocation truncated to
>> fit:
>> R_AARCH64_ADR_PREL_PG_HI21 against
>> symbol `_dl_main_map' defined in .data.rel.local section in
>> builddir/libc.a(dl-support.o)
>>
>> and
>>
>> $ objdump -t builddir/elf/dl-support.o
>> ...
>> 0000000000000000 g     O .data.rel.local	0000000000000468 .hidden
>> _dl_main_map
>> ...
>> $ objdump -r builddir/elf/dl-reloc-static-pie.o
>> ...
>> 000000000000004c R_AARCH64_ADR_PREL_PG_HI21
>> _dl_main_map+0x000000037ffffa40
>> 0000000000000050 R_AARCH64_ADR_PREL_PG_HI21
>> _dl_main_map+0x000000037ffff1e0
>> ...
>>
>> those offsets look wrong, i'll need to investigate
>>
>>
>
> Did you mean addend?  In any case, I checked a workaround
> into hjl/pie/static.  Please give it a try,

Here is the updated patch.  The main change is that gPcrt1.o is also added
to create static PIE with -pg.

OK for master?

-- 
H.J.

[-- Attachment #2: 0011-Add-enable-static-pie-to-build-many-glibcs.py.patch --]
[-- Type: text/x-patch, Size: 867 bytes --]

From 1798eb01da55411ce2c74ad0241801c03a1b67e6 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 27 Sep 2017 16:47:29 -0700
Subject: [PATCH 11/11] Add --enable-static-pie to build-many-glibcs.py

---
 scripts/build-many-glibcs.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py
index a6c01f9cc4..2b6b132bb4 100755
--- a/scripts/build-many-glibcs.py
+++ b/scripts/build-many-glibcs.py
@@ -1342,6 +1342,7 @@ class Glibc(object):
         cmdlist.create_copy_dir(srcdir, srcdir_copy)
         cfg_cmd = [os.path.join(srcdir_copy, 'configure'),
                    '--prefix=/usr',
+                   '--enable-static-pie',
                    '--enable-profile',
                    '--build=%s' % self.ctx.build_triplet,
                    '--host=%s' % self.triplet,
-- 
2.13.6


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-10-12 22:07                         ` H.J. Lu
@ 2017-10-12 22:16                           ` Joseph Myers
  2017-10-12 22:26                             ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-10-12 22:16 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Szabolcs Nagy, nd, GNU C Library

On Thu, 12 Oct 2017, H.J. Lu wrote:

> Here is the updated patch.  The main change is that gPcrt1.o is also added
> to create static PIE with -pg.

The attached build-many-glibcs.py patch is definitely inappropriate for 
master.  If --enable-static-pie is approved, it would be appropriate to 
build one or two additional glibc variants in build-many-glibcs.py with 
this option.  It is *not* appropriate to add it to all builds there, 
because of how (as discussed) the option is different from 
--enable-profile, changing how the normal static libc is built instead of 
adding a new variable.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-10-12 22:16                           ` Joseph Myers
@ 2017-10-12 22:26                             ` H.J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2017-10-12 22:26 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Szabolcs Nagy, nd, GNU C Library

[-- Attachment #1: Type: text/plain, Size: 784 bytes --]

On 10/12/17, Joseph Myers <joseph@codesourcery.com> wrote:
> On Thu, 12 Oct 2017, H.J. Lu wrote:
>
>> Here is the updated patch.  The main change is that gPcrt1.o is also
>> added
>> to create static PIE with -pg.
>
> The attached build-many-glibcs.py patch is definitely inappropriate for

Oops.   Here is the right patch.

> master.  If --enable-static-pie is approved, it would be appropriate to
> build one or two additional glibc variants in build-many-glibcs.py with

Sure.

> this option.  It is *not* appropriate to add it to all builds there,
> because of how (as discussed) the option is different from
> --enable-profile, changing how the normal static libc is built instead of
> adding a new variable.
>

I will look into it after --enable-static-pie is merged.

-- 
H.J.

[-- Attachment #2: 0001-Add-enable-static-pie-configure-option-to-build-stat.patch --]
[-- Type: text/x-patch, Size: 40993 bytes --]

From 83e95a0f4d5450816b968d04f846465caa6d511b 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 01/11] 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.

crt1.o, which is used to create dynamic and non-PIE static executables,
is updated to include a dummy _dl_relocate_static_pie.  Pcrt1.o is added
to create static PIE, which will link in the real _dl_relocate_static_pie.
gPcrt1.o is also added to create static PIE with -pg.

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 statice 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, m68k, s390 and sh.

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.

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 i686 and x86-64.

Build results of build-many-glibcs.py with --enable-static-pie with all
patches for static PIE applied are

PASS: glibcs-aarch64_be-linux-gnu build
PASS: glibcs-aarch64-linux-gnu build
PASS: glibcs-armeb-linux-gnueabi build
PASS: glibcs-armeb-linux-gnueabi-be8 build
PASS: glibcs-armeb-linux-gnueabihf build
PASS: glibcs-armeb-linux-gnueabihf-be8 build
PASS: glibcs-arm-linux-gnueabi build
PASS: glibcs-arm-linux-gnueabihf build
PASS: glibcs-hppa-linux-gnu build
PASS: glibcs-i486-linux-gnu build
PASS: glibcs-i586-linux-gnu build
PASS: glibcs-i686-linux-gnu build
PASS: glibcs-i686-linux-gnu-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-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-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-nios2-linux-gnu build
PASS: glibcs-powerpc64le-linux-gnu build
PASS: glibcs-powerpc64-linux-gnu build
PASS: glibcs-s390x-linux-gnu build
PASS: glibcs-x86_64-linux-gnu build
PASS: glibcs-x86_64-linux-gnu-disable-multi-arch build
PASS: glibcs-x86_64-linux-gnu-x32 build

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-ia64-linux-gnu build

elf/sln is failed to link due to:

libc.a(sched_yield.o): non-pic code with imm relocation against dynamic symbol `_dl_sysinfo'

This is caused by non-PIC version of DO_CALL macro in ia64 sysdep.h.  PIE
libc.a should use PIC version of DO_CALL, except during startup in static
PIE.  An ia64 startup.h, similar to i386 startup.h, is needed to handle
this.

FAIL: glibcs-mips64el-linux-gnu-n32 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64el-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64el-linux-gnu-n32-soft build
FAIL: glibcs-mips64-linux-gnu-n32 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008 build
FAIL: glibcs-mips64-linux-gnu-n32-nan2008-soft build
FAIL: glibcs-mips64-linux-gnu-n32-soft build
FAIL: glibcs-mipsel-linux-gnu build
FAIL: glibcs-mipsel-linux-gnu-nan2008 build
FAIL: glibcs-mipsel-linux-gnu-nan2008-soft build
FAIL: glibcs-mipsel-linux-gnu-soft build
FAIL: glibcs-mips-linux-gnu build
FAIL: glibcs-mips-linux-gnu-nan2008 build
FAIL: glibcs-mips-linux-gnu-nan2008-soft build
FAIL: glibcs-mips-linux-gnu-soft build

elf/sln is failed to link due to:

crt1.o: relocation R_MIPS_HI16 against `_gp' can not be used when making a shared object; recompile with -fPIC

This is caused by linker bug and/or non-PIC code in crt1.o.

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:14242

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 (static-start-installed-name): Add the `P' prefix
	for --enable-static-pie.
	(pic-default): Updated for --enable-static-pie.
	(pie-default): New for --enable-static-pie.
	(default-pie-ldflag): Likewise.
	(+link-static-before-libc): Use the first of $(DEFAULT-LDFLAGS-$(@F))
	and $(default-pie-ldflag).
	(+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 P$(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)P$(start-installed-name)): New.
	($(objpfx)g$(start-installed-name)): Also depend on
	$(objpfx)static-reloc.os.
	* 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.
	* 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.
	(CFLAGS-tst-gmon-static-pie.c): New.
	(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.
	* 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.
---
 INSTALL                     |  8 +++++
 Makeconfig                  | 25 +++++++++++++--
 NEWS                        |  6 ++++
 config.h.in                 |  3 ++
 configure                   | 78 +++++++++++++++++++++++++++++++++++++++++++++
 configure.ac                | 29 +++++++++++++++++
 csu/Makefile                | 17 ++++++++--
 csu/libc-start.c            |  2 ++
 csu/libc-tls.c              |  6 ++--
 csu/static-reloc.c          | 26 +++++++++++++++
 elf/Makefile                |  5 +--
 elf/dl-reloc-static-pie.c   | 55 ++++++++++++++++++++++++++++++++
 elf/dl-support.c            | 11 +++++++
 elf/dynamic-link.h          |  2 +-
 elf/get-dynamic-info.h      |  6 ++--
 gmon/Makefile               | 23 +++++++++++++
 gmon/tst-gmon-static-pie.c  |  1 +
 manual/install.texi         |  8 +++++
 sysdeps/generic/ldsodefs.h  |  7 ++++
 sysdeps/i386/configure      | 33 +++++++++++++++++++
 sysdeps/i386/configure.ac   | 23 +++++++++++++
 sysdeps/x86_64/configure    | 33 +++++++++++++++++++
 sysdeps/x86_64/configure.ac | 25 +++++++++++++++
 23 files changed, 418 insertions(+), 14 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 bc972b2ffa..b58ae890a3 100644
--- a/INSTALL
+++ b/INSTALL
@@ -89,6 +89,14 @@ 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'
+     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. Only
+     i686, x86-64 and x32 targets are verified to work.
+
 '--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..7e83f4da7b 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -352,6 +352,10 @@ ifndef static-start-installed-name
 static-start-installed-name = $(start-installed-name)
 endif
 
+ifeq (yes,$(enable-static-pie))
+static-start-installed-name := P$(static-start-installed-name)
+endif
+
 ifeq (yesyes,$(build-shared)$(have-z-combreloc))
 combreloc-LDFLAGS = -Wl,-z,combreloc
 LDFLAGS.so += $(combreloc-LDFLAGS)
@@ -371,6 +375,16 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
 LDFLAGS-rtld += $(hashstyle-LDFLAGS)
 endif
 
+ifeq (yes,$(enable-static-pie))
+pic-default = -DPIC
+pie-default = $(pie-ccflag)
+ifeq (yes,$(have-static-pie))
+default-pie-ldflag = -static-pie
+else
+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,7 +434,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)) \
 	      $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F))  \
 	      $(firstword $(CRT-$(@F)) $(csu-objpfx)$(static-start-installed-name)) \
 	      $(+preinit) $(+prectorT) \
@@ -637,8 +651,13 @@ 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))
++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 +978,7 @@ 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))
+CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
 libtype.o := lib%.a
 object-suffixes += .o
 ifeq (yes,$(build-shared))
@@ -984,7 +1003,7 @@ ifeq (yes,$(build-profile))
 all-object-suffixes += .op
 object-suffixes += .op
 CPPFLAGS-.op = -DPROF $(pic-default)
-CFLAGS-.op = -pg
+CFLAGS-.op = -pg $(pie-default)
 libtype.op = lib%_p.a
 endif
 
diff --git a/NEWS b/NEWS
index 464d1ce9b3..db551561bf 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,12 @@ 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).  Only i686, x86-64 and x32 targets are verified
+  to work.
+
 * 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 c140ff3ecb..f7db916711 100644
--- a/config.h.in
+++ b/config.h.in
@@ -244,6 +244,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 c2c9c72d5a..dcb044e763 100755
--- a/configure
+++ b/configure
@@ -764,6 +764,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
@@ -1419,6 +1420,7 @@ 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     build static executables as PIE [default=no]
   --disable-timezone-tools
                           do not install timezone tools [default=install]
   --enable-hardcoded-path-in-tests
@@ -3364,6 +3366,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
@@ -5765,6 +5774,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 :
@@ -6659,6 +6724,19 @@ fi
 $as_echo "$libc_cv_pie_default" >&6; }
 
 
+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 195e81acfd..cac82af948 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@:>@]),
+	      [static_pie=$enableval],
+	      [static_pie=no])
 AC_ARG_ENABLE([timezone-tools],
 	      AC_HELP_STRING([--disable-timezone-tools],
 			     [do not install timezone tools @<:@default=install@:>@]),
@@ -1250,6 +1255,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])
 ])
@@ -1752,6 +1770,17 @@ fi
 rm -f conftest.*])
 AC_SUBST(libc_cv_pie_default)
 
+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 fd668a5d00..287cee4330 100644
--- a/csu/Makefile
+++ b/csu/Makefile
@@ -37,7 +37,8 @@ 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) \
+			     P$(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
@@ -55,6 +56,10 @@ extra-objs += gmon-start.o
 endif
 install-lib += S$(start-installed-name)
 generated += start.os
+ifeq (yes,$(enable-static-pie))
+extra-objs += P$(start-installed-name)
+install-lib += P$(start-installed-name)
+endif
 else
 extra-objs += gmon-start.o
 endif
@@ -77,7 +82,10 @@ crtstuff = crti crtn
 install-lib += $(crtstuff:=.o)
 extra-objs += $(crtstuff:=.o)
 
-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
@@ -96,6 +104,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)P$(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 \
@@ -108,7 +119,7 @@ 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)
 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 a31fb72498..cb035e63aa 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
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
new file mode 100644
index 0000000000..077d87e5ff
--- /dev/null
+++ b/elf/dl-reloc-static-pie.c
@@ -0,0 +1,55 @@
+/* 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"
+
+extern struct link_map * _dl_get_dl_main_map (void)
+  __attribute__ ((visibility ("hidden")));
+
+/* 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 addres 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 5e3de90598..282e99d5e9 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -384,3 +384,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..d956e890dd 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.
@@ -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)gPcrt1.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 96b988e829..67bf48e1ea 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -120,6 +120,14 @@ 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
+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.  Only i686, x86-64
+and x32 targets are verified to work.
+
 @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 5efae2d96d..dbcc1ec766 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1048,6 +1048,13 @@ 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.  */
+void _dl_relocate_static_pie (void) attribute_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/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.13.6


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-10-23 22:56 ` Joseph Myers
@ 2017-10-23 23:13   ` H.J. Lu
  0 siblings, 0 replies; 28+ messages in thread
From: H.J. Lu @ 2017-10-23 23:13 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Szabolcs Nagy, nd, GNU C Library

On Mon, Oct 23, 2017 at 3:56 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Mon, 23 Oct 2017, H.J. Lu wrote:
>
>> PING.
>
> I'm not clear exactly what patch or patches you are pinging.
>
> If you still have any architecture-specific patches pending review by the
> architecture maintainers, I suggest starting with pinging those, making
> sure to CC the relevant architecture maintainers.  Separately,
> architecture-specific patches can be pinged (in each case, giving the URL
> of the patch being pinged); those will need detailed core developer review
> covering the details of the design and implementation.
>

I am pinging this patch:

https://sourceware.org/ml/libc-alpha/2017-10/msg00587.html

I have addressed all the concerns raised.


-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
  2017-10-23 22:27 H.J. Lu
@ 2017-10-23 22:56 ` Joseph Myers
  2017-10-23 23:13   ` H.J. Lu
  0 siblings, 1 reply; 28+ messages in thread
From: Joseph Myers @ 2017-10-23 22:56 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Szabolcs Nagy, nd, GNU C Library

On Mon, 23 Oct 2017, H.J. Lu wrote:

> PING.

I'm not clear exactly what patch or patches you are pinging.

If you still have any architecture-specific patches pending review by the 
architecture maintainers, I suggest starting with pinging those, making 
sure to CC the relevant architecture maintainers.  Separately, 
architecture-specific patches can be pinged (in each case, giving the URL 
of the patch being pinged); those will need detailed core developer review 
covering the details of the design and implementation.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: PING: [PATCH] Add --enable-static-pie to build static PIE
@ 2017-10-23 22:27 H.J. Lu
  2017-10-23 22:56 ` Joseph Myers
  0 siblings, 1 reply; 28+ messages in thread
From: H.J. Lu @ 2017-10-23 22:27 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Szabolcs Nagy, nd, GNU C Library

On Thu, Oct 12, 2017 at 3:26 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On 10/12/17, Joseph Myers <joseph@codesourcery.com> wrote:
>> On Thu, 12 Oct 2017, H.J. Lu wrote:
>>
>>> Here is the updated patch.  The main change is that gPcrt1.o is also
>>> added
>>> to create static PIE with -pg.
>>
>> The attached build-many-glibcs.py patch is definitely inappropriate for
>
> Oops.   Here is the right patch.
>
>> master.  If --enable-static-pie is approved, it would be appropriate to
>> build one or two additional glibc variants in build-many-glibcs.py with
>
> Sure.
>
>> this option.  It is *not* appropriate to add it to all builds there,
>> because of how (as discussed) the option is different from
>> --enable-profile, changing how the normal static libc is built instead of
>> adding a new variable.
>>
>
> I will look into it after --enable-static-pie is merged.
>

PING.

The main issues with static PIE are

1. Many binutils targets don't handle PIE properly.  I opened a few binutils
bugs for PIE.
2. Many assembly codes under sysdeps assumes PIC == SHARED.
I opened a glibc bug for it.
3. Some dl-machine.h files may not handle undefined weak symbols in PIE
properly.   But we will never know for sure unless we build static PIE.

I'd like to add static PIE support to glibc, which works on i686 and x86-64.
I will help other target developers get static PIE working for his/her target.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2017-10-23 23:13 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-11 16:47 PING: [PATCH] Add --enable-static-pie to build static PIE H.J. Lu
2017-09-26 22:51 ` H.J. Lu
2017-09-26 23:11   ` Joseph Myers
2017-09-27  8:30     ` H.J. Lu
2017-09-27  9:43       ` Szabolcs Nagy
2017-09-27 21:12         ` H.J. Lu
2017-09-27 10:55       ` Florian Weimer
2017-09-27 11:09         ` Szabolcs Nagy
2017-09-27 21:16           ` H.J. Lu
2017-09-27 21:14         ` H.J. Lu
2017-09-27 12:41       ` Joseph Myers
2017-09-27 21:28         ` H.J. Lu
2017-09-28  0:49           ` Joseph Myers
2017-09-28  2:21             ` H.J. Lu
2017-09-28 13:03               ` Joseph Myers
2017-09-29 21:49                 ` H.J. Lu
2017-10-05 13:12                   ` H.J. Lu
2017-10-05 15:22                     ` Szabolcs Nagy
2017-10-05 23:36                       ` H.J. Lu
2017-10-12 22:07                         ` H.J. Lu
2017-10-12 22:16                           ` Joseph Myers
2017-10-12 22:26                             ` H.J. Lu
2017-09-28  9:37       ` Markus Trippelsdorf
2017-09-28 12:26         ` H.J. Lu
2017-09-28 13:25           ` Markus Trippelsdorf
2017-10-23 22:27 H.J. Lu
2017-10-23 22:56 ` Joseph Myers
2017-10-23 23:13   ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).