@@ -6282,6 +6282,45 @@ fi
$as_echo "$libc_cv_has_glob_dat" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker sets p_align following sh_addralign" >&5
+$as_echo_n "checking whether the linker sets p_align following sh_addralign... " >&6; }
+if ${libc_cv_p_align_follow_sh_addralign+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat > conftest.c <<EOF
+void
+bar (void)
+{
+}
+int foo __attribute__ ((aligned (0x4000))) = 1;
+EOF
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
+ -fPIC -shared -o conftest.so conftest.c
+ -Wl,-z,max-page-size=0x1000
+ -nostdlib -nostartfiles $no_ssp
+ 1>&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then
+ if $READELF -lW conftest.so | egrep 'LOAD.*0x1000$' > /dev/null &&
+ $READELF -lW conftest.so | egrep 'LOAD.*0x4000$' > /dev/null; then
+ libc_cv_p_align_follow_sh_addralign=yes
+ else
+ libc_cv_p_align_follow_sh_addralign=no
+ fi
+else
+ libc_cv_p_align_follow_sh_addralign=no
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_p_align_follow_sh_addralign" >&5
+$as_echo "$libc_cv_p_align_follow_sh_addralign" >&6; }
+config_vars="$config_vars
+have-p_align-follow-sh_addralign = $libc_cv_p_align_follow_sh_addralign"
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fno-toplevel-reorder -fno-section-anchors" >&5
$as_echo_n "checking for -fno-toplevel-reorder -fno-section-anchors... " >&6; }
if ${libc_cv_fno_toplevel_reorder+:} false; then :
@@ -1472,6 +1472,35 @@ fi
rm -f conftest*])
AC_SUBST(libc_cv_has_glob_dat)
+AC_CACHE_CHECK(whether the linker sets p_align following sh_addralign,
+ libc_cv_p_align_follow_sh_addralign, [dnl
+cat > conftest.c <<EOF
+void
+bar (void)
+{
+}
+int foo __attribute__ ((aligned (0x4000))) = 1;
+EOF
+if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS
+ -fPIC -shared -o conftest.so conftest.c
+ -Wl,-z,max-page-size=0x1000
+ -nostdlib -nostartfiles $no_ssp
+ 1>&AS_MESSAGE_LOG_FD])
+then
+dnl Look for 0x1000 and 0x4000 p_align.
+ if $READELF -lW conftest.so | egrep 'LOAD.*0x1000$' > /dev/null &&
+ $READELF -lW conftest.so | egrep 'LOAD.*0x4000$' > /dev/null; then
+ libc_cv_p_align_follow_sh_addralign=yes
+ else
+ libc_cv_p_align_follow_sh_addralign=no
+ fi
+else
+ libc_cv_p_align_follow_sh_addralign=no
+fi
+rm -f conftest*])
+LIBC_CONFIG_VAR([have-p_align-follow-sh_addralign],
+ [$libc_cv_p_align_follow_sh_addralign])
+
AC_CACHE_CHECK(for -fno-toplevel-reorder -fno-section-anchors, libc_cv_fno_toplevel_reorder, [dnl
cat > conftest.c <<EOF
int foo;
@@ -378,6 +378,15 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-auditmod18 \
tst-audit18mod \
+ifeq (yes,$(have-p_align-follow-sh_addralign))
+tests += \
+ tst-p_align1 \
+
+modules-names += \
+ tst-p_alignmod1 \
+
+endif
+
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
modules-names-tests = $(filter-out ifuncmod% tst-tlsmod%,\
@@ -1995,3 +2004,6 @@ $(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \
$(objpfx)tst-ro-dynamic-mod.os
$(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig
+
+$(objpfx)tst-p_align1: $(objpfx)tst-p_alignmod1.so
+$(objpfx)tst-p_alignmod1.so: $(libsupport)
@@ -1101,6 +1101,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
size_t nloadcmds = 0;
bool has_holes = false;
bool empty_dynamic = false;
+ ElfW(Addr) p_align_max = 0;
/* The struct is initialized to zero so this is not necessary:
l->l_ld = 0;
@@ -1151,7 +1152,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
c->dataend = ph->p_vaddr + ph->p_filesz;
c->allocend = ph->p_vaddr + ph->p_memsz;
- c->mapalign = ph->p_align;
+ /* Remember the maximum p_align. */
+ if (ph->p_align > p_align_max)
+ p_align_max = ph->p_align;
c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize));
/* Determine whether there is a gap between the last segment
@@ -1226,6 +1229,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
goto lose;
}
+ /* Align all PT_LOAD segments to the maximum p_align. */
+ for (size_t i = 0; i < nloadcmds; i++)
+ loadcmds[i].mapalign = p_align_max;
+
/* dlopen of an executable is not valid because it is not possible
to perform proper relocations, handle static TLS, or run the
ELF constructors. For PIE, the check needs the dynamic
new file mode 100644
@@ -0,0 +1,27 @@
+/* Check different alignments of PT_LOAD segments in a shared library.
+ Copyright (C) 2021 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/>. */
+
+extern int do_load_test (void);
+
+static int
+do_test (void)
+{
+ return do_load_test ();
+}
+
+#include <support/test-driver.c>
new file mode 100644
@@ -0,0 +1 @@
+#include "tst-alignmod3.c"
new file mode 100644
@@ -0,0 +1,12 @@
+ifeq ($(subdir),elf)
+ifneq (yes,$(have-p_align-follow-sh_addralign))
+# Test alignments for all PT_LOAD segments with a tst-p_alignmod1.so
+# binary if linker doesn't set p_align according to sh_addralign.
+tests += \
+ tst-p_align1 \
+
+$(objpfx)tst-p_alignmod1.so: $(..)sysdeps/x86_64/64/tst-p_alignmod1.so.xz
+ cp -f $< $(objpfx)
+ unxz -f $(objpfx)tst-p_alignmod1.so.xz
+endif
+endif
new file mode 100755