This patch provides environment variables HUGEPAGE_PROBE and LD_HUGEPAGE_LIB to enable load shared object use hugepage. Signed-off-by: Lv Ying <lvying6@huawei.com> Reviewed-by: zhoukang <gameoverboss@163.com>
1178 lines
38 KiB
Diff
1178 lines
38 KiB
Diff
From 74c980c56a1ae533c3cd25f572f83c0c1def6a30 Mon Sep 17 00:00:00 2001
|
|
From: Lv Ying <lvying6@huawei.com>
|
|
Date: Tue, 25 Jan 2022 09:25:35 +0000
|
|
Subject: [PATCH 2/3] elf/ld.so: add testcase for ld.so load shared object use
|
|
hugepage feature
|
|
|
|
1. testcase for hugepageedit
|
|
2. testcase for feature env
|
|
3. testcase for feature fallback
|
|
4. testcase for hugepage mmap consistency witch process occupancy
|
|
5. testcase for dlopen use hugepage
|
|
---
|
|
config.make.in | 1 +
|
|
configure | 24 ++++++-
|
|
configure.ac | 3 +
|
|
elf/Makefile | 61 +++++++++++++++++
|
|
elf/hugepageedit.c | 69 +++----------------
|
|
elf/tst-check-hugepage.sh | 72 ++++++++++++++++++++
|
|
elf/tst-dl-hugepage.sh | 70 +++++++++++++++++++
|
|
elf/tst-dl-use-hugepage.c | 54 +++++++++++++++
|
|
elf/tst-get-ephdr.h | 96 ++++++++++++++++++++++++++
|
|
elf/tst-hugepageedit1.sh | 85 +++++++++++++++++++++++
|
|
elf/tst-ld-hugepage-env.sh | 108 ++++++++++++++++++++++++++++++
|
|
elf/tst-ld-hugepage-fallback.sh | 66 ++++++++++++++++++
|
|
elf/tst-ld-hugepage-mmap-smaps.sh | 49 ++++++++++++++
|
|
elf/tst-ld-hugepage.h | 7 ++
|
|
elf/tst-ld-hugepagemod.c | 19 ++++++
|
|
elf/tst-update-ehdr.c | 58 ++++++++++++++++
|
|
elf/tst-update-phdr.c | 93 +++++++++++++++++++++++++
|
|
elf/tst-use-hugepage.c | 15 +++++
|
|
18 files changed, 889 insertions(+), 61 deletions(-)
|
|
create mode 100644 elf/tst-check-hugepage.sh
|
|
create mode 100644 elf/tst-dl-hugepage.sh
|
|
create mode 100644 elf/tst-dl-use-hugepage.c
|
|
create mode 100644 elf/tst-get-ephdr.h
|
|
create mode 100644 elf/tst-hugepageedit1.sh
|
|
create mode 100644 elf/tst-ld-hugepage-env.sh
|
|
create mode 100644 elf/tst-ld-hugepage-fallback.sh
|
|
create mode 100644 elf/tst-ld-hugepage-mmap-smaps.sh
|
|
create mode 100644 elf/tst-ld-hugepage.h
|
|
create mode 100644 elf/tst-ld-hugepagemod.c
|
|
create mode 100644 elf/tst-update-ehdr.c
|
|
create mode 100644 elf/tst-update-phdr.c
|
|
create mode 100644 elf/tst-use-hugepage.c
|
|
|
|
diff --git a/config.make.in b/config.make.in
|
|
index cbf59114..0105cc8e 100644
|
|
--- a/config.make.in
|
|
+++ b/config.make.in
|
|
@@ -76,6 +76,7 @@ use-default-link = @use_default_link@
|
|
have-cxx-thread_local = @libc_cv_cxx_thread_local@
|
|
have-loop-to-function = @libc_cv_cc_loop_to_function@
|
|
have-textrel_ifunc = @libc_cv_textrel_ifunc@
|
|
+have-hugetlb-dir = @have_hugetlb_dir@
|
|
|
|
multi-arch = @multi_arch@
|
|
|
|
diff --git a/configure b/configure
|
|
index 43993923..be2277b1 100755
|
|
--- a/configure
|
|
+++ b/configure
|
|
@@ -670,7 +670,7 @@ stack_protector
|
|
libc_cv_ssp
|
|
libc_cv_with_fp
|
|
base_machine
|
|
-enable_hugepage_shared_library
|
|
+have_hugetlb_dir
|
|
have_tunables
|
|
build_pt_chown
|
|
build_nscd
|
|
@@ -3848,6 +3848,28 @@ enable-hugepage-shared-library = $enable_hugepage_shared_library"
|
|
if test "$enable_hugepage_shared_library" = yes; then
|
|
$as_echo "#define HUGEPAGE_SHARED_LIB 1" >>confdefs.h
|
|
|
|
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /sys/devices/system/node/node0/hugepages/hugepages-2048kB/" >&5
|
|
+$as_echo_n "checking for /sys/devices/system/node/node0/hugepages/hugepages-2048kB/... " >&6; }
|
|
+if ${ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_+:} false; then :
|
|
+ $as_echo_n "(cached) " >&6
|
|
+else
|
|
+ test "$cross_compiling" = yes &&
|
|
+ as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
|
|
+if test -r "/sys/devices/system/node/node0/hugepages/hugepages-2048kB/"; then
|
|
+ ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_=yes
|
|
+else
|
|
+ ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_=no
|
|
+fi
|
|
+fi
|
|
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" >&5
|
|
+$as_echo "$ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" >&6; }
|
|
+if test "x$ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" = xyes; then :
|
|
+ have_hugetlb_dir=yes
|
|
+else
|
|
+ have_hugetlb_dir=no
|
|
+fi
|
|
+
|
|
+
|
|
fi
|
|
|
|
# We keep the original values in `$config_*' and never modify them, so we
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 27a48338..fa34af26 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -487,6 +487,9 @@ AC_ARG_ENABLE([hugepage-shared-library],
|
|
LIBC_CONFIG_VAR([enable-hugepage-shared-library], [$enable_hugepage_shared_library])
|
|
if test "$enable_hugepage_shared_library" = yes; then
|
|
AC_DEFINE(HUGEPAGE_SHARED_LIB)
|
|
+ AC_CHECK_FILE(/sys/devices/system/node/node0/hugepages/hugepages-2048kB/,
|
|
+ have_hugetlb_dir=yes, have_hugetlb_dir=no)
|
|
+ AC_SUBST(have_hugetlb_dir)
|
|
fi
|
|
|
|
# We keep the original values in `$config_*' and never modify them, so we
|
|
diff --git a/elf/Makefile b/elf/Makefile
|
|
index 1574574d..0fb2be3b 100644
|
|
--- a/elf/Makefile
|
|
+++ b/elf/Makefile
|
|
@@ -213,6 +213,12 @@ others-pie += hugepageedit
|
|
install-bin += hugepageedit
|
|
|
|
$(objpfx)hugepageedit: $(objpfx)hugepageedit.o
|
|
+
|
|
+ifeq ($(run-built-tests),yes)
|
|
+tests-special += $(objpfx)tst-hugepageedit1.out $(objpfx)tst-ld-hugepage-env.out \
|
|
+ $(objpfx)tst-ld-hugepage-fallback.out $(objpfx)tst-ld-hugepage-mmap-smaps.out \
|
|
+ $(objpfx)tst-dl-hugepage.out
|
|
+endif
|
|
endif
|
|
|
|
# To find xmalloc.c and xstrdup.c
|
|
@@ -788,6 +794,13 @@ $(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
|
|
tst-gnu2-tls1mod.so-no-z-defs = yes
|
|
CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
|
|
endif
|
|
+ifeq (yes,$(enable-hugepage-shared-library))
|
|
+ld-hugepagemod-suffixes = 1 2 3 4 5
|
|
+ld-hugepagemod-modules = $(addprefix tst-ld-hugepagemod, $(ld-hugepagemod-suffixes))
|
|
+tst-usehugepage = $(addprefix tst-use-hugepage, $(ld-hugepagemod-suffixes))
|
|
+modules-names += $(ld-hugepagemod-modules)
|
|
+test-srcs += tst-update-ehdr tst-update-phdr tst-dl-use-hugepage $(tst-usehugepage)
|
|
+endif
|
|
ifeq (yes,$(have-protected-data))
|
|
modules-names += tst-protected1moda tst-protected1modb
|
|
tests += tst-protected1a tst-protected1b
|
|
@@ -2015,6 +2028,54 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
|
'$(run-program-env)' > $@; \
|
|
$(evaluate-test)
|
|
|
|
+ifeq (yes,$(enable-hugepage-shared-library))
|
|
+CFLAGS-tst-ld-hugepagemod.c += -DOBJDIR=\"$(elf-objpfx)\"
|
|
+$(objpfx)tst-ld-hugepage-bin.o :
|
|
+ dd if=/dev/zero of=$@ count=4 bs=2MB
|
|
+$(patsubst %,$(objpfx)%.os,$(ld-hugepagemod-modules)): $(objpfx)tst-ld-hugepagemod%.os: tst-ld-hugepagemod.c $(objpfx)tst-ld-hugepage-bin.o
|
|
+ $(compile-command.c) -DN=$*
|
|
+$(patsubst %,$(objpfx)%.o,$(tst-usehugepage)): $(objpfx)tst-use-hugepage%.o: tst-use-hugepage.c
|
|
+ $(compile-command.c)
|
|
+$(patsubst tst-use-hugepage%,$(objpfx)tst-use-hugepage%,$(tst-usehugepage)): $(objpfx)tst-use-hugepage% : \
|
|
+ $(objpfx)tst-use-hugepage%.o $(objpfx)tst-ld-hugepagemod%.so $(objpfx)ld.so
|
|
+$(objpfx)tst-dl-use-hugepage: $(libdl)
|
|
+
|
|
+ifeq ($(have-hugetlb-dir),yes)
|
|
+$(objpfx)tst-hugepageedit1.out: tst-hugepageedit1.sh tst-check-hugepage.sh \
|
|
+ $(objpfx)tst-update-ehdr $(objpfx)tst-use-hugepage1 $(objpfx)tst-ld-hugepagemod1.so
|
|
+ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
|
|
+ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
|
|
+ $(evaluate-test)
|
|
+
|
|
+$(objpfx)tst-ld-hugepage-env.out: tst-ld-hugepage-env.sh tst-check-hugepage.sh \
|
|
+ $(objpfx)tst-use-hugepage2 $(objpfx)tst-ld-hugepagemod2.so
|
|
+ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
|
|
+ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
|
|
+ $(evaluate-test)
|
|
+
|
|
+$(objpfx)tst-ld-hugepage-fallback.out: tst-ld-hugepage-fallback.sh tst-check-hugepage.sh \
|
|
+ $(objpfx)tst-update-phdr $(objpfx)tst-use-hugepage3 $(objpfx)tst-ld-hugepagemod3.so
|
|
+ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
|
|
+ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
|
|
+ $(evaluate-test)
|
|
+
|
|
+$(objpfx)tst-ld-hugepage-mmap-smaps.out: tst-ld-hugepage-mmap-smaps.sh tst-check-hugepage.sh \
|
|
+ $(objpfx)tst-use-hugepage4 $(objpfx)tst-ld-hugepagemod4.so
|
|
+ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
|
|
+ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
|
|
+ $(evaluate-test)
|
|
+
|
|
+$(objpfx)tst-dl-hugepage.out: tst-dl-hugepage.sh tst-check-hugepage.sh \
|
|
+ $(objpfx)tst-dl-use-hugepage $(objpfx)tst-ld-hugepagemod5.so
|
|
+ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
|
|
+ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
|
|
+ $(evaluate-test)
|
|
+else
|
|
+tests-unsupported += tst-hugepageedit1.out tst-ld-hugepage-env.out tst-ld-hugepage-fallback.out \
|
|
+ tst-ld-hugepage-mmap-smaps.out tst-dl-hugepage.out
|
|
+endif
|
|
+endif
|
|
+
|
|
# Test static linking of all the libraries we can possibly link
|
|
# together. Note that in some configurations this may be less than the
|
|
# complete list of libraries we build but we try to maxmimize this list.
|
|
diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c
|
|
index 14a91a4b..ab4247ad 100644
|
|
--- a/elf/hugepageedit.c
|
|
+++ b/elf/hugepageedit.c
|
|
@@ -25,18 +25,10 @@
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
+#include "tst-get-ephdr.h"
|
|
|
|
-/* reference kernel load_elf_phdrs program header table size constraint */
|
|
-#define ELF_MIN_ALIGN 4096
|
|
#define TOOL_NAME "hugepageedit"
|
|
|
|
-int check_ptr(void *ptr, void *start, size_t len)
|
|
-{
|
|
- if (ptr < start || ptr > start + len)
|
|
- return -1;
|
|
- return 0;
|
|
-}
|
|
-
|
|
void print_usage(void)
|
|
{
|
|
fprintf(stderr, "%s [-x] [-d] <ELF file>\n" \
|
|
@@ -47,6 +39,7 @@ void print_usage(void)
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
+ size_t length;
|
|
int exit_status = -1;
|
|
int i, opt, delete = 0, exec_only = 0;
|
|
while ((opt = getopt(argc, argv, "dx")) != -1)
|
|
@@ -84,57 +77,13 @@ int main(int argc, char *argv[])
|
|
return -1;
|
|
}
|
|
|
|
- struct stat statbuf;
|
|
- if (fstat(fd, &statbuf) != 0)
|
|
- {
|
|
- perror("fstat");
|
|
- goto close_fd;
|
|
- }
|
|
-
|
|
- /* this ensures file is large enough to hold ELF header */
|
|
- if (statbuf.st_size < sizeof (ElfW(Ehdr)))
|
|
- {
|
|
- fprintf(stderr, "file is not large enough to hold ELF header\n");
|
|
- goto close_fd;
|
|
- }
|
|
-
|
|
- void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
|
- if (ehdr == MAP_FAILED)
|
|
- {
|
|
- perror("mmap");
|
|
- goto close_fd;
|
|
- }
|
|
-
|
|
- if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0)
|
|
- {
|
|
- fprintf(stderr, "file is not ELF format\n");
|
|
- goto unmap;
|
|
- }
|
|
-
|
|
- if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr)))
|
|
- {
|
|
- fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n");
|
|
- goto unmap;
|
|
- }
|
|
-
|
|
- unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr));
|
|
- if (size == 0 || size > ELF_MIN_ALIGN)
|
|
- {
|
|
- fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size);
|
|
- goto unmap;
|
|
- }
|
|
-
|
|
- void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff;
|
|
- void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size;
|
|
-
|
|
- if (check_ptr(ephdr_s, ehdr, statbuf.st_size) ||
|
|
- check_ptr(ephdr_e, ehdr, statbuf.st_size))
|
|
- {
|
|
- fprintf(stderr, "ELF porgram header table is not fully mmaped\n");
|
|
- goto unmap;
|
|
- }
|
|
+ void *ehdr = get_ehdr(fd, &length);
|
|
+ if (ehdr == NULL)
|
|
+ goto close_fd;
|
|
|
|
- ElfW(Phdr) *phdr = (ElfW(Phdr) *)ephdr_s;
|
|
+ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length);
|
|
+ if (phdr == NULL)
|
|
+ goto unmap;
|
|
/*
|
|
* Here, mark hugepage flag in ELF header e_ident padding bytes won't work.
|
|
* elf/dl-load.c open_verify will check if shared object ELF header e_ident
|
|
@@ -160,7 +109,7 @@ int main(int argc, char *argv[])
|
|
exit_status = 0;
|
|
|
|
unmap:
|
|
- munmap(ehdr, statbuf.st_size);
|
|
+ munmap(ehdr, length);
|
|
|
|
close_fd:
|
|
close(fd);
|
|
diff --git a/elf/tst-check-hugepage.sh b/elf/tst-check-hugepage.sh
|
|
new file mode 100644
|
|
index 00000000..0cdebe2a
|
|
--- /dev/null
|
|
+++ b/elf/tst-check-hugepage.sh
|
|
@@ -0,0 +1,72 @@
|
|
+#!/bin/sh
|
|
+# check whether ld.so use hugepage when loading shared object and whether
|
|
+# there are exceptions when using hugepage
|
|
+# Copyright (C) 2021-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
|
|
+# <http://www.gnu.org/licenses/>.
|
|
+
|
|
+check_hugepage_mmap () {
|
|
+ log=$1
|
|
+
|
|
+ cat $log | egrep "reserved area|_dl_map_segments_largein:" > /dev/null && return 0
|
|
+ return 1
|
|
+}
|
|
+
|
|
+check_hugepage_mmap_success () {
|
|
+ log=$1
|
|
+
|
|
+ # check whether the log contains fallback log
|
|
+ cat $log | grep "_dl_map_segments_largein:" > /dev/null && return 1
|
|
+ check_hugepage_mmap $log || return 1
|
|
+ left=$(cat $log | grep _mmap_segment | wc -l)
|
|
+ right=$(cat $log | grep "} => mapseglen" | wc -l)
|
|
+ if [ $left -eq $right ]; then
|
|
+ return 0
|
|
+ else
|
|
+ return 1
|
|
+ fi
|
|
+}
|
|
+
|
|
+check_hugepage_fallback () {
|
|
+ log=$1
|
|
+
|
|
+ cat $log | grep "_dl_map_segments_largein:" > /dev/null && return 0
|
|
+ return 1
|
|
+}
|
|
+
|
|
+# return 0: mmap hugepage correctly
|
|
+# return 1: Non-hugepage mmap
|
|
+# return 2: mmap hugepage wrongly
|
|
+check_hugepage_mmap_detail () {
|
|
+ log=$1
|
|
+
|
|
+ # check whether the log contains hugepage mmap
|
|
+ areas=$(cat $log | grep "mmap hugepage:" | awk '{print $4}' | cut -d '[' -f2 | cut -d ')' -f1)
|
|
+ if test -z "$areas"; then
|
|
+ return 1
|
|
+ else
|
|
+ for area in $areas; do
|
|
+ num=$(grep "mmap hugepage: \[$area)" $log | wc -l)
|
|
+ num=$(( $num * 2))
|
|
+ total_num=$(grep $area $log | wc -l)
|
|
+ if [ $num -ne $total_num ]; then
|
|
+ return 2
|
|
+ fi
|
|
+ grep -A21 $area $log | tail -22
|
|
+ done
|
|
+ return 0
|
|
+ fi
|
|
+}
|
|
diff --git a/elf/tst-dl-hugepage.sh b/elf/tst-dl-hugepage.sh
|
|
new file mode 100644
|
|
index 00000000..f67e552f
|
|
--- /dev/null
|
|
+++ b/elf/tst-dl-hugepage.sh
|
|
@@ -0,0 +1,70 @@
|
|
+#!/bin/sh
|
|
+# Test that ld.so can handle dlopen call
|
|
+# Copyright (C) 2021-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
|
|
+# <http://www.gnu.org/licenses/>.
|
|
+
|
|
+set -ex
|
|
+echo "source $4"
|
|
+source $4
|
|
+
|
|
+common_objpfx=$1
|
|
+test_wrapper=$2
|
|
+test_wrapper_env=$3
|
|
+result=0
|
|
+
|
|
+excption_handle ()
|
|
+{
|
|
+ echo "ld.so hugepage feature is not behaving as expected, return $1"
|
|
+ result=1
|
|
+}
|
|
+
|
|
+check_global_var ()
|
|
+{
|
|
+ log=$1
|
|
+
|
|
+ for i in $(seq 1 2); do
|
|
+ cat $log | grep "In huge_func, huge_global = $i" > /dev/null|| return -1
|
|
+ done
|
|
+ return 0
|
|
+}
|
|
+
|
|
+testroot="${common_objpfx}elf/dl-hugepage-directory"
|
|
+
|
|
+rm -rf "$testroot"
|
|
+mkdir -p $testroot
|
|
+
|
|
+echo '# reseve 200 2MB hugepage'
|
|
+echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
|
|
+
|
|
+echo '# Test LD_HUGEPAGE_LIB=1 whether ld.so mmap hugepage is consistent with the actual process occupancy'
|
|
+${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-dl-use-hugepage ${common_objpfx}elf/tst-ld-hugepagemod5.so > ${testroot}/log1 2>&1
|
|
+check_hugepage_mmap_detail ${testroot}/log1 && rc=0 || rc=$?
|
|
+#check_global_var ${testroot}/log1 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle $rc
|
|
+
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod5.so || exit 1
|
|
+
|
|
+echo '# Test HUGEPAGE_PROBE=1 whether ld.so mmap hugepage is consistent with the actual process occupancy'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-dl-use-hugepage ${common_objpfx}elf/tst-ld-hugepagemod5.so > ${testroot}/log2 2>&1
|
|
+check_hugepage_mmap_detail ${testroot}/log2 && rc=0 || rc=$?
|
|
+#check_global_var ${testroot}/log2 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle $rc
|
|
+
|
|
+exit $result
|
|
diff --git a/elf/tst-dl-use-hugepage.c b/elf/tst-dl-use-hugepage.c
|
|
new file mode 100644
|
|
index 00000000..cd7c6f29
|
|
--- /dev/null
|
|
+++ b/elf/tst-dl-use-hugepage.c
|
|
@@ -0,0 +1,54 @@
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <unistd.h>
|
|
+#include <dlfcn.h>
|
|
+#include "tst-ld-hugepage.h"
|
|
+
|
|
+#define DL_ERR_HANDLE(s) \
|
|
+do { \
|
|
+ fprintf(stderr, "%s: %s\n", s, dlerror()); \
|
|
+ exit(EXIT_FAILURE); \
|
|
+} while(0)
|
|
+
|
|
+static void dl_flag_test(char *libname, int flags, int val)
|
|
+{
|
|
+ int *global;
|
|
+ char *error;
|
|
+ void (*funcp)(void);
|
|
+ char command[100];
|
|
+ sprintf(command, "cat /proc/%d/smaps", getpid());
|
|
+
|
|
+ void *handle = dlopen(libname, flags);
|
|
+ if (handle == NULL)
|
|
+ DL_ERR_HANDLE("dlopen");
|
|
+
|
|
+ (void) dlerror();
|
|
+
|
|
+ *(void **)(&global) = dlsym(handle, "huge_global");
|
|
+ error = dlerror();
|
|
+ if (error != NULL)
|
|
+ DL_ERR_HANDLE("dlsym");
|
|
+
|
|
+ (void) dlerror();
|
|
+ *(void **)(&funcp) = dlsym(handle, "huge_func");
|
|
+ error = dlerror();
|
|
+ if (error != NULL)
|
|
+ DL_ERR_HANDLE("dlsym");
|
|
+
|
|
+ *global = val;
|
|
+ (*funcp)();
|
|
+ system(command);
|
|
+ dlclose(handle);
|
|
+}
|
|
+
|
|
+int main(int argc, char *argv[])
|
|
+{
|
|
+ if (argc != 2)
|
|
+ {
|
|
+ fprintf(stderr, "shared object should be a parameter\n");
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+ dl_flag_test(argv[1], RTLD_LAZY, 1);
|
|
+ dl_flag_test(argv[1], RTLD_NOW, 2);
|
|
+ return 0;
|
|
+}
|
|
diff --git a/elf/tst-get-ephdr.h b/elf/tst-get-ephdr.h
|
|
new file mode 100644
|
|
index 00000000..109af265
|
|
--- /dev/null
|
|
+++ b/elf/tst-get-ephdr.h
|
|
@@ -0,0 +1,96 @@
|
|
+/* mmap ELF file return ELF header and get mmap length
|
|
+ Copyright (C) 1995-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
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+#include <stdio.h>
|
|
+#include <elf.h>
|
|
+#include <link.h>
|
|
+#include <string.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/mman.h>
|
|
+
|
|
+/* reference kernel load_elf_phdrs program header table size constraint */
|
|
+#define ELF_MIN_ALIGN 4096
|
|
+
|
|
+static __always_inline void *get_ehdr(int fd, size_t *len)
|
|
+{
|
|
+ struct stat statbuf;
|
|
+ *len = 0;
|
|
+ if (fstat(fd, &statbuf) != 0)
|
|
+ {
|
|
+ perror("fstat");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /* this ensures file is large enough to hold ELF header */
|
|
+ if (statbuf.st_size < sizeof (ElfW(Ehdr)))
|
|
+ {
|
|
+ fprintf(stderr, "file is not large enough to hold ELF header\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
|
+ if (ehdr == MAP_FAILED)
|
|
+ {
|
|
+ perror("mmap");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0)
|
|
+ {
|
|
+ fprintf(stderr, "file is not ELF format\n");
|
|
+ munmap(ehdr, statbuf.st_size);
|
|
+ ehdr = NULL;
|
|
+ }
|
|
+
|
|
+ *len = statbuf.st_size;
|
|
+ return ehdr;
|
|
+}
|
|
+
|
|
+static __always_inline int check_ptr(void *ptr, void *start, size_t len)
|
|
+{
|
|
+ if (ptr < start || ptr > start + len)
|
|
+ return -1;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static __always_inline void *get_phdr(void *ehdr, size_t length)
|
|
+{
|
|
+ if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr)))
|
|
+ {
|
|
+ fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr));
|
|
+ if (size == 0 || size > ELF_MIN_ALIGN)
|
|
+ {
|
|
+ fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff;
|
|
+ void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size;
|
|
+
|
|
+ if (check_ptr(ephdr_s, ehdr, length) ||
|
|
+ check_ptr(ephdr_e, ehdr, length))
|
|
+ {
|
|
+ fprintf(stderr, "ELF porgram header table is not fully mmaped\n");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return ephdr_s;
|
|
+}
|
|
diff --git a/elf/tst-hugepageedit1.sh b/elf/tst-hugepageedit1.sh
|
|
new file mode 100644
|
|
index 00000000..ee43c279
|
|
--- /dev/null
|
|
+++ b/elf/tst-hugepageedit1.sh
|
|
@@ -0,0 +1,85 @@
|
|
+#!/bin/sh
|
|
+# Test that hugepageedit can handle abnormal files reasonably
|
|
+# Copyright (C) 2021-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
|
|
+# <http://www.gnu.org/licenses/>.
|
|
+
|
|
+set -ex
|
|
+echo "source $4"
|
|
+source $4
|
|
+
|
|
+common_objpfx=$1
|
|
+test_wrapper=$2
|
|
+test_wrapper_env=$3
|
|
+result=0
|
|
+
|
|
+excption_handle ()
|
|
+{
|
|
+ echo "hugepageedit and ls.so use hugepage feature is not beahving expected"
|
|
+ result=1
|
|
+}
|
|
+
|
|
+testroot="${common_objpfx}elf/hugepageedit-test-directory"
|
|
+
|
|
+rm -rf "$testroot"
|
|
+mkdir -p $testroot
|
|
+cp ${common_objpfx}elf/tst-use-hugepage1 $testroot/tst-use-hugepage1
|
|
+
|
|
+echo '# reseve 200 2MB hugepage'
|
|
+echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
|
|
+
|
|
+echo '# Test no option hugepageedit'
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log1 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log1 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test hugepageedit -d option'
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log2 2>&1
|
|
+check_hugepage_mmap ${testroot}/log2 && rc=1 || rc=0
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test hugepageedit -x option'
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit -x ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log3 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log3 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test Non-ELF file'
|
|
+dd if=/dev/urandom of=${testroot}/test.file count=1024 bs=1024
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/test.file 2>&1 && result=1
|
|
+
|
|
+echo '# Test ELF phnum is 0'
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-update-ehdr ${testroot}/tst-use-hugepage1 0 2>&1 || result=1
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/tst-use-hugepage1 2>&1 && result=1
|
|
+
|
|
+echo '# Test ELF phnum is 0xFFFF'
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-update-ehdr ${testroot}/tst-use-hugepage1 65535 2>&1 || result=1
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/tst-use-hugepage1 2>&1 && result=1
|
|
+
|
|
+exit $result
|
|
diff --git a/elf/tst-ld-hugepage-env.sh b/elf/tst-ld-hugepage-env.sh
|
|
new file mode 100644
|
|
index 00000000..e16ada67
|
|
--- /dev/null
|
|
+++ b/elf/tst-ld-hugepage-env.sh
|
|
@@ -0,0 +1,108 @@
|
|
+#!/bin/sh
|
|
+# Test that ld.so can handle different env input
|
|
+# Copyright (C) 2021-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
|
|
+# <http://www.gnu.org/licenses/>.
|
|
+
|
|
+set -ex
|
|
+echo "source $4"
|
|
+source $4
|
|
+
|
|
+common_objpfx=$1
|
|
+test_wrapper=$2
|
|
+test_wrapper_env=$3
|
|
+result=0
|
|
+
|
|
+excption_handle ()
|
|
+{
|
|
+ echo "ld.so hugepage feature is not behaving as expected"
|
|
+ result=1
|
|
+}
|
|
+
|
|
+testroot="${common_objpfx}elf/ld-hugepage-env-directory"
|
|
+
|
|
+rm -rf "$testroot"
|
|
+mkdir -p $testroot
|
|
+
|
|
+echo '# reseve 200 2MB hugepage'
|
|
+echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
|
|
+
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod2.so || exit 1
|
|
+
|
|
+echo '# Test HUGEPAGE_PROBE env set 1 and shared object is not hugepageedited'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log1 2>&1
|
|
+check_hugepage_mmap ${testroot}/log1 && rc=1 || rc=0
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test LD_HUGEPAGE_LIB env set 1 and shared object is not hugepageedited'
|
|
+${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log2 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log2 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test LD_HUGEPAGE_LIB env set 100 and shared object is not hugepageedited'
|
|
+${test_wrapper_env} LD_HUGEPAGE_LIB=100 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log3 2>&1
|
|
+check_hugepage_mmap ${testroot}/log3 && rc=1 || rc=0
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test LD_HUGEPAGE_LIB env set -8 and shared object is not hugepageedited'
|
|
+${test_wrapper_env} LD_HUGEPAGE_LIB=-8 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log4 2>&1
|
|
+check_hugepage_mmap ${testroot}/log4 && rc=1 || rc=0
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test LD_HUGEPAGE_LIB env set aa#_bb and shared object is not hugepageedited'
|
|
+${test_wrapper_env} LD_HUGEPAGE_LIB=aa#_bb LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log5 2>&1
|
|
+check_hugepage_mmap ${testroot}/log5 && rc=1 || rc=0
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod2.so || exit 1
|
|
+echo '# Test HUGEPAGE_PROBE env set 2 and shared object is hugepageedited'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=2 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log6 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log6 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test HUGEPAGE_PROBE env set -2 and shared object is hugepageedited'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=-2 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log7 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log7 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test HUGEPAGE_PROBE env set 0 and shared object is hugepageedited'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=0 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log8 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log8 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test HUGEPAGE_PROBE env set 3.14 and shared object is hugepageedited'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=3.14 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log9 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log9 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# Test HUGEPAGE_PROBE env set #aabb and shared object is hugepageedited'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=#aabb LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log10 2>&1
|
|
+check_hugepage_mmap_success ${testroot}/log10 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+exit $result
|
|
diff --git a/elf/tst-ld-hugepage-fallback.sh b/elf/tst-ld-hugepage-fallback.sh
|
|
new file mode 100644
|
|
index 00000000..0c616633
|
|
--- /dev/null
|
|
+++ b/elf/tst-ld-hugepage-fallback.sh
|
|
@@ -0,0 +1,66 @@
|
|
+#!/bin/sh
|
|
+# Test that ld.so can fallback to original shared object load process when
|
|
+# exception happens
|
|
+# Copyright (C) 2021-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
|
|
+# <http://www.gnu.org/licenses/>.
|
|
+
|
|
+echo "source $4"
|
|
+source $4
|
|
+
|
|
+common_objpfx=$1
|
|
+test_wrapper=$2
|
|
+test_wrapper_env=$3
|
|
+result=0
|
|
+
|
|
+excption_handle ()
|
|
+{
|
|
+ echo "ld.so hugepage feature should fallback this time"
|
|
+ result=1
|
|
+}
|
|
+
|
|
+testroot="${common_objpfx}elf/ld-hugepage-fallback"
|
|
+
|
|
+rm -rf "$testroot"
|
|
+mkdir -p $testroot
|
|
+
|
|
+echo '# reseve 200 2MB hugepage'
|
|
+echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
|
|
+
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1
|
|
+
|
|
+echo '# tst-update-phdr make shared object previous PT_LOAD segment vma > next'
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-update-phdr ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1
|
|
+
|
|
+echo '# Test LD_HUGEPAGE_LIB env set 1 and shared object is not hugepageedited'
|
|
+${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage3 > ${testroot}/log1 2>&1
|
|
+check_hugepage_fallback ${testroot}/log1 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+echo '# hugepageedit shared object'
|
|
+${test_wrapper_env} \
|
|
+${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1
|
|
+
|
|
+echo '# Test HUGEPAGE_PROBE env set 1 and shared object is hugepageedited'
|
|
+${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage3 > ${testroot}/log2 2>&1
|
|
+check_hugepage_fallback ${testroot}/log2 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle
|
|
+
|
|
+exit $result
|
|
diff --git a/elf/tst-ld-hugepage-mmap-smaps.sh b/elf/tst-ld-hugepage-mmap-smaps.sh
|
|
new file mode 100644
|
|
index 00000000..b817ab53
|
|
--- /dev/null
|
|
+++ b/elf/tst-ld-hugepage-mmap-smaps.sh
|
|
@@ -0,0 +1,49 @@
|
|
+#!/bin/sh
|
|
+# Test that ld.so mmapping hugepage is consistent with the actual process occupancy
|
|
+# Copyright (C) 2021-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
|
|
+# <http://www.gnu.org/licenses/>.
|
|
+
|
|
+set -ex
|
|
+echo "source $4"
|
|
+source $4
|
|
+
|
|
+common_objpfx=$1
|
|
+test_wrapper=$2
|
|
+test_wrapper_env=$3
|
|
+result=0
|
|
+
|
|
+excption_handle ()
|
|
+{
|
|
+ echo "ld.so mmap hugepage is not consistent with the actual process occupancy, return $1"
|
|
+ result=1
|
|
+}
|
|
+
|
|
+testroot="${common_objpfx}elf/ld-hugepage-mmap-smaps"
|
|
+
|
|
+rm -rf "$testroot"
|
|
+mkdir -p $testroot
|
|
+
|
|
+echo '# reseve 200 2MB hugepage'
|
|
+echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
|
|
+
|
|
+echo '# Test LD_HUGEPAGE_LIB=1 whether ld.so mmap hugepage is consistent with the actual process occupancy'
|
|
+${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
|
|
+${test_wrapper} ${common_objpfx}elf/tst-use-hugepage4 > ${testroot}/log1 2>&1
|
|
+check_hugepage_mmap_detail ${testroot}/log1 && rc=0 || rc=$?
|
|
+test $rc -eq 0 || excption_handle $rc
|
|
+
|
|
+exit $result
|
|
diff --git a/elf/tst-ld-hugepage.h b/elf/tst-ld-hugepage.h
|
|
new file mode 100644
|
|
index 00000000..30e938da
|
|
--- /dev/null
|
|
+++ b/elf/tst-ld-hugepage.h
|
|
@@ -0,0 +1,7 @@
|
|
+#ifndef TST_HUGEPAGE_H
|
|
+#define TST_HUGEPAGE_H
|
|
+
|
|
+extern void huge_func(void);
|
|
+extern int huge_global;
|
|
+
|
|
+#endif
|
|
diff --git a/elf/tst-ld-hugepagemod.c b/elf/tst-ld-hugepagemod.c
|
|
new file mode 100644
|
|
index 00000000..70c42e5a
|
|
--- /dev/null
|
|
+++ b/elf/tst-ld-hugepagemod.c
|
|
@@ -0,0 +1,19 @@
|
|
+#include <stdio.h>
|
|
+
|
|
+#define BIN_PATH OBJDIR"/tst-ld-hugepage-bin.o"
|
|
+
|
|
+int huge_global;
|
|
+
|
|
+asm (".section .rodata\n\t" \
|
|
+ ".globl vvvdso_start, vvvdso_end\n" \
|
|
+ ".balign 4096\n" \
|
|
+ "vvvdso_start:\n\t" \
|
|
+ ".incbin " "\""BIN_PATH"\"" "\n\t" \
|
|
+ ".balign 4096\n" \
|
|
+ "vvvdso_end:\n\t" \
|
|
+ ".previous");
|
|
+
|
|
+void huge_func(void)
|
|
+{
|
|
+ printf("In huge_func, huge_global = %d\n", huge_global);
|
|
+}
|
|
diff --git a/elf/tst-update-ehdr.c b/elf/tst-update-ehdr.c
|
|
new file mode 100644
|
|
index 00000000..6d653aa0
|
|
--- /dev/null
|
|
+++ b/elf/tst-update-ehdr.c
|
|
@@ -0,0 +1,58 @@
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <elf.h>
|
|
+#include <fcntl.h>
|
|
+#include <limits.h>
|
|
+#include <errno.h>
|
|
+#include <unistd.h>
|
|
+#include <sys/stat.h>
|
|
+#include "tst-get-ephdr.h"
|
|
+
|
|
+#define TOOL_NAME "tst-update-ehdr"
|
|
+
|
|
+void print_usage(void)
|
|
+{
|
|
+ fprintf(stderr, "%s <ELF file> <phdr number>\n", TOOL_NAME);
|
|
+}
|
|
+
|
|
+int main(int argc, char **argv)
|
|
+{
|
|
+ size_t length;
|
|
+ int exit_status = EXIT_FAILURE;
|
|
+
|
|
+ if (argc != 3)
|
|
+ {
|
|
+ print_usage();
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ int fd = open(argv[1], O_RDWR);
|
|
+ if (fd < 0)
|
|
+ {
|
|
+ perror("open");
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ void *ehdr = get_ehdr(fd, &length);
|
|
+ if (ehdr == NULL)
|
|
+ goto close_fd;
|
|
+
|
|
+ char *endptr;
|
|
+ unsigned long val = strtoul(argv[2], &endptr, 10);
|
|
+ if ((errno == ERANGE && val == ULONG_MAX) || (errno != 0 && val == 0))
|
|
+ {
|
|
+ perror("strtoul");
|
|
+ goto unmap;
|
|
+ }
|
|
+
|
|
+ ((ElfW(Ehdr) *)ehdr)->e_phnum = val;
|
|
+ exit_status = EXIT_SUCCESS;
|
|
+
|
|
+unmap:
|
|
+ munmap(ehdr, length);
|
|
+
|
|
+close_fd:
|
|
+ close(fd);
|
|
+
|
|
+ exit(exit_status);
|
|
+}
|
|
diff --git a/elf/tst-update-phdr.c b/elf/tst-update-phdr.c
|
|
new file mode 100644
|
|
index 00000000..bd3e30eb
|
|
--- /dev/null
|
|
+++ b/elf/tst-update-phdr.c
|
|
@@ -0,0 +1,93 @@
|
|
+/* construct exception PT_LOAD segment VMA
|
|
+ make previous PT_LOAD vma > next PT_LOAD vma
|
|
+ Copyright (C) 2021-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
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <fcntl.h>
|
|
+#include <string.h>
|
|
+#include <unistd.h>
|
|
+#include <elf.h>
|
|
+#include <link.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/mman.h>
|
|
+#include <sys/types.h>
|
|
+#include "tst-get-ephdr.h"
|
|
+
|
|
+#define TOOL_NAME "tst-update-phdr"
|
|
+#define PAGE_SIZE 0x1000
|
|
+
|
|
+void print_usage(void)
|
|
+{
|
|
+ fprintf(stderr, "%s <ELF file>\n", TOOL_NAME);
|
|
+}
|
|
+
|
|
+int main(int argc, char **argv)
|
|
+{
|
|
+ size_t length;
|
|
+ int exit_status = EXIT_FAILURE;
|
|
+ int i;
|
|
+ if (argc != 2)
|
|
+ {
|
|
+ print_usage();
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ int fd = open(argv[1], O_RDWR);
|
|
+ if (fd < 0)
|
|
+ {
|
|
+ perror("open");
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+
|
|
+ void *ehdr = get_ehdr(fd, &length);
|
|
+ if (ehdr == NULL)
|
|
+ goto close_fd;
|
|
+
|
|
+ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length);
|
|
+ if (phdr == NULL)
|
|
+ goto unmap;
|
|
+
|
|
+ ElfW(Phdr) *prev =NULL, *next = NULL;
|
|
+ for (i = 0; i < ((ElfW(Ehdr) *)ehdr)->e_phnum; i++)
|
|
+ {
|
|
+ if (prev != NULL && next != NULL)
|
|
+ break;
|
|
+ if (phdr[i].p_type == PT_LOAD)
|
|
+ {
|
|
+ if (prev == NULL)
|
|
+ prev = &phdr[i];
|
|
+ else
|
|
+ next = &phdr[i];
|
|
+ }
|
|
+ }
|
|
+ if (prev != NULL && next != NULL)
|
|
+ {
|
|
+ prev->p_vaddr = next->p_vaddr + PAGE_SIZE;
|
|
+ exit_status = EXIT_SUCCESS;
|
|
+ }
|
|
+ else
|
|
+ fprintf(stderr, "There are no PT_LOADs in %s\n", argv[1]);
|
|
+
|
|
+unmap:
|
|
+ munmap(ehdr, length);
|
|
+
|
|
+close_fd:
|
|
+ close(fd);
|
|
+
|
|
+ exit(exit_status);
|
|
+}
|
|
diff --git a/elf/tst-use-hugepage.c b/elf/tst-use-hugepage.c
|
|
new file mode 100644
|
|
index 00000000..938e0afc
|
|
--- /dev/null
|
|
+++ b/elf/tst-use-hugepage.c
|
|
@@ -0,0 +1,15 @@
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <unistd.h>
|
|
+#include "tst-ld-hugepage.h"
|
|
+
|
|
+int main(void)
|
|
+{
|
|
+ char command[100];
|
|
+ sprintf(command, "cat /proc/%d/smaps", getpid());
|
|
+ system(command);
|
|
+ huge_func();
|
|
+ huge_global = 1;
|
|
+ huge_func();
|
|
+ return 0;
|
|
+}
|
|
--
|
|
2.31.1
|
|
|