Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[manylinux2014] arm64 patchelf alignment fix #739

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docker/build_scripts/build_utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ function build_patchelf {
curl -fsSL -o patchelf.tar.gz https://github.com/NixOS/patchelf/archive/$patchelf_version.tar.gz
check_sha256sum patchelf.tar.gz $patchelf_hash
tar -xzf patchelf.tar.gz
(cd patchelf-$patchelf_version && ./bootstrap.sh && do_standard_install)
# Apply aarch64 alignment fix patch until version >0.11 of patchelf is released
(cd patchelf-$patchelf_version && patch -p1 -i "$src_dir"/patches/patchelf-fix-default-aarch64-alignment.patch && ./bootstrap.sh && do_standard_install)
rm -rf patchelf.tar.gz patchelf-$patchelf_version
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
From cb700613dea85ba7f0f04214cdda80ae2eb92393 Mon Sep 17 00:00:00 2001
From: Pierre Bourdon <[email protected]>
Date: Sat, 20 Jun 2020 01:46:23 +0200
Subject: [PATCH] Improve the default section alignment choice

Currently patchelf uses the host system's page size (determined at build
time) as the default section load memory alignment. This causes multiple
issues

- Cross-compilation: when using patchelf on ELFs targetting a different
architecture from the host, the host page size is still used by
default.

- Variable page size architectures: ARMv8 systems can be configured in
either 4K, 16K, or 64K page size mode depending on kernel
configuration. An ARMv8 patchelf built on a 4K page size system will
end up creating ELFs that cannot be used on a 64K page size system.

- Reproducibility: the page size of the machine that built patchelf
"leaks" into the binary.

The build time --with-page-size as well as the run time --page-size
options can be used to work around some of these issues. But it's much
better to have patchelf do the right thing without explicit
configuration.

This commit adds support for inferring page size from the ELF header's
"machine" field. The default values are extracted from GNU gold's source
code. Note that both --with-page-size as well as --page-size continue to
work and take precedence on the default value.
---
configure.ac | 14 +++++---------
src/patchelf.cc | 43 ++++++++++++++++++++++++++++++++-----------
2 files changed, 37 insertions(+), 20 deletions(-)

diff --git a/configure.ac b/configure.ac
index c2e5e98..7a72b40 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,19 +6,15 @@ AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2 foreign color-tests serial-tests])
AM_PROG_CC_C_O
AC_PROG_CXX

-PAGESIZE=auto
+DEFAULT_PAGESIZE=auto
AC_ARG_WITH([page-size],
AS_HELP_STRING([--with-page-size=SIZE], [Specify default pagesize (default auto)]),
- PAGESIZE=$withval
+ DEFAULT_PAGESIZE=$withval
)

-if test "$PAGESIZE" = auto; then
- if command -v getconf >/dev/null; then
- PAGESIZE=$(getconf PAGESIZE || getconf PAGE_SIZE)
- fi
- if test "$PAGESIZE" = auto -o -z "$PAGESIZE"; then
- PAGESIZE=4096
- fi
+if test "$DEFAULT_PAGESIZE" != auto; then
+ AC_DEFINE_UNQUOTED(DEFAULT_PAGESIZE, ${DEFAULT_PAGESIZE})
+ AC_MSG_RESULT([Setting page size to ${DEFAULT_PAGESIZE}])
fi

AC_DEFINE_UNQUOTED(PAGESIZE, ${PAGESIZE})
diff --git a/src/patchelf.cc b/src/patchelf.cc
index 965686a..dfca258 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -48,7 +48,11 @@ static bool forceRPath = false;
static std::vector<std::string> fileNames;
static std::string outputFileName;
static bool alwaysWrite = false;
-static int pageSize = PAGESIZE;
+#ifdef DEFAULT_PAGESIZE
+static int forcedPageSize = DEFAULT_PAGESIZE;
+#else
+static int forcedPageSize = -1;
+#endif

typedef std::shared_ptr<std::vector<unsigned char>> FileContents;

@@ -81,12 +85,6 @@ static bool hasAllowedPrefix(const std::string & s, const std::vector<std::strin
}


-static unsigned int getPageSize()
-{
- return pageSize;
-}
-
-
template<ElfFileParams>
class ElfFile
{
@@ -161,6 +159,8 @@ private:

friend struct CompShdr;

+ unsigned int getPageSize() const;
+
void sortShdrs();

void shiftFile(unsigned int extraPages, Elf_Addr startPage);
@@ -444,6 +444,29 @@ ElfFile<ElfFileParamNames>::ElfFile(FileContents fileContents)
}


+template<ElfFileParams>
+unsigned int ElfFile<ElfFileParamNames>::getPageSize() const
+{
+ if (forcedPageSize > 0)
+ return forcedPageSize;
+
+ // Architectures (and ABIs) can have different minimum section alignment
+ // requirements. There is no authoritative list of these values. The
+ // current list is extracted from GNU gold's source code (abi_pagesize).
+ switch (hdr->e_machine) {
+ case EM_SPARC:
+ case EM_MIPS:
+ case EM_PPC:
+ case EM_PPC64:
+ case EM_AARCH64:
+ case EM_TILEGX:
+ return 0x10000;
+ default:
+ return 0x1000;
+ }
+}
+
+
template<ElfFileParams>
void ElfFile<ElfFileParamNames>::sortPhdrs()
{
@@ -1613,8 +1636,6 @@ static void patchElf()
if (!printInterpreter && !printRPath && !printSoname && !printNeeded)
debug("patching ELF file '%s'\n", fileName.c_str());

- debug("Kernel page size is %u bytes\n", getPageSize());
-
auto fileContents = readFile(fileName);
std::string outputFileName2 = outputFileName.empty() ? fileName : outputFileName;

@@ -1670,8 +1691,8 @@ int mainWrapped(int argc, char * * argv)
}
else if (arg == "--page-size") {
if (++i == argc) error("missing argument");
- pageSize = atoi(argv[i]);
- if (pageSize <= 0) error("invalid argument to --page-size");
+ forcedPageSize = atoi(argv[i]);
+ if (forcedPageSize <= 0) error("invalid argument to --page-size");
}
else if (arg == "--print-interpreter") {
printInterpreter = true;
--
2.23.3