summaryrefslogtreecommitdiff
path: root/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2024-08-03 06:28:41 +0000
committerCoprDistGit <infra@openeuler.org>2024-08-03 06:28:41 +0000
commitd20db0561a6a36f914fde030512503b114ef9a0c (patch)
treed4e5e3494d95c269a1cee6195f11bf3201bcadbf /0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch
parent016343d99b1b269d7246ef1e143d4b54914433d4 (diff)
Diffstat (limited to '0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch')
-rw-r--r--0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch1177
1 files changed, 1177 insertions, 0 deletions
diff --git a/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch b/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch
new file mode 100644
index 0000000..9442241
--- /dev/null
+++ b/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch
@@ -0,0 +1,1177 @@
+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
+