[v5,1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Testing passed
|
redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Testing passed
|
Commit Message
When a static PIE is loaded at the specific address, its PT_DYNAMIC
segment entries contain the relocated values for the load address.
Compute the load address from the p_vaddr of the PT_LOAD segement
which covers the file start. This fixes BZ #31799.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
configure | 67 ++++++++++++++++++++++++++++++++++++
configure.ac | 30 ++++++++++++++++
elf/Makefile | 20 +++++++++++
elf/dl-reloc-static-pie.c | 25 ++++++++++----
elf/tst-pie-address-static.c | 19 ++++++++++
elf/tst-pie-address.c | 28 +++++++++++++++
6 files changed, 182 insertions(+), 7 deletions(-)
create mode 100644 elf/tst-pie-address-static.c
create mode 100644 elf/tst-pie-address.c
Comments
* H. J. Lu:
> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> segment entries contain the relocated values for the load address.
> Compute the load address from the p_vaddr of the PT_LOAD segement
> which covers the file start. This fixes BZ #31799.
A PIE loaded at a specific address is no longer PIE.
I think this should work:
cat > t.c <<EOF
#include <stdio.h>
int
main (void)
{
puts ("Hello, world!");
}
EOF
ld --verbose | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> ld.script
gcc -fpie -static -Wl,-T,ld.script t.c
But it fails with:
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
(.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
collect2: error: ld returned 1 exit status
This is the relocation:
18: 48 8b 3d 00 00 00 00 mov 0x0(%rip),%rdi # 1f <_start+0x1f>
1b: R_X86_64_REX_GOTPCRELX main-0x4
1f: ff 15 00 00 00 00 call *0x0(%rip) # 25 <_start+0x25>
21: R_X86_64_GOTPCRELX __libc_start_main-0x4
Shouldn't it be possible to relax it to this?
lea main(%rip),%rdi
Thanks,
Florian
On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> > segment entries contain the relocated values for the load address.
> > Compute the load address from the p_vaddr of the PT_LOAD segement
> > which covers the file start. This fixes BZ #31799.
>
> A PIE loaded at a specific address is no longer PIE.
>
> I think this should work:
>
> cat > t.c <<EOF
> #include <stdio.h>
>
> int
> main (void)
> {
> puts ("Hello, world!");
> }
> EOF
> ld --verbose | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> > ld.script
> gcc -fpie -static -Wl,-T,ld.script t.c
>
> But it fails with:
>
> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
> collect2: error: ld returned 1 exit status
Did you mean?
[hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
function `_start':
(.text+0x1b): failed to convert GOTPCREL relocation against 'main';
relink with --no-relax
/usr/local/bin/ld: final link failed
collect2: error: ld returned 1 exit status
[hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
function `_start':
(.text+0x1b): failed to convert GOTPCREL relocation against 'main';
relink with --no-relax
/usr/local/bin/ld: final link failed
collect2: error: ld returned 1 exit status
[hjl@gnu-cfl-3 tmp]$
This no longer fits in the small model.
> This is the relocation:
>
> 18: 48 8b 3d 00 00 00 00 mov 0x0(%rip),%rdi # 1f <_start+0x1f>
> 1b: R_X86_64_REX_GOTPCRELX main-0x4
> 1f: ff 15 00 00 00 00 call *0x0(%rip) # 25 <_start+0x25>
> 21: R_X86_64_GOTPCRELX __libc_start_main-0x4
>
> Shouldn't it be possible to relax it to this?
>
> lea main(%rip),%rdi
>
This is just a tip of the icebug when you try -Wl,-Ttext-segment=0x100000000
with PDE. Linker can't help here.
On 27/05/24 11:38, H.J. Lu wrote:
> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> segment entries contain the relocated values for the load address.
> Compute the load address from the p_vaddr of the PT_LOAD segement
> which covers the file start. This fixes BZ #31799.
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
> configure | 67 ++++++++++++++++++++++++++++++++++++
> configure.ac | 30 ++++++++++++++++
> elf/Makefile | 20 +++++++++++
> elf/dl-reloc-static-pie.c | 25 ++++++++++----
> elf/tst-pie-address-static.c | 19 ++++++++++
> elf/tst-pie-address.c | 28 +++++++++++++++
> 6 files changed, 182 insertions(+), 7 deletions(-)
> create mode 100644 elf/tst-pie-address-static.c
> create mode 100644 elf/tst-pie-address.c
>
> diff --git a/configure b/configure
> index 49b093043c..612fa0cf77 100755
> --- a/configure
> +++ b/configure
> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
> config_vars="$config_vars
> cc-pie-default = $libc_cv_cc_pie_default"
>
> +# Get PDE load address.
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
> +printf %s "checking PDE load address... " >&6; }
> +if test ${libc_cv_pde_load_address+y}
> +then :
> + printf %s "(cached) " >&6
> +else $as_nop
> + cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> + pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> + -nostartfiles -nostdlib $no_ssp \
> + -o conftest conftest.S 1>&5 2>&5; then
> + # Get the load address of the first PT_LOAD segment.
> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> + | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> +fi
> +rm -f conftest*
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> +config_vars="$config_vars
> +pde-load-address = $libc_cv_pde_load_address"
> +
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> +libc_linker_feature=no
> +cat > conftest.c <<EOF
> +int _start (void) { return 42; }
> +EOF
> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> + -Wl,-Ttext-segment=$libc_cv_pde_load_address -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=$?
> + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; }
> +then
> + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
> + true
> + else
> + libc_linker_feature=yes
> + fi
> +fi
> +rm -f conftest*
> +if test $libc_linker_feature = yes; then
> + libc_cv_load_address=-Wl,-Ttext-segment
> +else
> + libc_cv_load_address=
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
> +printf "%s\n" "$libc_linker_feature" >&6; }
> +config_vars="$config_vars
> +load-address-ldflag = $libc_cv_load_address"
> +
> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
> printf %s "checking if we can build programs as PIE... " >&6; }
> cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> diff --git a/configure.ac b/configure.ac
> index e48957f318..89a2f5d842 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1721,6 +1721,36 @@ fi
> rm -f conftest.*])
> LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>
> +# Get PDE load address.
> +AC_CACHE_CHECK([PDE load address],
> + libc_cv_pde_load_address, [dnl
> +cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> + pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> + -nostartfiles -nostdlib $no_ssp \
> + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
> + # Get the load address of the first PT_LOAD segment.
> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> + | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> + AC_MSG_ERROR([${CC-cc} can not create PDE])
> +fi
> +rm -f conftest*])
> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
This does seems to work on ARM, RISCV, nor on loongarch (the current
architectures that support static-pie):
aarch64-linux-gnu$ cat t.S
.globl _start
_start:
.globl __start
__start:
aarch64-linux-gnu$ aarch64-glibc-linux-gnu-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
aarch64-linux-gnu$ aarch64-glibc-linux-gnu-readelf -Wl t
There are no program headers in this file.
$ aarch64-glibc-linux-gnu-ld -v
GNU ld (GNU Binutils) 2.42.0.20240312
armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-readelf -Wl -t
There are no program headers in this file.
armv7a-linux-gnueabihf$ arm-glibc-linux-ld -v
GNU ld (GNU Binutils) 2.42.0.20240312
I am not sure why BFD is not creating programs headers for this scenario,
but this makes the test innefective on these architectures.
> +
> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> + [libc_cv_load_address=-Wl,-Ttext-segment],
> + [libc_cv_load_address=])
> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> +
> AC_MSG_CHECKING(if we can build programs as PIE)
> AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> # error PIE is not supported
> diff --git a/elf/Makefile b/elf/Makefile
> index 57b3a19d36..4e2d123b8e 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -1046,6 +1046,25 @@ tests-pie += \
> tst-pie1 \
> tst-pie2 \
> # tests-pie
> +ifneq (,$(load-address-ldflag))
> +tests += \
> + tst-pie-address \
> + # tests
> +tests-pie += \
> + tst-pie-address \
> + # tests-pie
> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> +ifeq (yes,$(enable-static-pie))
> +tests += \
> + tst-pie-address-static \
> + # tests
> +tests-static += \
> + tst-pie-address-static \
> + # tests-static
> +LDFLAGS-tst-pie-address-static += \
> + $(load-address-ldflag)=$(pde-load-address)
> +endif
> +endif
For the tst-pie-address-static test (where although is set as ET_EXEC, still has
DF_1_PIE) will the kernel always enforce the loading address set by -Wl,-Ttext-segment
or it might eventually take this just a hint and thus creating a possible false negative
in the future?
And reading all the discussion on BZ#31795, I am not really convinced that setting
ET_EXEC for a static-pie with a defined loading address makes much sense (even though
it tried to overcome a kernel limitation), specially that BFD seems to be only linker
that does it. Maybe we should check with the kernel so it can enforce the loading
address for DF_1_PIE instead of trying the ET_EXEC hack.
> ifeq (yes,$(have-protected-data))
> tests += vismain
> tests-pie += vismain
> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
>
> CFLAGS-tst-pie1.c += $(pie-ccflag)
> CFLAGS-tst-pie2.c += $(pie-ccflag)
> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>
> $(objpfx)tst-piemod1.so: $(libsupport)
> $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> index 10c23d0bf0..6286f19f1f 100644
> --- a/elf/dl-reloc-static-pie.c
> +++ b/elf/dl-reloc-static-pie.c
> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> {
> struct link_map *main_map = _dl_get_dl_main_map ();
>
> - /* Figure out the run-time load address of static PIE. */
> - main_map->l_addr = elf_machine_load_address ();
> -
> - /* Read our own dynamic section and fill in the info array. */
> - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> -
> + ElfW(Addr) file_p_vaddr = 0;
> const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> size_t phnum = GL(dl_phnum);
> for (ph = phdr; ph < &phdr[phnum]; ++ph)
> - if (ph->p_type == PT_DYNAMIC)
> + switch (ph->p_type)
> {
> + case PT_LOAD:
> + /* Get p_vaddr of the PT_LOAD segement which covers the file
> + start. */
> + if (ph->p_offset == 0)
> + file_p_vaddr = ph->p_vaddr;
> + break;
> + case PT_DYNAMIC:
> main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> break;
> + default:
> + break;
> }
>
> + /* Figure out the run-time load address of static PIE. */
> + ElfW(Addr) l_addr = elf_machine_load_address ();
> + main_map->l_addr = l_addr - file_p_vaddr;
> +
> + /* Read our own dynamic section and fill in the info array. */
> + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> +
> elf_get_dynamic_info (main_map, false, true);
>
> # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> new file mode 100644
> index 0000000000..25d27fb962
> --- /dev/null
> +++ b/elf/tst-pie-address-static.c
> @@ -0,0 +1,19 @@
> +/* Test static PIE loaded at the specific address.
> + Copyright (C) 2024 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include "tst-pie-address.c"
> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> new file mode 100644
> index 0000000000..1f01783631
> --- /dev/null
> +++ b/elf/tst-pie-address.c
> @@ -0,0 +1,28 @@
> +/* Test PIE loaded at the specific address.
> + Copyright (C) 2024 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <stdio.h>
> +
> +static int
> +do_test (void)
> +{
> + printf ("Hello\n");
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
On Tue, May 28, 2024 at 7:28 AM Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 27/05/24 11:38, H.J. Lu wrote:
> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> > segment entries contain the relocated values for the load address.
> > Compute the load address from the p_vaddr of the PT_LOAD segement
> > which covers the file start. This fixes BZ #31799.
> >
> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> > ---
> > configure | 67 ++++++++++++++++++++++++++++++++++++
> > configure.ac | 30 ++++++++++++++++
> > elf/Makefile | 20 +++++++++++
> > elf/dl-reloc-static-pie.c | 25 ++++++++++----
> > elf/tst-pie-address-static.c | 19 ++++++++++
> > elf/tst-pie-address.c | 28 +++++++++++++++
> > 6 files changed, 182 insertions(+), 7 deletions(-)
> > create mode 100644 elf/tst-pie-address-static.c
> > create mode 100644 elf/tst-pie-address.c
> >
> > diff --git a/configure b/configure
> > index 49b093043c..612fa0cf77 100755
> > --- a/configure
> > +++ b/configure
> > @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
> > config_vars="$config_vars
> > cc-pie-default = $libc_cv_cc_pie_default"
> >
> > +# Get PDE load address.
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
> > +printf %s "checking PDE load address... " >&6; }
> > +if test ${libc_cv_pde_load_address+y}
> > +then :
> > + printf %s "(cached) " >&6
> > +else $as_nop
> > + cat > conftest.S <<EOF
> > +.globl _start
> > +_start:
> > +.globl __start
> > +__start:
> > +EOF
> > +if test $libc_cv_cc_pie_default = yes; then
> > + pde_ld_flags="-no-pie"
> > +fi
> > +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> > + -nostartfiles -nostdlib $no_ssp \
> > + -o conftest conftest.S 1>&5 2>&5; then
> > + # Get the load address of the first PT_LOAD segment.
> > + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> > + | $AWK '/LOAD/ { print $3; exit 0; }')
> > +else
> > + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> > +fi
> > +rm -f conftest*
> > +fi
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
> > +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> > +config_vars="$config_vars
> > +pde-load-address = $libc_cv_pde_load_address"
> > +
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> > +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> > +libc_linker_feature=no
> > +cat > conftest.c <<EOF
> > +int _start (void) { return 42; }
> > +EOF
> > +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> > + -Wl,-Ttext-segment=$libc_cv_pde_load_address -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=$?
> > + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> > + test $ac_status = 0; }; }
> > +then
> > + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> > + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> > + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
> > + true
> > + else
> > + libc_linker_feature=yes
> > + fi
> > +fi
> > +rm -f conftest*
> > +if test $libc_linker_feature = yes; then
> > + libc_cv_load_address=-Wl,-Ttext-segment
> > +else
> > + libc_cv_load_address=
> > +fi
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
> > +printf "%s\n" "$libc_linker_feature" >&6; }
> > +config_vars="$config_vars
> > +load-address-ldflag = $libc_cv_load_address"
> > +
> > { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
> > printf %s "checking if we can build programs as PIE... " >&6; }
> > cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> > diff --git a/configure.ac b/configure.ac
> > index e48957f318..89a2f5d842 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -1721,6 +1721,36 @@ fi
> > rm -f conftest.*])
> > LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
> >
> > +# Get PDE load address.
> > +AC_CACHE_CHECK([PDE load address],
> > + libc_cv_pde_load_address, [dnl
> > +cat > conftest.S <<EOF
> > +.globl _start
> > +_start:
> > +.globl __start
> > +__start:
> > +EOF
> > +if test $libc_cv_cc_pie_default = yes; then
> > + pde_ld_flags="-no-pie"
> > +fi
> > +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> > + -nostartfiles -nostdlib $no_ssp \
> > + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
> > + # Get the load address of the first PT_LOAD segment.
> > + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> > + | $AWK '/LOAD/ { print $3; exit 0; }')
> > +else
> > + AC_MSG_ERROR([${CC-cc} can not create PDE])
> > +fi
> > +rm -f conftest*])
> > +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>
> This does seems to work on ARM, RISCV, nor on loongarch (the current
> architectures that support static-pie):
>
> aarch64-linux-gnu$ cat t.S
> .globl _start
> _start:
> .globl __start
> __start:
> aarch64-linux-gnu$ aarch64-glibc-linux-gnu-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
> aarch64-linux-gnu$ aarch64-glibc-linux-gnu-readelf -Wl t
>
> There are no program headers in this file.
> $ aarch64-glibc-linux-gnu-ld -v
> GNU ld (GNU Binutils) 2.42.0.20240312
>
> armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
> armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-readelf -Wl -t
>
> There are no program headers in this file.
> armv7a-linux-gnueabihf$ arm-glibc-linux-ld -v
> GNU ld (GNU Binutils) 2.42.0.20240312
>
> I am not sure why BFD is not creating programs headers for this scenario,
> but this makes the test innefective on these architectures.
>
> > +
> > +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> > + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> > + [libc_cv_load_address=-Wl,-Ttext-segment],
> > + [libc_cv_load_address=])
> > +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> > +
> > AC_MSG_CHECKING(if we can build programs as PIE)
> > AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> > # error PIE is not supported
> > diff --git a/elf/Makefile b/elf/Makefile
> > index 57b3a19d36..4e2d123b8e 100644
> > --- a/elf/Makefile
> > +++ b/elf/Makefile
> > @@ -1046,6 +1046,25 @@ tests-pie += \
> > tst-pie1 \
> > tst-pie2 \
> > # tests-pie
> > +ifneq (,$(load-address-ldflag))
> > +tests += \
> > + tst-pie-address \
> > + # tests
> > +tests-pie += \
> > + tst-pie-address \
> > + # tests-pie
> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> > +ifeq (yes,$(enable-static-pie))
> > +tests += \
> > + tst-pie-address-static \
> > + # tests
> > +tests-static += \
> > + tst-pie-address-static \
> > + # tests-static
> > +LDFLAGS-tst-pie-address-static += \
> > + $(load-address-ldflag)=$(pde-load-address)
> > +endif
> > +endif
>
>
> For the tst-pie-address-static test (where although is set as ET_EXEC, still has
> DF_1_PIE) will the kernel always enforce the loading address set by -Wl,-Ttext-segment
> or it might eventually take this just a hint and thus creating a possible false negative
> in the future?
Kernel will guarantee PT_LOAD segment p_vaddr for ET_EXEC. For ET_DYN,
kernel may load ET_DYN at some random address. ET_EXEC is the only way
to always load a small model binary above 4G.
> And reading all the discussion on BZ#31795, I am not really convinced that setting
> ET_EXEC for a static-pie with a defined loading address makes much sense (even though
Without ET_EXEC, you don't know if a binary will be loaded at the
specific address.
> it tried to overcome a kernel limitation), specially that BFD seems to be only linker
> that does it. Maybe we should check with the kernel so it can enforce the loading
> address for DF_1_PIE instead of trying the ET_EXEC hack.
>
> > ifeq (yes,$(have-protected-data))
> > tests += vismain
> > tests-pie += vismain
> > @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
> >
> > CFLAGS-tst-pie1.c += $(pie-ccflag)
> > CFLAGS-tst-pie2.c += $(pie-ccflag)
> > +CFLAGS-tst-pie-address.c += $(pie-ccflag)
> >
> > $(objpfx)tst-piemod1.so: $(libsupport)
> > $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> > diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> > index 10c23d0bf0..6286f19f1f 100644
> > --- a/elf/dl-reloc-static-pie.c
> > +++ b/elf/dl-reloc-static-pie.c
> > @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> > {
> > struct link_map *main_map = _dl_get_dl_main_map ();
> >
> > - /* Figure out the run-time load address of static PIE. */
> > - main_map->l_addr = elf_machine_load_address ();
> > -
> > - /* Read our own dynamic section and fill in the info array. */
> > - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> > -
> > + ElfW(Addr) file_p_vaddr = 0;
> > const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> > size_t phnum = GL(dl_phnum);
> > for (ph = phdr; ph < &phdr[phnum]; ++ph)
> > - if (ph->p_type == PT_DYNAMIC)
> > + switch (ph->p_type)
> > {
> > + case PT_LOAD:
> > + /* Get p_vaddr of the PT_LOAD segement which covers the file
> > + start. */
> > + if (ph->p_offset == 0)
> > + file_p_vaddr = ph->p_vaddr;
> > + break;
> > + case PT_DYNAMIC:
> > main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> > break;
> > + default:
> > + break;
> > }
> >
> > + /* Figure out the run-time load address of static PIE. */
> > + ElfW(Addr) l_addr = elf_machine_load_address ();
> > + main_map->l_addr = l_addr - file_p_vaddr;
> > +
> > + /* Read our own dynamic section and fill in the info array. */
> > + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> > +
> > elf_get_dynamic_info (main_map, false, true);
> >
> > # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> > diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> > new file mode 100644
> > index 0000000000..25d27fb962
> > --- /dev/null
> > +++ b/elf/tst-pie-address-static.c
> > @@ -0,0 +1,19 @@
> > +/* Test static PIE loaded at the specific address.
> > + Copyright (C) 2024 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
> > + <https://www.gnu.org/licenses/>. */
> > +
> > +#include "tst-pie-address.c"
> > diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> > new file mode 100644
> > index 0000000000..1f01783631
> > --- /dev/null
> > +++ b/elf/tst-pie-address.c
> > @@ -0,0 +1,28 @@
> > +/* Test PIE loaded at the specific address.
> > + Copyright (C) 2024 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
> > + <https://www.gnu.org/licenses/>. */
> > +
> > +#include <stdio.h>
> > +
> > +static int
> > +do_test (void)
> > +{
> > + printf ("Hello\n");
> > + return 0;
> > +}
> > +
> > +#include <support/test-driver.c>
* H. J. Lu:
> On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> > segment entries contain the relocated values for the load address.
>> > Compute the load address from the p_vaddr of the PT_LOAD segement
>> > which covers the file start. This fixes BZ #31799.
>>
>> A PIE loaded at a specific address is no longer PIE.
>>
>> I think this should work:
>>
>> cat > t.c <<EOF
>> #include <stdio.h>
>>
>> int
>> main (void)
>> {
>> puts ("Hello, world!");
>> }
>> EOF
>> ld --verbose | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
>> > ld.script
>> gcc -fpie -static -Wl,-T,ld.script t.c
>>
>> But it fails with:
>>
>> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
>> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
>> collect2: error: ld returned 1 exit status
>
> Did you mean?
>
> [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> function `_start':
> (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> relink with --no-relax
> /usr/local/bin/ld: final link failed
> collect2: error: ld returned 1 exit status
> [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> function `_start':
> (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> relink with --no-relax
> /usr/local/bin/ld: final link failed
> collect2: error: ld returned 1 exit status
> [hjl@gnu-cfl-3 tmp]$
Sort of, but I compiled with PIE as well.
> This no longer fits in the small model.
You need to *compile* as PIE. The link editor should be able to produce
a position-dependent executable that is loaded at an arbitrary address
from such relocatable input files. The small model and GOTPCREL still
work because the GOT is still less than 2 GiB away from the code. This
is just a linker limitation.
Thanks,
Florian
On Fri, Jun 14, 2024 at 12:36:30PM +0200, Florian Weimer wrote:
> * H. J. Lu:
>
> > On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * H. J. Lu:
> >>
> >> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> >> > segment entries contain the relocated values for the load address.
> >> > Compute the load address from the p_vaddr of the PT_LOAD segement
> >> > which covers the file start. This fixes BZ #31799.
> >>
> >> A PIE loaded at a specific address is no longer PIE.
> >>
> >> I think this should work:
> >>
> >> cat > t.c <<EOF
> >> #include <stdio.h>
> >>
> >> int
> >> main (void)
> >> {
> >> puts ("Hello, world!");
> >> }
> >> EOF
> >> ld --verbose | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> >> > ld.script
> >> gcc -fpie -static -Wl,-T,ld.script t.c
> >>
> >> But it fails with:
> >>
> >> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
> >> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
> >> collect2: error: ld returned 1 exit status
> >
> > Did you mean?
> >
> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> > function `_start':
> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> > relink with --no-relax
> > /usr/local/bin/ld: final link failed
> > collect2: error: ld returned 1 exit status
> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> > function `_start':
> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> > relink with --no-relax
> > /usr/local/bin/ld: final link failed
> > collect2: error: ld returned 1 exit status
> > [hjl@gnu-cfl-3 tmp]$
>
> Sort of, but I compiled with PIE as well.
>
> > This no longer fits in the small model.
>
> You need to *compile* as PIE. The link editor should be able to produce
> a position-dependent executable that is loaded at an arbitrary address
> from such relocatable input files. The small model and GOTPCREL still
> work because the GOT is still less than 2 GiB away from the code. This
> is just a linker limitation.
>
There are no large model *crt*.o nor .a files. The only way to create
a small model executable loaded at a specific address above 4GB is to
build it as PIE with non-zero load address and marked as ET_EXEC.
If you believe it is a linker issue, please open a linker bug.
H.J.
On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> segment entries contain the relocated values for the load address.
> Compute the load address from the p_vaddr of the PT_LOAD segement
> which covers the file start. This fixes BZ #31799.
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
> configure | 67 ++++++++++++++++++++++++++++++++++++
> configure.ac | 30 ++++++++++++++++
> elf/Makefile | 20 +++++++++++
> elf/dl-reloc-static-pie.c | 25 ++++++++++----
> elf/tst-pie-address-static.c | 19 ++++++++++
> elf/tst-pie-address.c | 28 +++++++++++++++
> 6 files changed, 182 insertions(+), 7 deletions(-)
> create mode 100644 elf/tst-pie-address-static.c
> create mode 100644 elf/tst-pie-address.c
>
> diff --git a/configure b/configure
> index 49b093043c..612fa0cf77 100755
> --- a/configure
> +++ b/configure
> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
> config_vars="$config_vars
> cc-pie-default = $libc_cv_cc_pie_default"
>
> +# Get PDE load address.
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address"
> >&5
> +printf %s "checking PDE load address... " >&6; }
> +if test ${libc_cv_pde_load_address+y}
> +then :
> + printf %s "(cached) " >&6
> +else $as_nop
> + cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> + pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> + -nostartfiles -nostdlib $no_ssp \
> + -o conftest conftest.S 1>&5 2>&5; then
> + # Get the load address of the first PT_LOAD segment.
> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> + | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> +fi
> +rm -f conftest*
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_cv_pde_load_address" >&5
> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> +config_vars="$config_vars
> +pde-load-address = $libc_cv_pde_load_address"
> +
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that
> supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> +printf %s "checking for linker that supports
> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> +libc_linker_feature=no
> +cat > conftest.c <<EOF
> +int _start (void) { return 42; }
> +EOF
> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> + -Wl,-Ttext-segment=$libc_cv_pde_load_address -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=$?
> + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; }
> +then
> + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored"
> > /dev/null 2>&1; then
> + true
> + else
> + libc_linker_feature=yes
> + fi
> +fi
> +rm -f conftest*
> +if test $libc_linker_feature = yes; then
> + libc_cv_load_address=-Wl,-Ttext-segment
> +else
> + libc_cv_load_address=
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_linker_feature" >&5
> +printf "%s\n" "$libc_linker_feature" >&6; }
> +config_vars="$config_vars
> +load-address-ldflag = $libc_cv_load_address"
> +
> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build
> programs as PIE" >&5
> printf %s "checking if we can build programs as PIE... " >&6; }
> cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> diff --git a/configure.ac b/configure.ac
> index e48957f318..89a2f5d842 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1721,6 +1721,36 @@ fi
> rm -f conftest.*])
> LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>
> +# Get PDE load address.
> +AC_CACHE_CHECK([PDE load address],
> + libc_cv_pde_load_address, [dnl
> +cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> + pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> + -nostartfiles -nostdlib $no_ssp \
> + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
> 2>&AS_MESSAGE_LOG_FD; then
> + # Get the load address of the first PT_LOAD segment.
> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> + | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> + AC_MSG_ERROR([${CC-cc} can not create PDE])
> +fi
> +rm -f conftest*])
> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
> +
> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> + [libc_cv_load_address=-Wl,-Ttext-segment],
> + [libc_cv_load_address=])
> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> +
> AC_MSG_CHECKING(if we can build programs as PIE)
> AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> # error PIE is not supported
> diff --git a/elf/Makefile b/elf/Makefile
> index 57b3a19d36..4e2d123b8e 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -1046,6 +1046,25 @@ tests-pie += \
> tst-pie1 \
> tst-pie2 \
> # tests-pie
> +ifneq (,$(load-address-ldflag))
> +tests += \
> + tst-pie-address \
> + # tests
> +tests-pie += \
> + tst-pie-address \
> + # tests-pie
> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> +ifeq (yes,$(enable-static-pie))
> +tests += \
> + tst-pie-address-static \
> + # tests
> +tests-static += \
> + tst-pie-address-static \
> + # tests-static
> +LDFLAGS-tst-pie-address-static += \
> + $(load-address-ldflag)=$(pde-load-address)
> +endif
> +endif
> ifeq (yes,$(have-protected-data))
> tests += vismain
> tests-pie += vismain
> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
> tst-array5-static.exp \
>
> CFLAGS-tst-pie1.c += $(pie-ccflag)
> CFLAGS-tst-pie2.c += $(pie-ccflag)
> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>
> $(objpfx)tst-piemod1.so: $(libsupport)
> $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> index 10c23d0bf0..6286f19f1f 100644
> --- a/elf/dl-reloc-static-pie.c
> +++ b/elf/dl-reloc-static-pie.c
> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> {
> struct link_map *main_map = _dl_get_dl_main_map ();
>
> - /* Figure out the run-time load address of static PIE. */
> - main_map->l_addr = elf_machine_load_address ();
> -
> - /* Read our own dynamic section and fill in the info array. */
> - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> -
> + ElfW(Addr) file_p_vaddr = 0;
> const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> size_t phnum = GL(dl_phnum);
> for (ph = phdr; ph < &phdr[phnum]; ++ph)
> - if (ph->p_type == PT_DYNAMIC)
> + switch (ph->p_type)
> {
> + case PT_LOAD:
> + /* Get p_vaddr of the PT_LOAD segement which covers the file
> + start. */
> + if (ph->p_offset == 0)
> + file_p_vaddr = ph->p_vaddr;
> + break;
> + case PT_DYNAMIC:
> main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> break;
> + default:
> + break;
> }
>
> + /* Figure out the run-time load address of static PIE. */
> + ElfW(Addr) l_addr = elf_machine_load_address ();
> + main_map->l_addr = l_addr - file_p_vaddr;
> +
> + /* Read our own dynamic section and fill in the info array. */
> + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> +
> elf_get_dynamic_info (main_map, false, true);
>
> # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> new file mode 100644
> index 0000000000..25d27fb962
> --- /dev/null
> +++ b/elf/tst-pie-address-static.c
> @@ -0,0 +1,19 @@
> +/* Test static PIE loaded at the specific address.
> + Copyright (C) 2024 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include "tst-pie-address.c"
> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> new file mode 100644
> index 0000000000..1f01783631
> --- /dev/null
> +++ b/elf/tst-pie-address.c
> @@ -0,0 +1,28 @@
> +/* Test PIE loaded at the specific address.
> + Copyright (C) 2024 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
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <stdio.h>
> +
> +static int
> +do_test (void)
> +{
> + printf ("Hello\n");
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
> --
> 2.45.1
>
Ping.
>
* H. J. Lu:
> On Fri, Jun 14, 2024 at 12:36:30PM +0200, Florian Weimer wrote:
>> * H. J. Lu:
>>
>> > On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
>> >>
>> >> * H. J. Lu:
>> >>
>> >> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> >> > segment entries contain the relocated values for the load address.
>> >> > Compute the load address from the p_vaddr of the PT_LOAD segement
>> >> > which covers the file start. This fixes BZ #31799.
>> >>
>> >> A PIE loaded at a specific address is no longer PIE.
>> >>
>> >> I think this should work:
>> >>
>> >> cat > t.c <<EOF
>> >> #include <stdio.h>
>> >>
>> >> int
>> >> main (void)
>> >> {
>> >> puts ("Hello, world!");
>> >> }
>> >> EOF
>> >> ld --verbose | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
>> >> > ld.script
>> >> gcc -fpie -static -Wl,-T,ld.script t.c
>> >>
>> >> But it fails with:
>> >>
>> >> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
>> >> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
>> >> collect2: error: ld returned 1 exit status
>> >
>> > Did you mean?
>> >
>> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
>> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
>> > function `_start':
>> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
>> > relink with --no-relax
>> > /usr/local/bin/ld: final link failed
>> > collect2: error: ld returned 1 exit status
>> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
>> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
>> > function `_start':
>> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
>> > relink with --no-relax
>> > /usr/local/bin/ld: final link failed
>> > collect2: error: ld returned 1 exit status
>> > [hjl@gnu-cfl-3 tmp]$
>>
>> Sort of, but I compiled with PIE as well.
>>
>> > This no longer fits in the small model.
>>
>> You need to *compile* as PIE. The link editor should be able to produce
>> a position-dependent executable that is loaded at an arbitrary address
>> from such relocatable input files. The small model and GOTPCREL still
>> work because the GOT is still less than 2 GiB away from the code. This
>> is just a linker limitation.
>>
>
> There are no large model *crt*.o nor .a files. The only way to create
> a small model executable loaded at a specific address above 4GB is to
> build it as PIE with non-zero load address and marked as ET_EXEC.
This works for me:
cat > t.c <<EOF
#include <stdio.h>
char *volatile s = "Hello, world!"; /* Force relocation. */
int
main (void)
{
printf ("%s at %p\n", s, s);
}
EOF
ld --verbose | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> ld.script
gcc -fpie -pie -Wl,-T,ld.script,--no-relax t.c
$ ./a.out
Hello, world! at 0x100002004
$ readelf -hW ./a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x100001050
Start of program headers: 64 (bytes into file)
Start of section headers: 14728 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 32
So it can be done, for dynamic linking.
My preference would still be to change the static non-PIE objects not to
use absolute 32-bit relocations, so that they can be used for this.
Rather than changing the PIE-specific objects to work with ET_EXEC
binaries, too.
Thanks,
Florian
On Tue, Jul 2, 2024, 1:22 AM Florian Weimer <fweimer@redhat.com> wrote:
> * H. J. Lu:
>
> > On Fri, Jun 14, 2024 at 12:36:30PM +0200, Florian Weimer wrote:
> >> * H. J. Lu:
> >>
> >> > On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com>
> wrote:
> >> >>
> >> >> * H. J. Lu:
> >> >>
> >> >> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> >> >> > segment entries contain the relocated values for the load address.
> >> >> > Compute the load address from the p_vaddr of the PT_LOAD segement
> >> >> > which covers the file start. This fixes BZ #31799.
> >> >>
> >> >> A PIE loaded at a specific address is no longer PIE.
> >> >>
> >> >> I think this should work:
> >> >>
> >> >> cat > t.c <<EOF
> >> >> #include <stdio.h>
> >> >>
> >> >> int
> >> >> main (void)
> >> >> {
> >> >> puts ("Hello, world!");
> >> >> }
> >> >> EOF
> >> >> ld --verbose | sed -n -e
> '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> >> >> > ld.script
> >> >> gcc -fpie -static -Wl,-T,ld.script t.c
> >> >>
> >> >> But it fails with:
> >> >>
> >> >> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> function `_start':
> >> >> (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> relink with --no-relax
> >> >> collect2: error: ld returned 1 exit status
> >> >
> >> > Did you mean?
> >> >
> >> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
> >> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> >> > function `_start':
> >> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> >> > relink with --no-relax
> >> > /usr/local/bin/ld: final link failed
> >> > collect2: error: ld returned 1 exit status
> >> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000 x.c
> >> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> >> > function `_start':
> >> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> >> > relink with --no-relax
> >> > /usr/local/bin/ld: final link failed
> >> > collect2: error: ld returned 1 exit status
> >> > [hjl@gnu-cfl-3 tmp]$
> >>
> >> Sort of, but I compiled with PIE as well.
> >>
> >> > This no longer fits in the small model.
> >>
> >> You need to *compile* as PIE. The link editor should be able to produce
> >> a position-dependent executable that is loaded at an arbitrary address
> >> from such relocatable input files. The small model and GOTPCREL still
> >> work because the GOT is still less than 2 GiB away from the code. This
> >> is just a linker limitation.
> >>
> >
> > There are no large model *crt*.o nor .a files. The only way to create
> > a small model executable loaded at a specific address above 4GB is to
> > build it as PIE with non-zero load address and marked as ET_EXEC.
>
> This works for me:
>
> cat > t.c <<EOF
> #include <stdio.h>
>
> char *volatile s = "Hello, world!"; /* Force relocation. */
>
> int
> main (void)
> {
> printf ("%s at %p\n", s, s);
> }
> EOF
> ld --verbose | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> > ld.script
> gcc -fpie -pie -Wl,-T,ld.script,--no-relax t.c
>
> $ ./a.out
> Hello, world! at 0x100002004
> $ readelf -hW ./a.out
> ELF Header:
> Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
> Class: ELF64
> Data: 2's complement, little endian
> Version: 1 (current)
> OS/ABI: UNIX - System V
> ABI Version: 0
> Type: EXEC (Executable file)
> Machine: Advanced Micro Devices X86-64
> Version: 0x1
> Entry point address: 0x100001050
> Start of program headers: 64 (bytes into file)
> Start of section headers: 14728 (bytes into file)
> Flags: 0x0
> Size of this header: 64 (bytes)
> Size of program headers: 56 (bytes)
> Number of program headers: 13
> Size of section headers: 64 (bytes)
> Number of section headers: 33
> Section header string table index: 32
>
> So it can be done, for dynamic linking.
>
Of course, PIE can be loaded above 4GB. But this is unrelated to my glibc
patch,
which applies to both ET_DYN and ET_EXEC.
The reason for ET_EXEC is that the non zero load address in ET_DYN is a hint
and kernel may ignore it.
> My preference would still be to change the static non-PIE objects not to
> use absolute 32-bit relocations, so that they can be used for this.
> Rather than changing the PIE-specific objects to work with ET_EXEC
> binaries, too.
>
> Thanks,
> Florian
>
>
On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
>
> On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> segment entries contain the relocated values for the load address.
>> Compute the load address from the p_vaddr of the PT_LOAD segement
>> which covers the file start. This fixes BZ #31799.
>>
>> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>> ---
>> configure | 67 ++++++++++++++++++++++++++++++++++++
>> configure.ac | 30 ++++++++++++++++
>> elf/Makefile | 20 +++++++++++
>> elf/dl-reloc-static-pie.c | 25 ++++++++++----
>> elf/tst-pie-address-static.c | 19 ++++++++++
>> elf/tst-pie-address.c | 28 +++++++++++++++
>> 6 files changed, 182 insertions(+), 7 deletions(-)
>> create mode 100644 elf/tst-pie-address-static.c
>> create mode 100644 elf/tst-pie-address.c
>>
>> diff --git a/configure b/configure
>> index 49b093043c..612fa0cf77 100755
>> --- a/configure
>> +++ b/configure
>> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>> config_vars="$config_vars
>> cc-pie-default = $libc_cv_cc_pie_default"
>>
>> +# Get PDE load address.
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
>> +printf %s "checking PDE load address... " >&6; }
>> +if test ${libc_cv_pde_load_address+y}
>> +then :
>> + printf %s "(cached) " >&6
>> +else $as_nop
>> + cat > conftest.S <<EOF
>> +.globl _start
>> +_start:
>> +.globl __start
>> +__start:
>> +EOF
>> +if test $libc_cv_cc_pie_default = yes; then
>> + pde_ld_flags="-no-pie"
>> +fi
>> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> + -nostartfiles -nostdlib $no_ssp \
>> + -o conftest conftest.S 1>&5 2>&5; then
>> + # Get the load address of the first PT_LOAD segment.
>> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> + | $AWK '/LOAD/ { print $3; exit 0; }')
>> +else
>> + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>> +fi
>> +rm -f conftest*
>> +fi
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
>> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>> +config_vars="$config_vars
>> +pde-load-address = $libc_cv_pde_load_address"
>> +
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>> +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>> +libc_linker_feature=no
>> +cat > conftest.c <<EOF
>> +int _start (void) { return 42; }
>> +EOF
>> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>> + -Wl,-Ttext-segment=$libc_cv_pde_load_address -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=$?
>> + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>> + test $ac_status = 0; }; }
>> +then
>> + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>> + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>> + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
>> + true
>> + else
>> + libc_linker_feature=yes
>> + fi
>> +fi
>> +rm -f conftest*
>> +if test $libc_linker_feature = yes; then
>> + libc_cv_load_address=-Wl,-Ttext-segment
>> +else
>> + libc_cv_load_address=
>> +fi
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
>> +printf "%s\n" "$libc_linker_feature" >&6; }
>> +config_vars="$config_vars
>> +load-address-ldflag = $libc_cv_load_address"
>> +
>> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
>> printf %s "checking if we can build programs as PIE... " >&6; }
>> cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>> diff --git a/configure.ac b/configure.ac
>> index e48957f318..89a2f5d842 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -1721,6 +1721,36 @@ fi
>> rm -f conftest.*])
>> LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>>
>> +# Get PDE load address.
>> +AC_CACHE_CHECK([PDE load address],
>> + libc_cv_pde_load_address, [dnl
>> +cat > conftest.S <<EOF
>> +.globl _start
>> +_start:
>> +.globl __start
>> +__start:
>> +EOF
>> +if test $libc_cv_cc_pie_default = yes; then
>> + pde_ld_flags="-no-pie"
>> +fi
>> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> + -nostartfiles -nostdlib $no_ssp \
>> + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
>> + # Get the load address of the first PT_LOAD segment.
>> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> + | $AWK '/LOAD/ { print $3; exit 0; }')
>> +else
>> + AC_MSG_ERROR([${CC-cc} can not create PDE])
>> +fi
>> +rm -f conftest*])
>> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>> +
>> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>> + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>> + [libc_cv_load_address=-Wl,-Ttext-segment],
>> + [libc_cv_load_address=])
>> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>> +
>> AC_MSG_CHECKING(if we can build programs as PIE)
>> AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>> # error PIE is not supported
>> diff --git a/elf/Makefile b/elf/Makefile
>> index 57b3a19d36..4e2d123b8e 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -1046,6 +1046,25 @@ tests-pie += \
>> tst-pie1 \
>> tst-pie2 \
>> # tests-pie
>> +ifneq (,$(load-address-ldflag))
>> +tests += \
>> + tst-pie-address \
>> + # tests
>> +tests-pie += \
>> + tst-pie-address \
>> + # tests-pie
>> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>> +ifeq (yes,$(enable-static-pie))
>> +tests += \
>> + tst-pie-address-static \
>> + # tests
>> +tests-static += \
>> + tst-pie-address-static \
>> + # tests-static
>> +LDFLAGS-tst-pie-address-static += \
>> + $(load-address-ldflag)=$(pde-load-address)
>> +endif
>> +endif
>> ifeq (yes,$(have-protected-data))
>> tests += vismain
>> tests-pie += vismain
>> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
>>
>> CFLAGS-tst-pie1.c += $(pie-ccflag)
>> CFLAGS-tst-pie2.c += $(pie-ccflag)
>> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>>
>> $(objpfx)tst-piemod1.so: $(libsupport)
>> $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>> index 10c23d0bf0..6286f19f1f 100644
>> --- a/elf/dl-reloc-static-pie.c
>> +++ b/elf/dl-reloc-static-pie.c
>> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>> {
>> struct link_map *main_map = _dl_get_dl_main_map ();
>>
>> - /* Figure out the run-time load address of static PIE. */
>> - main_map->l_addr = elf_machine_load_address ();
>> -
>> - /* Read our own dynamic section and fill in the info array. */
>> - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
>> -
>> + ElfW(Addr) file_p_vaddr = 0;
>> const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>> size_t phnum = GL(dl_phnum);
>> for (ph = phdr; ph < &phdr[phnum]; ++ph)
>> - if (ph->p_type == PT_DYNAMIC)
>> + switch (ph->p_type)
>> {
>> + case PT_LOAD:
>> + /* Get p_vaddr of the PT_LOAD segement which covers the file
>> + start. */
>> + if (ph->p_offset == 0)
>> + file_p_vaddr = ph->p_vaddr;
>> + break;
>> + case PT_DYNAMIC:
>> main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>> break;
>> + default:
>> + break;
>> }
>>
>> + /* Figure out the run-time load address of static PIE. */
>> + ElfW(Addr) l_addr = elf_machine_load_address ();
>> + main_map->l_addr = l_addr - file_p_vaddr;
>> +
>> + /* Read our own dynamic section and fill in the info array. */
>> + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>> +
>> elf_get_dynamic_info (main_map, false, true);
>>
>> # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
>> new file mode 100644
>> index 0000000000..25d27fb962
>> --- /dev/null
>> +++ b/elf/tst-pie-address-static.c
>> @@ -0,0 +1,19 @@
>> +/* Test static PIE loaded at the specific address.
>> + Copyright (C) 2024 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
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include "tst-pie-address.c"
>> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>> new file mode 100644
>> index 0000000000..1f01783631
>> --- /dev/null
>> +++ b/elf/tst-pie-address.c
>> @@ -0,0 +1,28 @@
>> +/* Test PIE loaded at the specific address.
>> + Copyright (C) 2024 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
>> + <https://www.gnu.org/licenses/>. */
>> +
>> +#include <stdio.h>
>> +
>> +static int
>> +do_test (void)
>> +{
>> + printf ("Hello\n");
>> + return 0;
>> +}
>> +
>> +#include <support/test-driver.c>
>> --
>> 2.45.1
>
>
> Ping.
>
PING.
On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> >
> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>
> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> >> segment entries contain the relocated values for the load address.
> >> Compute the load address from the p_vaddr of the PT_LOAD segement
> >> which covers the file start. This fixes BZ #31799.
> >>
> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> >> ---
> >> configure | 67 ++++++++++++++++++++++++++++++++++++
> >> configure.ac | 30 ++++++++++++++++
> >> elf/Makefile | 20 +++++++++++
> >> elf/dl-reloc-static-pie.c | 25 ++++++++++----
> >> elf/tst-pie-address-static.c | 19 ++++++++++
> >> elf/tst-pie-address.c | 28 +++++++++++++++
> >> 6 files changed, 182 insertions(+), 7 deletions(-)
> >> create mode 100644 elf/tst-pie-address-static.c
> >> create mode 100644 elf/tst-pie-address.c
> >>
> >> diff --git a/configure b/configure
> >> index 49b093043c..612fa0cf77 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
> >> config_vars="$config_vars
> >> cc-pie-default = $libc_cv_cc_pie_default"
> >>
> >> +# Get PDE load address.
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load
> address" >&5
> >> +printf %s "checking PDE load address... " >&6; }
> >> +if test ${libc_cv_pde_load_address+y}
> >> +then :
> >> + printf %s "(cached) " >&6
> >> +else $as_nop
> >> + cat > conftest.S <<EOF
> >> +.globl _start
> >> +_start:
> >> +.globl __start
> >> +__start:
> >> +EOF
> >> +if test $libc_cv_cc_pie_default = yes; then
> >> + pde_ld_flags="-no-pie"
> >> +fi
> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> >> + -nostartfiles -nostdlib $no_ssp \
> >> + -o conftest conftest.S 1>&5 2>&5; then
> >> + # Get the load address of the first PT_LOAD segment.
> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
> >> +else
> >> + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> >> +fi
> >> +rm -f conftest*
> >> +fi
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_cv_pde_load_address" >&5
> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> >> +config_vars="$config_vars
> >> +pde-load-address = $libc_cv_pde_load_address"
> >> +
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that
> supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> >> +printf %s "checking for linker that supports
> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> >> +libc_linker_feature=no
> >> +cat > conftest.c <<EOF
> >> +int _start (void) { return 42; }
> >> +EOF
> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> >> + -Wl,-Ttext-segment=$libc_cv_pde_load_address
> -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=$?
> >> + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> >> + test $ac_status = 0; }; }
> >> +then
> >> + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> >> + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> >> + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address
> ignored" > /dev/null 2>&1; then
> >> + true
> >> + else
> >> + libc_linker_feature=yes
> >> + fi
> >> +fi
> >> +rm -f conftest*
> >> +if test $libc_linker_feature = yes; then
> >> + libc_cv_load_address=-Wl,-Ttext-segment
> >> +else
> >> + libc_cv_load_address=
> >> +fi
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_linker_feature" >&5
> >> +printf "%s\n" "$libc_linker_feature" >&6; }
> >> +config_vars="$config_vars
> >> +load-address-ldflag = $libc_cv_load_address"
> >> +
> >> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build
> programs as PIE" >&5
> >> printf %s "checking if we can build programs as PIE... " >&6; }
> >> cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> >> diff --git a/configure.ac b/configure.ac
> >> index e48957f318..89a2f5d842 100644
> >> --- a/configure.ac
> >> +++ b/configure.ac
> >> @@ -1721,6 +1721,36 @@ fi
> >> rm -f conftest.*])
> >> LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
> >>
> >> +# Get PDE load address.
> >> +AC_CACHE_CHECK([PDE load address],
> >> + libc_cv_pde_load_address, [dnl
> >> +cat > conftest.S <<EOF
> >> +.globl _start
> >> +_start:
> >> +.globl __start
> >> +__start:
> >> +EOF
> >> +if test $libc_cv_cc_pie_default = yes; then
> >> + pde_ld_flags="-no-pie"
> >> +fi
> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> >> + -nostartfiles -nostdlib $no_ssp \
> >> + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
> 2>&AS_MESSAGE_LOG_FD; then
> >> + # Get the load address of the first PT_LOAD segment.
> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
> >> +else
> >> + AC_MSG_ERROR([${CC-cc} can not create PDE])
> >> +fi
> >> +rm -f conftest*])
> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
> >> +
> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> >> + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> >> + [libc_cv_load_address=-Wl,-Ttext-segment],
> >> + [libc_cv_load_address=])
> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> >> +
> >> AC_MSG_CHECKING(if we can build programs as PIE)
> >> AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> >> # error PIE is not supported
> >> diff --git a/elf/Makefile b/elf/Makefile
> >> index 57b3a19d36..4e2d123b8e 100644
> >> --- a/elf/Makefile
> >> +++ b/elf/Makefile
> >> @@ -1046,6 +1046,25 @@ tests-pie += \
> >> tst-pie1 \
> >> tst-pie2 \
> >> # tests-pie
> >> +ifneq (,$(load-address-ldflag))
> >> +tests += \
> >> + tst-pie-address \
> >> + # tests
> >> +tests-pie += \
> >> + tst-pie-address \
> >> + # tests-pie
> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> >> +ifeq (yes,$(enable-static-pie))
> >> +tests += \
> >> + tst-pie-address-static \
> >> + # tests
> >> +tests-static += \
> >> + tst-pie-address-static \
> >> + # tests-static
> >> +LDFLAGS-tst-pie-address-static += \
> >> + $(load-address-ldflag)=$(pde-load-address)
> >> +endif
> >> +endif
> >> ifeq (yes,$(have-protected-data))
> >> tests += vismain
> >> tests-pie += vismain
> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
> tst-array5-static.exp \
> >>
> >> CFLAGS-tst-pie1.c += $(pie-ccflag)
> >> CFLAGS-tst-pie2.c += $(pie-ccflag)
> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
> >>
> >> $(objpfx)tst-piemod1.so: $(libsupport)
> >> $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> >> index 10c23d0bf0..6286f19f1f 100644
> >> --- a/elf/dl-reloc-static-pie.c
> >> +++ b/elf/dl-reloc-static-pie.c
> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> >> {
> >> struct link_map *main_map = _dl_get_dl_main_map ();
> >>
> >> - /* Figure out the run-time load address of static PIE. */
> >> - main_map->l_addr = elf_machine_load_address ();
> >> -
> >> - /* Read our own dynamic section and fill in the info array. */
> >> - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic
> ());
> >> -
> >> + ElfW(Addr) file_p_vaddr = 0;
> >> const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> >> size_t phnum = GL(dl_phnum);
> >> for (ph = phdr; ph < &phdr[phnum]; ++ph)
> >> - if (ph->p_type == PT_DYNAMIC)
> >> + switch (ph->p_type)
> >> {
> >> + case PT_LOAD:
> >> + /* Get p_vaddr of the PT_LOAD segement which covers the file
> >> + start. */
> >> + if (ph->p_offset == 0)
> >> + file_p_vaddr = ph->p_vaddr;
> >> + break;
> >> + case PT_DYNAMIC:
> >> main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> >> break;
> >> + default:
> >> + break;
> >> }
> >>
> >> + /* Figure out the run-time load address of static PIE. */
> >> + ElfW(Addr) l_addr = elf_machine_load_address ();
> >> + main_map->l_addr = l_addr - file_p_vaddr;
> >> +
> >> + /* Read our own dynamic section and fill in the info array. */
> >> + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> >> +
> >> elf_get_dynamic_info (main_map, false, true);
> >>
> >> # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> >> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> >> new file mode 100644
> >> index 0000000000..25d27fb962
> >> --- /dev/null
> >> +++ b/elf/tst-pie-address-static.c
> >> @@ -0,0 +1,19 @@
> >> +/* Test static PIE loaded at the specific address.
> >> + Copyright (C) 2024 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
> >> + <https://www.gnu.org/licenses/>. */
> >> +
> >> +#include "tst-pie-address.c"
> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> >> new file mode 100644
> >> index 0000000000..1f01783631
> >> --- /dev/null
> >> +++ b/elf/tst-pie-address.c
> >> @@ -0,0 +1,28 @@
> >> +/* Test PIE loaded at the specific address.
> >> + Copyright (C) 2024 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
> >> + <https://www.gnu.org/licenses/>. */
> >> +
> >> +#include <stdio.h>
> >> +
> >> +static int
> >> +do_test (void)
> >> +{
> >> + printf ("Hello\n");
> >> + return 0;
> >> +}
> >> +
> >> +#include <support/test-driver.c>
> >> --
> >> 2.45.1
> >
> >
> > Ping.
> >
>
> PING.
>
PING.
> --
> H.J.
>
>
On Wed, Oct 2, 2024, 5:45 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
>> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >
>> >
>> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >>
>> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> >> segment entries contain the relocated values for the load address.
>> >> Compute the load address from the p_vaddr of the PT_LOAD segement
>> >> which covers the file start. This fixes BZ #31799.
>> >>
>> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>> >> ---
>> >> configure | 67 ++++++++++++++++++++++++++++++++++++
>> >> configure.ac | 30 ++++++++++++++++
>> >> elf/Makefile | 20 +++++++++++
>> >> elf/dl-reloc-static-pie.c | 25 ++++++++++----
>> >> elf/tst-pie-address-static.c | 19 ++++++++++
>> >> elf/tst-pie-address.c | 28 +++++++++++++++
>> >> 6 files changed, 182 insertions(+), 7 deletions(-)
>> >> create mode 100644 elf/tst-pie-address-static.c
>> >> create mode 100644 elf/tst-pie-address.c
>> >>
>> >> diff --git a/configure b/configure
>> >> index 49b093043c..612fa0cf77 100755
>> >> --- a/configure
>> >> +++ b/configure
>> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>> >> config_vars="$config_vars
>> >> cc-pie-default = $libc_cv_cc_pie_default"
>> >>
>> >> +# Get PDE load address.
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load
>> address" >&5
>> >> +printf %s "checking PDE load address... " >&6; }
>> >> +if test ${libc_cv_pde_load_address+y}
>> >> +then :
>> >> + printf %s "(cached) " >&6
>> >> +else $as_nop
>> >> + cat > conftest.S <<EOF
>> >> +.globl _start
>> >> +_start:
>> >> +.globl __start
>> >> +__start:
>> >> +EOF
>> >> +if test $libc_cv_cc_pie_default = yes; then
>> >> + pde_ld_flags="-no-pie"
>> >> +fi
>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> >> + -nostartfiles -nostdlib $no_ssp \
>> >> + -o conftest conftest.S 1>&5 2>&5; then
>> >> + # Get the load address of the first PT_LOAD segment.
>> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
>> >> +else
>> >> + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>> >> +fi
>> >> +rm -f conftest*
>> >> +fi
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>> $libc_cv_pde_load_address" >&5
>> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>> >> +config_vars="$config_vars
>> >> +pde-load-address = $libc_cv_pde_load_address"
>> >> +
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker
>> that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>> >> +printf %s "checking for linker that supports
>> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>> >> +libc_linker_feature=no
>> >> +cat > conftest.c <<EOF
>> >> +int _start (void) { return 42; }
>> >> +EOF
>> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>> >> + -Wl,-Ttext-segment=$libc_cv_pde_load_address
>> -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=$?
>> >> + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>> >> + test $ac_status = 0; }; }
>> >> +then
>> >> + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>> >> + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>> >> + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address
>> ignored" > /dev/null 2>&1; then
>> >> + true
>> >> + else
>> >> + libc_linker_feature=yes
>> >> + fi
>> >> +fi
>> >> +rm -f conftest*
>> >> +if test $libc_linker_feature = yes; then
>> >> + libc_cv_load_address=-Wl,-Ttext-segment
>> >> +else
>> >> + libc_cv_load_address=
>> >> +fi
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>> $libc_linker_feature" >&5
>> >> +printf "%s\n" "$libc_linker_feature" >&6; }
>> >> +config_vars="$config_vars
>> >> +load-address-ldflag = $libc_cv_load_address"
>> >> +
>> >> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can
>> build programs as PIE" >&5
>> >> printf %s "checking if we can build programs as PIE... " >&6; }
>> >> cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>> >> diff --git a/configure.ac b/configure.ac
>> >> index e48957f318..89a2f5d842 100644
>> >> --- a/configure.ac
>> >> +++ b/configure.ac
>> >> @@ -1721,6 +1721,36 @@ fi
>> >> rm -f conftest.*])
>> >> LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>> >>
>> >> +# Get PDE load address.
>> >> +AC_CACHE_CHECK([PDE load address],
>> >> + libc_cv_pde_load_address, [dnl
>> >> +cat > conftest.S <<EOF
>> >> +.globl _start
>> >> +_start:
>> >> +.globl __start
>> >> +__start:
>> >> +EOF
>> >> +if test $libc_cv_cc_pie_default = yes; then
>> >> + pde_ld_flags="-no-pie"
>> >> +fi
>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> >> + -nostartfiles -nostdlib $no_ssp \
>> >> + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
>> 2>&AS_MESSAGE_LOG_FD; then
>> >> + # Get the load address of the first PT_LOAD segment.
>> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
>> >> +else
>> >> + AC_MSG_ERROR([${CC-cc} can not create PDE])
>> >> +fi
>> >> +rm -f conftest*])
>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>> >> +
>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>> >> + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>> >> + [libc_cv_load_address=-Wl,-Ttext-segment],
>> >> + [libc_cv_load_address=])
>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>> >> +
>> >> AC_MSG_CHECKING(if we can build programs as PIE)
>> >> AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>> >> # error PIE is not supported
>> >> diff --git a/elf/Makefile b/elf/Makefile
>> >> index 57b3a19d36..4e2d123b8e 100644
>> >> --- a/elf/Makefile
>> >> +++ b/elf/Makefile
>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
>> >> tst-pie1 \
>> >> tst-pie2 \
>> >> # tests-pie
>> >> +ifneq (,$(load-address-ldflag))
>> >> +tests += \
>> >> + tst-pie-address \
>> >> + # tests
>> >> +tests-pie += \
>> >> + tst-pie-address \
>> >> + # tests-pie
>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>> >> +ifeq (yes,$(enable-static-pie))
>> >> +tests += \
>> >> + tst-pie-address-static \
>> >> + # tests
>> >> +tests-static += \
>> >> + tst-pie-address-static \
>> >> + # tests-static
>> >> +LDFLAGS-tst-pie-address-static += \
>> >> + $(load-address-ldflag)=$(pde-load-address)
>> >> +endif
>> >> +endif
>> >> ifeq (yes,$(have-protected-data))
>> >> tests += vismain
>> >> tests-pie += vismain
>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
>> tst-array5-static.exp \
>> >>
>> >> CFLAGS-tst-pie1.c += $(pie-ccflag)
>> >> CFLAGS-tst-pie2.c += $(pie-ccflag)
>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>> >>
>> >> $(objpfx)tst-piemod1.so: $(libsupport)
>> >> $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>> >> index 10c23d0bf0..6286f19f1f 100644
>> >> --- a/elf/dl-reloc-static-pie.c
>> >> +++ b/elf/dl-reloc-static-pie.c
>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>> >> {
>> >> struct link_map *main_map = _dl_get_dl_main_map ();
>> >>
>> >> - /* Figure out the run-time load address of static PIE. */
>> >> - main_map->l_addr = elf_machine_load_address ();
>> >> -
>> >> - /* Read our own dynamic section and fill in the info array. */
>> >> - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic
>> ());
>> >> -
>> >> + ElfW(Addr) file_p_vaddr = 0;
>> >> const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>> >> size_t phnum = GL(dl_phnum);
>> >> for (ph = phdr; ph < &phdr[phnum]; ++ph)
>> >> - if (ph->p_type == PT_DYNAMIC)
>> >> + switch (ph->p_type)
>> >> {
>> >> + case PT_LOAD:
>> >> + /* Get p_vaddr of the PT_LOAD segement which covers the file
>> >> + start. */
>> >> + if (ph->p_offset == 0)
>> >> + file_p_vaddr = ph->p_vaddr;
>> >> + break;
>> >> + case PT_DYNAMIC:
>> >> main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>> >> break;
>> >> + default:
>> >> + break;
>> >> }
>> >>
>> >> + /* Figure out the run-time load address of static PIE. */
>> >> + ElfW(Addr) l_addr = elf_machine_load_address ();
>> >> + main_map->l_addr = l_addr - file_p_vaddr;
>> >> +
>> >> + /* Read our own dynamic section and fill in the info array. */
>> >> + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>> >> +
>> >> elf_get_dynamic_info (main_map, false, true);
>> >>
>> >> # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>> >> diff --git a/elf/tst-pie-address-static.c
>> b/elf/tst-pie-address-static.c
>> >> new file mode 100644
>> >> index 0000000000..25d27fb962
>> >> --- /dev/null
>> >> +++ b/elf/tst-pie-address-static.c
>> >> @@ -0,0 +1,19 @@
>> >> +/* Test static PIE loaded at the specific address.
>> >> + Copyright (C) 2024 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
>> >> + <https://www.gnu.org/licenses/>. */
>> >> +
>> >> +#include "tst-pie-address.c"
>> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>> >> new file mode 100644
>> >> index 0000000000..1f01783631
>> >> --- /dev/null
>> >> +++ b/elf/tst-pie-address.c
>> >> @@ -0,0 +1,28 @@
>> >> +/* Test PIE loaded at the specific address.
>> >> + Copyright (C) 2024 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
>> >> + <https://www.gnu.org/licenses/>. */
>> >> +
>> >> +#include <stdio.h>
>> >> +
>> >> +static int
>> >> +do_test (void)
>> >> +{
>> >> + printf ("Hello\n");
>> >> + return 0;
>> >> +}
>> >> +
>> >> +#include <support/test-driver.c>
>> >> --
>> >> 2.45.1
>> >
>> >
>> > Ping.
>> >
>>
>> PING.
>>
>
> PING.
>
PING.
>
>> --
>> H.J.
>>
>>
>>
On Tue, Oct 8, 2024, 6:41 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> On Wed, Oct 2, 2024, 5:45 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
>> On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>>> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>> >
>>> >
>>> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>> >>
>>> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>>> >> segment entries contain the relocated values for the load address.
>>> >> Compute the load address from the p_vaddr of the PT_LOAD segement
>>> >> which covers the file start. This fixes BZ #31799.
>>> >>
>>> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>>> >> ---
>>> >> configure | 67
>>> ++++++++++++++++++++++++++++++++++++
>>> >> configure.ac | 30 ++++++++++++++++
>>> >> elf/Makefile | 20 +++++++++++
>>> >> elf/dl-reloc-static-pie.c | 25 ++++++++++----
>>> >> elf/tst-pie-address-static.c | 19 ++++++++++
>>> >> elf/tst-pie-address.c | 28 +++++++++++++++
>>> >> 6 files changed, 182 insertions(+), 7 deletions(-)
>>> >> create mode 100644 elf/tst-pie-address-static.c
>>> >> create mode 100644 elf/tst-pie-address.c
>>> >>
>>> >> diff --git a/configure b/configure
>>> >> index 49b093043c..612fa0cf77 100755
>>> >> --- a/configure
>>> >> +++ b/configure
>>> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>>> >> config_vars="$config_vars
>>> >> cc-pie-default = $libc_cv_cc_pie_default"
>>> >>
>>> >> +# Get PDE load address.
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load
>>> address" >&5
>>> >> +printf %s "checking PDE load address... " >&6; }
>>> >> +if test ${libc_cv_pde_load_address+y}
>>> >> +then :
>>> >> + printf %s "(cached) " >&6
>>> >> +else $as_nop
>>> >> + cat > conftest.S <<EOF
>>> >> +.globl _start
>>> >> +_start:
>>> >> +.globl __start
>>> >> +__start:
>>> >> +EOF
>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>> >> + pde_ld_flags="-no-pie"
>>> >> +fi
>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>> >> + -nostartfiles -nostdlib $no_ssp \
>>> >> + -o conftest conftest.S 1>&5 2>&5; then
>>> >> + # Get the load address of the first PT_LOAD segment.
>>> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
>>> >> +else
>>> >> + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>>> >> +fi
>>> >> +rm -f conftest*
>>> >> +fi
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>>> $libc_cv_pde_load_address" >&5
>>> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>>> >> +config_vars="$config_vars
>>> >> +pde-load-address = $libc_cv_pde_load_address"
>>> >> +
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker
>>> that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>>> >> +printf %s "checking for linker that supports
>>> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>>> >> +libc_linker_feature=no
>>> >> +cat > conftest.c <<EOF
>>> >> +int _start (void) { return 42; }
>>> >> +EOF
>>> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>>> >> + -Wl,-Ttext-segment=$libc_cv_pde_load_address
>>> -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=$?
>>> >> + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>>> >> + test $ac_status = 0; }; }
>>> >> +then
>>> >> + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>>> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>>> >> + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>>> >> + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address
>>> ignored" > /dev/null 2>&1; then
>>> >> + true
>>> >> + else
>>> >> + libc_linker_feature=yes
>>> >> + fi
>>> >> +fi
>>> >> +rm -f conftest*
>>> >> +if test $libc_linker_feature = yes; then
>>> >> + libc_cv_load_address=-Wl,-Ttext-segment
>>> >> +else
>>> >> + libc_cv_load_address=
>>> >> +fi
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>>> $libc_linker_feature" >&5
>>> >> +printf "%s\n" "$libc_linker_feature" >&6; }
>>> >> +config_vars="$config_vars
>>> >> +load-address-ldflag = $libc_cv_load_address"
>>> >> +
>>> >> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can
>>> build programs as PIE" >&5
>>> >> printf %s "checking if we can build programs as PIE... " >&6; }
>>> >> cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>>> >> diff --git a/configure.ac b/configure.ac
>>> >> index e48957f318..89a2f5d842 100644
>>> >> --- a/configure.ac
>>> >> +++ b/configure.ac
>>> >> @@ -1721,6 +1721,36 @@ fi
>>> >> rm -f conftest.*])
>>> >> LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>>> >>
>>> >> +# Get PDE load address.
>>> >> +AC_CACHE_CHECK([PDE load address],
>>> >> + libc_cv_pde_load_address, [dnl
>>> >> +cat > conftest.S <<EOF
>>> >> +.globl _start
>>> >> +_start:
>>> >> +.globl __start
>>> >> +__start:
>>> >> +EOF
>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>> >> + pde_ld_flags="-no-pie"
>>> >> +fi
>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>> >> + -nostartfiles -nostdlib $no_ssp \
>>> >> + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
>>> 2>&AS_MESSAGE_LOG_FD; then
>>> >> + # Get the load address of the first PT_LOAD segment.
>>> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
>>> >> +else
>>> >> + AC_MSG_ERROR([${CC-cc} can not create PDE])
>>> >> +fi
>>> >> +rm -f conftest*])
>>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>>> >> +
>>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>>> >> + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>>> >> + [libc_cv_load_address=-Wl,-Ttext-segment],
>>> >> + [libc_cv_load_address=])
>>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>>> >> +
>>> >> AC_MSG_CHECKING(if we can build programs as PIE)
>>> >> AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>>> >> # error PIE is not supported
>>> >> diff --git a/elf/Makefile b/elf/Makefile
>>> >> index 57b3a19d36..4e2d123b8e 100644
>>> >> --- a/elf/Makefile
>>> >> +++ b/elf/Makefile
>>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
>>> >> tst-pie1 \
>>> >> tst-pie2 \
>>> >> # tests-pie
>>> >> +ifneq (,$(load-address-ldflag))
>>> >> +tests += \
>>> >> + tst-pie-address \
>>> >> + # tests
>>> >> +tests-pie += \
>>> >> + tst-pie-address \
>>> >> + # tests-pie
>>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>>> >> +ifeq (yes,$(enable-static-pie))
>>> >> +tests += \
>>> >> + tst-pie-address-static \
>>> >> + # tests
>>> >> +tests-static += \
>>> >> + tst-pie-address-static \
>>> >> + # tests-static
>>> >> +LDFLAGS-tst-pie-address-static += \
>>> >> + $(load-address-ldflag)=$(pde-load-address)
>>> >> +endif
>>> >> +endif
>>> >> ifeq (yes,$(have-protected-data))
>>> >> tests += vismain
>>> >> tests-pie += vismain
>>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
>>> tst-array5-static.exp \
>>> >>
>>> >> CFLAGS-tst-pie1.c += $(pie-ccflag)
>>> >> CFLAGS-tst-pie2.c += $(pie-ccflag)
>>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>>> >>
>>> >> $(objpfx)tst-piemod1.so: $(libsupport)
>>> >> $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>>> >> index 10c23d0bf0..6286f19f1f 100644
>>> >> --- a/elf/dl-reloc-static-pie.c
>>> >> +++ b/elf/dl-reloc-static-pie.c
>>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>>> >> {
>>> >> struct link_map *main_map = _dl_get_dl_main_map ();
>>> >>
>>> >> - /* Figure out the run-time load address of static PIE. */
>>> >> - main_map->l_addr = elf_machine_load_address ();
>>> >> -
>>> >> - /* Read our own dynamic section and fill in the info array. */
>>> >> - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic
>>> ());
>>> >> -
>>> >> + ElfW(Addr) file_p_vaddr = 0;
>>> >> const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>>> >> size_t phnum = GL(dl_phnum);
>>> >> for (ph = phdr; ph < &phdr[phnum]; ++ph)
>>> >> - if (ph->p_type == PT_DYNAMIC)
>>> >> + switch (ph->p_type)
>>> >> {
>>> >> + case PT_LOAD:
>>> >> + /* Get p_vaddr of the PT_LOAD segement which covers the file
>>> >> + start. */
>>> >> + if (ph->p_offset == 0)
>>> >> + file_p_vaddr = ph->p_vaddr;
>>> >> + break;
>>> >> + case PT_DYNAMIC:
>>> >> main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>>> >> break;
>>> >> + default:
>>> >> + break;
>>> >> }
>>> >>
>>> >> + /* Figure out the run-time load address of static PIE. */
>>> >> + ElfW(Addr) l_addr = elf_machine_load_address ();
>>> >> + main_map->l_addr = l_addr - file_p_vaddr;
>>> >> +
>>> >> + /* Read our own dynamic section and fill in the info array. */
>>> >> + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>>> >> +
>>> >> elf_get_dynamic_info (main_map, false, true);
>>> >>
>>> >> # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>>> >> diff --git a/elf/tst-pie-address-static.c
>>> b/elf/tst-pie-address-static.c
>>> >> new file mode 100644
>>> >> index 0000000000..25d27fb962
>>> >> --- /dev/null
>>> >> +++ b/elf/tst-pie-address-static.c
>>> >> @@ -0,0 +1,19 @@
>>> >> +/* Test static PIE loaded at the specific address.
>>> >> + Copyright (C) 2024 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
>>> >> + <https://www.gnu.org/licenses/>. */
>>> >> +
>>> >> +#include "tst-pie-address.c"
>>> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>>> >> new file mode 100644
>>> >> index 0000000000..1f01783631
>>> >> --- /dev/null
>>> >> +++ b/elf/tst-pie-address.c
>>> >> @@ -0,0 +1,28 @@
>>> >> +/* Test PIE loaded at the specific address.
>>> >> + Copyright (C) 2024 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
>>> >> + <https://www.gnu.org/licenses/>. */
>>> >> +
>>> >> +#include <stdio.h>
>>> >> +
>>> >> +static int
>>> >> +do_test (void)
>>> >> +{
>>> >> + printf ("Hello\n");
>>> >> + return 0;
>>> >> +}
>>> >> +
>>> >> +#include <support/test-driver.c>
>>> >> --
>>> >> 2.45.1
>>> >
>>> >
>>> > Ping.
>>> >
>>>
>>> PING.
>>>
>>
>> PING.
>>
>
> PING.
>
PING.
>
>>
>>> --
>>> H.J.
>>>
>>>
>>>
>>>
On Mon, Oct 21, 2024 at 4:51 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Oct 8, 2024, 6:41 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Wed, Oct 2, 2024, 5:45 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>
>>> On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>>
>>>> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>> >
>>>> >
>>>> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>> >>
>>>> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>>>> >> segment entries contain the relocated values for the load address.
>>>> >> Compute the load address from the p_vaddr of the PT_LOAD segement
>>>> >> which covers the file start. This fixes BZ #31799.
>>>> >>
>>>> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>>>> >> ---
>>>> >> configure | 67 ++++++++++++++++++++++++++++++++++++
>>>> >> configure.ac | 30 ++++++++++++++++
>>>> >> elf/Makefile | 20 +++++++++++
>>>> >> elf/dl-reloc-static-pie.c | 25 ++++++++++----
>>>> >> elf/tst-pie-address-static.c | 19 ++++++++++
>>>> >> elf/tst-pie-address.c | 28 +++++++++++++++
>>>> >> 6 files changed, 182 insertions(+), 7 deletions(-)
>>>> >> create mode 100644 elf/tst-pie-address-static.c
>>>> >> create mode 100644 elf/tst-pie-address.c
>>>> >>
>>>> >> diff --git a/configure b/configure
>>>> >> index 49b093043c..612fa0cf77 100755
>>>> >> --- a/configure
>>>> >> +++ b/configure
>>>> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>>>> >> config_vars="$config_vars
>>>> >> cc-pie-default = $libc_cv_cc_pie_default"
>>>> >>
>>>> >> +# Get PDE load address.
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
>>>> >> +printf %s "checking PDE load address... " >&6; }
>>>> >> +if test ${libc_cv_pde_load_address+y}
>>>> >> +then :
>>>> >> + printf %s "(cached) " >&6
>>>> >> +else $as_nop
>>>> >> + cat > conftest.S <<EOF
>>>> >> +.globl _start
>>>> >> +_start:
>>>> >> +.globl __start
>>>> >> +__start:
>>>> >> +EOF
>>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>>> >> + pde_ld_flags="-no-pie"
>>>> >> +fi
>>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>>> >> + -nostartfiles -nostdlib $no_ssp \
>>>> >> + -o conftest conftest.S 1>&5 2>&5; then
>>>> >> + # Get the load address of the first PT_LOAD segment.
>>>> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>>> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
>>>> >> +else
>>>> >> + as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>>>> >> +fi
>>>> >> +rm -f conftest*
>>>> >> +fi
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
>>>> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>>>> >> +config_vars="$config_vars
>>>> >> +pde-load-address = $libc_cv_pde_load_address"
>>>> >> +
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>>>> >> +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>>>> >> +libc_linker_feature=no
>>>> >> +cat > conftest.c <<EOF
>>>> >> +int _start (void) { return 42; }
>>>> >> +EOF
>>>> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>>>> >> + -Wl,-Ttext-segment=$libc_cv_pde_load_address -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=$?
>>>> >> + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>>>> >> + test $ac_status = 0; }; }
>>>> >> +then
>>>> >> + if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>>>> >> + -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>>>> >> + | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
>>>> >> + true
>>>> >> + else
>>>> >> + libc_linker_feature=yes
>>>> >> + fi
>>>> >> +fi
>>>> >> +rm -f conftest*
>>>> >> +if test $libc_linker_feature = yes; then
>>>> >> + libc_cv_load_address=-Wl,-Ttext-segment
>>>> >> +else
>>>> >> + libc_cv_load_address=
>>>> >> +fi
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
>>>> >> +printf "%s\n" "$libc_linker_feature" >&6; }
>>>> >> +config_vars="$config_vars
>>>> >> +load-address-ldflag = $libc_cv_load_address"
>>>> >> +
>>>> >> { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
>>>> >> printf %s "checking if we can build programs as PIE... " >&6; }
>>>> >> cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>>>> >> diff --git a/configure.ac b/configure.ac
>>>> >> index e48957f318..89a2f5d842 100644
>>>> >> --- a/configure.ac
>>>> >> +++ b/configure.ac
>>>> >> @@ -1721,6 +1721,36 @@ fi
>>>> >> rm -f conftest.*])
>>>> >> LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>>>> >>
>>>> >> +# Get PDE load address.
>>>> >> +AC_CACHE_CHECK([PDE load address],
>>>> >> + libc_cv_pde_load_address, [dnl
>>>> >> +cat > conftest.S <<EOF
>>>> >> +.globl _start
>>>> >> +_start:
>>>> >> +.globl __start
>>>> >> +__start:
>>>> >> +EOF
>>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>>> >> + pde_ld_flags="-no-pie"
>>>> >> +fi
>>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>>> >> + -nostartfiles -nostdlib $no_ssp \
>>>> >> + -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
>>>> >> + # Get the load address of the first PT_LOAD segment.
>>>> >> + libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>>> >> + | $AWK '/LOAD/ { print $3; exit 0; }')
>>>> >> +else
>>>> >> + AC_MSG_ERROR([${CC-cc} can not create PDE])
>>>> >> +fi
>>>> >> +rm -f conftest*])
>>>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>>>> >> +
>>>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>>>> >> + [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>>>> >> + [libc_cv_load_address=-Wl,-Ttext-segment],
>>>> >> + [libc_cv_load_address=])
>>>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>>>> >> +
IIUC, all of the new conf code is for setting up tests.
Can you make that more clear in either comment or var names?
>>>> >> AC_MSG_CHECKING(if we can build programs as PIE)
>>>> >> AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>>>> >> # error PIE is not supported
>>>> >> diff --git a/elf/Makefile b/elf/Makefile
>>>> >> index 57b3a19d36..4e2d123b8e 100644
>>>> >> --- a/elf/Makefile
>>>> >> +++ b/elf/Makefile
>>>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
>>>> >> tst-pie1 \
>>>> >> tst-pie2 \
>>>> >> # tests-pie
>>>> >> +ifneq (,$(load-address-ldflag))
>>>> >> +tests += \
>>>> >> + tst-pie-address \
>>>> >> + # tests
>>>> >> +tests-pie += \
>>>> >> + tst-pie-address \
>>>> >> + # tests-pie
>>>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>>>> >> +ifeq (yes,$(enable-static-pie))
>>>> >> +tests += \
>>>> >> + tst-pie-address-static \
>>>> >> + # tests
>>>> >> +tests-static += \
>>>> >> + tst-pie-address-static \
>>>> >> + # tests-static
>>>> >> +LDFLAGS-tst-pie-address-static += \
>>>> >> + $(load-address-ldflag)=$(pde-load-address)
>>>> >> +endif
>>>> >> +endif
>>>> >> ifeq (yes,$(have-protected-data))
>>>> >> tests += vismain
>>>> >> tests-pie += vismain
>>>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
>>>> >>
>>>> >> CFLAGS-tst-pie1.c += $(pie-ccflag)
>>>> >> CFLAGS-tst-pie2.c += $(pie-ccflag)
>>>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>>>> >>
>>>> >> $(objpfx)tst-piemod1.so: $(libsupport)
>>>> >> $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>>>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>>>> >> index 10c23d0bf0..6286f19f1f 100644
>>>> >> --- a/elf/dl-reloc-static-pie.c
>>>> >> +++ b/elf/dl-reloc-static-pie.c
>>>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>>>> >> {
>>>> >> struct link_map *main_map = _dl_get_dl_main_map ();
>>>> >>
>>>> >> - /* Figure out the run-time load address of static PIE. */
>>>> >> - main_map->l_addr = elf_machine_load_address ();
>>>> >> -
>>>> >> - /* Read our own dynamic section and fill in the info array. */
>>>> >> - main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
>>>> >> -
>>>> >> + ElfW(Addr) file_p_vaddr = 0;
>>>> >> const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>>>> >> size_t phnum = GL(dl_phnum);
>>>> >> for (ph = phdr; ph < &phdr[phnum]; ++ph)
>>>> >> - if (ph->p_type == PT_DYNAMIC)
>>>> >> + switch (ph->p_type)
>>>> >> {
>>>> >> + case PT_LOAD:
>>>> >> + /* Get p_vaddr of the PT_LOAD segement which covers the file
>>>> >> + start. */
>>>> >> + if (ph->p_offset == 0)
>>>> >> + file_p_vaddr = ph->p_vaddr;
>>>> >> + break;
>>>> >> + case PT_DYNAMIC:
>>>> >> main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>>>> >> break;
>>>> >> + default:
>>>> >> + break;
>>>> >> }
>>>> >>
>>>> >> + /* Figure out the run-time load address of static PIE. */
>>>> >> + ElfW(Addr) l_addr = elf_machine_load_address ();
>>>> >> + main_map->l_addr = l_addr - file_p_vaddr;
Can you explain this? I though vaddr field was the true virtual-address
but you seem to be treating it as an offset here.
>>>> >> +
>>>> >> + /* Read our own dynamic section and fill in the info array. */
>>>> >> + main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>>>> >> +
>>>> >> elf_get_dynamic_info (main_map, false, true);
>>>> >>
>>>> >> # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>>>> >> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
>>>> >> new file mode 100644
>>>> >> index 0000000000..25d27fb962
>>>> >> --- /dev/null
>>>> >> +++ b/elf/tst-pie-address-static.c
>>>> >> @@ -0,0 +1,19 @@
>>>> >> +/* Test static PIE loaded at the specific address.
>>>> >> + Copyright (C) 2024 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
>>>> >> + <https://www.gnu.org/licenses/>. */
>>>> >> +
>>>> >> +#include "tst-pie-address.c"
>>>> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>>>> >> new file mode 100644
>>>> >> index 0000000000..1f01783631
>>>> >> --- /dev/null
>>>> >> +++ b/elf/tst-pie-address.c
>>>> >> @@ -0,0 +1,28 @@
>>>> >> +/* Test PIE loaded at the specific address.
>>>> >> + Copyright (C) 2024 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
>>>> >> + <https://www.gnu.org/licenses/>. */
>>>> >> +
>>>> >> +#include <stdio.h>
>>>> >> +
>>>> >> +static int
>>>> >> +do_test (void)
>>>> >> +{
>>>> >> + printf ("Hello\n");
>>>> >> + return 0;
>>>> >> +}
>>>> >> +
>>>> >> +#include <support/test-driver.c>
>>>> >> --
>>>> >> 2.45.1
>>>> >
>>>> >
>>>> > Ping.
>>>> >
>>>>
>>>> PING.
>>>
>>>
>>> PING.
>>
>>
>> PING.
>
>
> PING.
>
>>
>>>
>>>>
>>>> --
>>>> H.J.
>>>>
>>>>
>>>>
@@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
config_vars="$config_vars
cc-pie-default = $libc_cv_cc_pie_default"
+# Get PDE load address.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
+printf %s "checking PDE load address... " >&6; }
+if test ${libc_cv_pde_load_address+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+ pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+ -nostartfiles -nostdlib $no_ssp \
+ -o conftest conftest.S 1>&5 2>&5; then
+ # Get the load address of the first PT_LOAD segment.
+ libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+ | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+ as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
+fi
+rm -f conftest*
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
+printf "%s\n" "$libc_cv_pde_load_address" >&6; }
+config_vars="$config_vars
+pde-load-address = $libc_cv_pde_load_address"
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
+printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
+libc_linker_feature=no
+cat > conftest.c <<EOF
+int _start (void) { return 42; }
+EOF
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
+ -Wl,-Ttext-segment=$libc_cv_pde_load_address -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=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then
+ if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
+ -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
+ | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
+ true
+ else
+ libc_linker_feature=yes
+ fi
+fi
+rm -f conftest*
+if test $libc_linker_feature = yes; then
+ libc_cv_load_address=-Wl,-Ttext-segment
+else
+ libc_cv_load_address=
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
+printf "%s\n" "$libc_linker_feature" >&6; }
+config_vars="$config_vars
+load-address-ldflag = $libc_cv_load_address"
+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
printf %s "checking if we can build programs as PIE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -1721,6 +1721,36 @@ fi
rm -f conftest.*])
LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
+# Get PDE load address.
+AC_CACHE_CHECK([PDE load address],
+ libc_cv_pde_load_address, [dnl
+cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+ pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+ -nostartfiles -nostdlib $no_ssp \
+ -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
+ # Get the load address of the first PT_LOAD segment.
+ libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+ | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+ AC_MSG_ERROR([${CC-cc} can not create PDE])
+fi
+rm -f conftest*])
+LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
+
+LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
+ [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
+ [libc_cv_load_address=-Wl,-Ttext-segment],
+ [libc_cv_load_address=])
+LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
+
AC_MSG_CHECKING(if we can build programs as PIE)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
# error PIE is not supported
@@ -1046,6 +1046,25 @@ tests-pie += \
tst-pie1 \
tst-pie2 \
# tests-pie
+ifneq (,$(load-address-ldflag))
+tests += \
+ tst-pie-address \
+ # tests
+tests-pie += \
+ tst-pie-address \
+ # tests-pie
+LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
+ifeq (yes,$(enable-static-pie))
+tests += \
+ tst-pie-address-static \
+ # tests
+tests-static += \
+ tst-pie-address-static \
+ # tests-static
+LDFLAGS-tst-pie-address-static += \
+ $(load-address-ldflag)=$(pde-load-address)
+endif
+endif
ifeq (yes,$(have-protected-data))
tests += vismain
tests-pie += vismain
@@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
CFLAGS-tst-pie1.c += $(pie-ccflag)
CFLAGS-tst-pie2.c += $(pie-ccflag)
+CFLAGS-tst-pie-address.c += $(pie-ccflag)
$(objpfx)tst-piemod1.so: $(libsupport)
$(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
@@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
{
struct link_map *main_map = _dl_get_dl_main_map ();
- /* Figure out the run-time load address of static PIE. */
- main_map->l_addr = elf_machine_load_address ();
-
- /* Read our own dynamic section and fill in the info array. */
- main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
-
+ ElfW(Addr) file_p_vaddr = 0;
const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
size_t phnum = GL(dl_phnum);
for (ph = phdr; ph < &phdr[phnum]; ++ph)
- if (ph->p_type == PT_DYNAMIC)
+ switch (ph->p_type)
{
+ case PT_LOAD:
+ /* Get p_vaddr of the PT_LOAD segement which covers the file
+ start. */
+ if (ph->p_offset == 0)
+ file_p_vaddr = ph->p_vaddr;
+ break;
+ case PT_DYNAMIC:
main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
break;
+ default:
+ break;
}
+ /* Figure out the run-time load address of static PIE. */
+ ElfW(Addr) l_addr = elf_machine_load_address ();
+ main_map->l_addr = l_addr - file_p_vaddr;
+
+ /* Read our own dynamic section and fill in the info array. */
+ main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
+
elf_get_dynamic_info (main_map, false, true);
# ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
new file mode 100644
@@ -0,0 +1,19 @@
+/* Test static PIE loaded at the specific address.
+ Copyright (C) 2024 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
+ <https://www.gnu.org/licenses/>. */
+
+#include "tst-pie-address.c"
new file mode 100644
@@ -0,0 +1,28 @@
+/* Test PIE loaded at the specific address.
+ Copyright (C) 2024 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+
+static int
+do_test (void)
+{
+ printf ("Hello\n");
+ return 0;
+}
+
+#include <support/test-driver.c>