From 1fa8e23048e6e6f98456f083793b62f9c21e83b6 Mon Sep 17 00:00:00 2001 From: Geoffrey Blake Date: Thu, 20 Aug 2020 16:42:21 +0000 Subject: [PATCH 1/2] Add patchelf diff for v0.11 that fixes bad alignment issues on AArch64 machines with 64k pages. - Based on https://github.com/NixOS/patchelf/commit/0470d6921b5a3fe8e92e356c8e11d120dbbb06c0 Can be removed once a new version of patchelf is released containing the above commit. --- ...tchelf-fix-default-aarch64-alignment.patch | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 docker/build_scripts/patches/patchelf-fix-default-aarch64-alignment.patch diff --git a/docker/build_scripts/patches/patchelf-fix-default-aarch64-alignment.patch b/docker/build_scripts/patches/patchelf-fix-default-aarch64-alignment.patch new file mode 100644 index 00000000..a491003e --- /dev/null +++ b/docker/build_scripts/patches/patchelf-fix-default-aarch64-alignment.patch @@ -0,0 +1,156 @@ +From cb700613dea85ba7f0f04214cdda80ae2eb92393 Mon Sep 17 00:00:00 2001 +From: Pierre Bourdon +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 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> FileContents; + +@@ -81,12 +85,6 @@ static bool hasAllowedPrefix(const std::string & s, const std::vector + 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::ElfFile(FileContents fileContents) + } + + ++template ++unsigned int ElfFile::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 + void ElfFile::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 + From 470f25c2919587db7e40a942cf427c36fb0ce8d2 Mon Sep 17 00:00:00 2001 From: Geoffrey Blake Date: Thu, 20 Aug 2020 16:42:45 +0000 Subject: [PATCH 2/2] Update build_patchelf() in docker/build_utils.sh to apply alignment fix patch to 0.11 release. --- docker/build_scripts/build_utils.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/build_scripts/build_utils.sh b/docker/build_scripts/build_utils.sh index bd3fbfb8..7829fdea 100755 --- a/docker/build_scripts/build_utils.sh +++ b/docker/build_scripts/build_utils.sh @@ -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 }