diff mbox series

[v7] elf: Handle static PIE with non-zero load address [BZ #31799]

Message ID CAMe9rOo6aj3R0=jdp77=jmUe_Xg_nh+B15GfG0tQXm+6CCJJww@mail.gmail.com
State New
Headers show
Series [v7] elf: Handle static PIE with non-zero load address [BZ #31799] | expand

Commit Message

H.J. Lu Oct. 26, 2024, 10:29 p.m. UTC
For a static PIE with non-zero load address, its PT_DYNAMIC segment
entries contain the relocated values for the load address in static PIE.
Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
the PT_LOAD segment with offset == 0 as the load address in static PIE
and adjust the entries of PT_DYNAMIC segment in static PIE by properly
setting the l_addr field for static PIE.  This fixes BZ #31799.

OK to install?

Thanks.

Comments

Noah Goldstein Oct. 28, 2024, 2:54 p.m. UTC | #1
On Sat, Oct 26, 2024 at 5:29 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> For a static PIE with non-zero load address, its PT_DYNAMIC segment
> entries contain the relocated values for the load address in static PIE.
> Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
> the PT_LOAD segment with offset == 0 as the load address in static PIE
> and adjust the entries of PT_DYNAMIC segment in static PIE by properly
> setting the l_addr field for static PIE.  This fixes BZ #31799.
>
> OK to install?
>
> Thanks.

Can you post the V7 property instead of as an attachment?
But it looks fine to me.
>
> --
> H.J.
H.J. Lu Oct. 28, 2024, 10:12 p.m. UTC | #2
On Mon, Oct 28, 2024 at 10:54 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
>
> On Sat, Oct 26, 2024 at 5:29 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > For a static PIE with non-zero load address, its PT_DYNAMIC segment
> > entries contain the relocated values for the load address in static PIE.
> > Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
> > the PT_LOAD segment with offset == 0 as the load address in static PIE
> > and adjust the entries of PT_DYNAMIC segment in static PIE by properly
> > setting the l_addr field for static PIE.  This fixes BZ #31799.
> >
> > OK to install?
> >
> > Thanks.
>
> Can you post the V7 property instead of as an attachment?

Done.

> But it looks fine to me.
> >
> > --
> > H.J.
Florian Weimer Nov. 29, 2024, 4:52 p.m. UTC | #3
* H. J. Lu:

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

These tests fail on aarch64 and s390x for us:

=====FAIL: elf/tst-pie-address.out=====
=====FAIL: elf/tst-pie-address.test-result=====
FAIL: elf/tst-pie-address
original exit status 139
=====FAIL: elf/tst-pie-address-static.out=====
=====FAIL: elf/tst-pie-address-static.test-result=====
FAIL: elf/tst-pie-address-static
original exit status 132

The configure checks report this 

checking whether -fPIE is default... no
checking PDE load address... 0x0000000001000000
checking for linker that supports -Ttext-segment=0x0000000001000000... yes
checking if we can build programs as PIE... yes
checking if we can build static PIE programs... yes

checking whether -fPIE is default... no
checking PDE load address... 0x0000000000400000
checking for linker that supports -Ttext-segment=0x0000000000400000... yes
checking if we can build programs as PIE... yes
checking if we can build static PIE programs... yes

Thanks,
Florian
H.J. Lu Nov. 30, 2024, 4:18 a.m. UTC | #4
On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:

> * H. J. Lu:
>
> > +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
>
> These tests fail on aarch64 and s390x for us:
>
> =====FAIL: elf/tst-pie-address.out=====
> =====FAIL: elf/tst-pie-address.test-result=====
> FAIL: elf/tst-pie-address
> original exit status 139
> =====FAIL: elf/tst-pie-address-static.out=====
> =====FAIL: elf/tst-pie-address-static.test-result=====
> FAIL: elf/tst-pie-address-static
> original exit status 132
>

Do they fail without -Ttext-segment=? My change doesn't
touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.


> The configure checks report this
>
> checking whether -fPIE is default... no
> checking PDE load address... 0x0000000001000000
> checking for linker that supports -Ttext-segment=0x0000000001000000... yes
> checking if we can build programs as PIE... yes
> checking if we can build static PIE programs... yes
>
> checking whether -fPIE is default... no
> checking PDE load address... 0x0000000000400000
> checking for linker that supports -Ttext-segment=0x0000000000400000... yes
> checking if we can build programs as PIE... yes
> checking if we can build static PIE programs... yes
>
> Thanks,
> Florian
>
>
>
H.J. Lu Dec. 2, 2024, 1:15 a.m. UTC | #5
On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> > +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
>>
>> These tests fail on aarch64 and s390x for us:
>>
>> =====FAIL: elf/tst-pie-address.out=====
>> =====FAIL: elf/tst-pie-address.test-result=====
>> FAIL: elf/tst-pie-address
>> original exit status 139
>> =====FAIL: elf/tst-pie-address-static.out=====
>> =====FAIL: elf/tst-pie-address-static.test-result=====
>> FAIL: elf/tst-pie-address-static
>> original exit status 132
>
>
> Do they fail without -Ttext-segment=? My change doesn't
> touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
>
>>
>> The configure checks report this
>>
>> checking whether -fPIE is default... no
>> checking PDE load address... 0x0000000001000000

Somehow aarch64 got

pde-load-address =

in config.make.  I will take a look.

>> checking for linker that supports -Ttext-segment=0x0000000001000000... yes
>> checking if we can build programs as PIE... yes
>> checking if we can build static PIE programs... yes
>>
>> checking whether -fPIE is default... no
>> checking PDE load address... 0x0000000000400000
>> checking for linker that supports -Ttext-segment=0x0000000000400000... yes
>> checking if we can build programs as PIE... yes
>> checking if we can build static PIE programs... yes
>>
>> Thanks,
>> Florian
>>
>>
Stefan Liebler Dec. 2, 2024, 9:09 a.m. UTC | #6
On 30.11.24 05:18, H.J. Lu wrote:
> On Sat, Nov 30, 2024, 12: 52 AM Florian Weimer <fweimer@ redhat. com>
> wrote: * H. J. Lu: > +ifneq (,$(load-address-ldflag)) > +tests += \ > +
> tst-pie-address \ > + # tests > +tests-pie += \ > + tst-pie-address \ > + #
> 
> On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com
> <mailto:fweimer@redhat.com>> wrote:
> 
>     * H. J. Lu:
> 
>     > +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
> 
>     These tests fail on aarch64 and s390x for us:
> 
>     =====FAIL: elf/tst-pie-address.out=====
>     =====FAIL: elf/tst-pie-address.test-result=====
>     FAIL: elf/tst-pie-address
>     original exit status 139
>     =====FAIL: elf/tst-pie-address-static.out=====
>     =====FAIL: elf/tst-pie-address-static.test-result=====
>     FAIL: elf/tst-pie-address-static
>     original exit status 132
> 
> 
> Do they fail without -Ttext-segment=? My change doesn't
> touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
I've also recognized this fail. At least on s390, it segfaults in this
already relocated static PIE case, as elf_machine_load_address() returns
0x0 (The got entry of _dl_start already contains the run-time-address
and thus the diff is zero) and elf_machine_load_address() is also wrong.
I'm already working on a patch relying on __ehdr_start and __DYNAMIC
similar to other architectures. Will do some tests first and then post a
patch for s390x.

Bye,
Stefan
> 
> 
>     The configure checks report this
> 
>     checking whether -fPIE is default... no
>     checking PDE load address... 0x0000000001000000
>     checking for linker that supports -Ttext-
>     segment=0x0000000001000000... yes
>     checking if we can build programs as PIE... yes
>     checking if we can build static PIE programs... yes
> 
>     checking whether -fPIE is default... no
>     checking PDE load address... 0x0000000000400000
>     checking for linker that supports -Ttext-
>     segment=0x0000000000400000... yes
>     checking if we can build programs as PIE... yes
>     checking if we can build static PIE programs... yes
> 
>     Thanks,
>     Florian
> 
>
diff mbox series

Patch

From 7b4be3b7d2667b4dca3516311167788ddf78f580 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 26 May 2024 04:55:32 -0700
Subject: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ
 #31799]

For a static PIE with non-zero load address, its PT_DYNAMIC segment
entries contain the relocated values for the load address in static PIE.
Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
the PT_LOAD segment with offset == 0 as the load address in static PIE
and adjust the entries of PT_DYNAMIC segment in static PIE by properly
setting the l_addr field for static PIE.  This fixes BZ #31799.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 configure                    | 74 ++++++++++++++++++++++++++++++++++++
 configure.ac                 | 36 ++++++++++++++++++
 elf/Makefile                 | 20 ++++++++++
 elf/dl-reloc-static-pie.c    | 30 +++++++++++----
 elf/tst-pie-address-static.c | 19 +++++++++
 elf/tst-pie-address.c        | 28 ++++++++++++++
 6 files changed, 200 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 9c0c0dce03..9bcf62dca5 100755
--- a/configure
+++ b/configure
@@ -8107,6 +8107,80 @@  printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
 config_vars="$config_vars
 cc-pie-default = $libc_cv_cc_pie_default"
 
+# Get Position Dependent Executable (PDE) load address to be used to
+# load static Position Independent Executable (PIE) at a known working
+# non-zero load address.  This is only used by glibc tests to verify
+# that PIE and static PIE with non-zero load address work correctly.
+{ 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 case e in #(
+  e) 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* ;;
+esac
+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"
+
+# Get the linker command-line option to load executable at a non-zero
+# load address.  This is only used by glibc tests to verify that PIE and
+# static PIE with non-zero load address work correctly.
+{ 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_ldflag=-Wl,-Ttext-segment
+else
+  libc_cv_load_address_ldflag=
+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_ldflag"
+
 { 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 d5a00461ff..895bd5267d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1763,6 +1763,42 @@  fi
 rm -f conftest.*])
 LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
 
+# Get Position Dependent Executable (PDE) load address to be used to
+# load static Position Independent Executable (PIE) at a known working
+# non-zero load address.  This is only used by glibc tests to verify
+# that PIE and static PIE with non-zero load address work correctly.
+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])
+
+# Get the linker command-line option to load executable at a non-zero
+# load address.  This is only used by glibc tests to verify that PIE and
+# static PIE with non-zero load address work correctly.
+LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
+		    [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
+		    [libc_cv_load_address_ldflag=-Wl,-Ttext-segment],
+		    [libc_cv_load_address_ldflag=])
+LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag])
+
 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 9cfe738919..4eaca7af67 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1091,6 +1091,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
@@ -1937,6 +1956,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..bfee89dfc3 100644
--- a/elf/dl-reloc-static-pie.c
+++ b/elf/dl-reloc-static-pie.c
@@ -37,21 +37,37 @@  _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 ());
-
+  /* NB: elf_machine_load_address () returns the run-time load address
+     of static PIE.  The l_addr field contains the difference between the
+     link-time load address in the ELF file and the run-time load address
+     in memory.  We must subtract the link-time load address of static PIE,
+     which can be non-zero, when computing the l_addr field.  Since static
+     PIE usually doesn't have PT_PHDR segment, use p_vaddr of the PT_LOAD
+     segment with offset == 0 as the load address of static PIE.  */
+  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:
+	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..be2831e9d6
--- /dev/null
+++ b/elf/tst-pie-address-static.c
@@ -0,0 +1,19 @@ 
+/* Test static PIE with non-zero load 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..aa1ca0a9fd
--- /dev/null
+++ b/elf/tst-pie-address.c
@@ -0,0 +1,28 @@ 
+/* Test PIE with non-zero load 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.47.0