From 03746bff2c3b1617923d2c52f586ace23d9018a2 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Aug 2025 14:54:44 -0400 Subject: [PATCH 01/30] Backport infra improvements from master to 0.15 This is the version currently used in Nixpkgs as the stable version, so I am interested in seeing it be developable, even as the hope is to move to a newer version. --- .editorconfig | 26 + .git-blame-ignore-revs | 2 + .github/dependabot.yml | 6 + .github/workflows/ci.yml | 12 +- .github/workflows/publish.yml | 83 +- .gitignore | 3 + .mergify.yml | 26 + CMakeLists.txt | 14 + COPYING | 8 +- README.md | 29 +- configure.ac | 10 + default.nix | 2 +- flake.lock | 60 +- flake.nix | 340 +++++++-- m4/ax_cxx_compile_stdcxx.m4 | 1009 +++++++++++++++++++++++++ maintainers/flake-module.nix | 96 +++ maintainers/format.sh | 16 + meson.build | 31 + meson.format | 7 + meson.options | 7 + patchelf.nix => package-autotools.nix | 7 +- package-cmake.nix | 17 + package-meson.nix | 17 + patchelf.1 | 2 +- src/CMakeLists.txt | 12 + src/Makefile.am | 2 +- src/meson.build | 18 + 27 files changed, 1748 insertions(+), 114 deletions(-) create mode 100644 .editorconfig create mode 100644 .git-blame-ignore-revs create mode 100644 .github/dependabot.yml create mode 100644 .mergify.yml create mode 100644 CMakeLists.txt create mode 100644 m4/ax_cxx_compile_stdcxx.m4 create mode 100644 maintainers/flake-module.nix create mode 100755 maintainers/format.sh create mode 100644 meson.build create mode 100644 meson.format create mode 100644 meson.options rename patchelf.nix => package-autotools.nix (71%) create mode 100644 package-cmake.nix create mode 100644 package-meson.nix create mode 100644 src/CMakeLists.txt create mode 100644 src/meson.build diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..142250dc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +# EditorConfig configuration for PatchELF +# http://EditorConfig.org + +# Top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file, UTF-8 charset +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +# Match Nix files, set indent to spaces with width of two +[*.nix] +indent_style = space +indent_size = 2 + +# Match C++/C/shell, set indent to spaces with width of four +[*.{hpp,cc,hh,c,h,sh}] +indent_style = space +indent_size = 4 + +# Match diffs, avoid to trim trailing whitespace +[*.{diff,patch}] +trim_trailing_whitespace = false diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..1392aa88 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Manual nixfmt run +706478750fc8574ed816ef746d3ad3790b2ea66a diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..5ace4600 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9790cfb..39eea409 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,18 +1,24 @@ name: "CI" on: pull_request: + merge_group: push: jobs: + shellcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: shellcheck tests/*.sh nix: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: cachix/install-nix-action@v13 + - uses: actions/checkout@v4 + - uses: cachix/install-nix-action@v31 - run: nix-build -A hydraJobs.release ubuntu: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: get toolchain version run: | c++ --version diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b6d66853..624eae2e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,6 +1,7 @@ name: Publish on: pull_request: + merge_group: push: branches: - '*' @@ -13,34 +14,79 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 - - uses: cachix/install-nix-action@v13 + uses: actions/checkout@v4 + - uses: cachix/install-nix-action@v31 - name: Build tarballs run: | - nix-build -A hydraJobs.tarball + nix build -L .#hydraJobs.tarball install -D ./result/tarballs/*.tar.bz2 ./dist/patchelf-$(cat version).tar.bz2 install -D ./result/tarballs/*.tar.gz ./dist/patchelf-$(cat version).tar.gz - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 with: - name: patchelf + name: patchelf-tarball path: dist/* - build_binaries: + build_windows: + name: Build windows executable + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - uses: cachix/install-nix-action@v31 + - name: Build windows executable + run: | + nix build -L .#patchelf-win32 .#patchelf-win64 + install -D ./result/bin/patchelf.exe ./dist/patchelf-win32-$(cat version).exe + install -D ./result-1/bin/patchelf.exe ./dist/patchelf-win64-$(cat version).exe + - uses: actions/upload-artifact@v4 + with: + name: patchelf-windows + path: dist/* + + test_windows: + name: Test windows binaries + needs: [build_windows] + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v5 + with: + name: patchelf-windows + path: dist + - name: Show binaries + run: dir .\\dist + - name: Test windows 64-bit binary + run: .\\dist\\patchelf-win32-*.exe --version + + - name: Test windows 32-bit binary + run: .\\dist\\patchelf-win64-*.exe --version + + build_musl: name: Build static musl binaries needs: [build_tarballs] runs-on: ubuntu-latest strategy: fail-fast: false matrix: - platform: ["amd64", "i386", "ppc64le", "arm64v8", "arm32v7", "s390x"] + platform: ["amd64", "i386", "ppc64le", "arm64v8", "arm32v7", "s390x", "riscv64"] steps: - name: Set up QEMU if: matrix.platform != 'amd64' - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v3 + + - name: Set docker arch + run: | + platform=${{ matrix.platform }} + if [[ $platform == arm64v8 ]]; then + platform=arm64 + elif [[ $platform == arm32v7 ]]; then + platform=arm + fi + echo "DOCKER_PLATFORM=$platform" >> $GITHUB_ENV - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v5 with: - name: patchelf + name: patchelf-tarball path: dist - name: Build binaries env: @@ -54,7 +100,7 @@ jobs: rm -f dist/* cd patchelf-* ./configure --prefix /patchelf - make check + make check || (cat tests/test-suite.log; exit 1) make install-strip cd - tar -czf ./dist/patchelf-\$(cat patchelf-*/version)-\$(uname -m).tar.gz -C /patchelf . @@ -65,7 +111,7 @@ jobs: else ENTRYPOINT= fi - docker run -e CXXFLAGS -v $(pwd):/gha ${{ matrix.platform }}/alpine:3.15 ${ENTRYPOINT} sh -ec "cd /gha && sh ./build.sh" + docker run --platform "$DOCKER_PLATFORM" -e CXXFLAGS -v $(pwd):/gha ${{ matrix.platform }}/alpine:edge ${ENTRYPOINT} sh -ec "cd /gha && sh ./build.sh" - name: Check binaries run: | cat < check.sh @@ -74,21 +120,22 @@ jobs: tar -xf ./dist/patchelf-*-*.tar.gz ./bin/patchelf --version EOF - docker run -v $(pwd):/gha ${{ matrix.platform }}/debian:stable-slim sh -ec "cd /gha && sh ./check.sh" - - uses: actions/upload-artifact@v2 + docker run --platform "$DOCKER_PLATFORM" -v $(pwd):/gha ${{ matrix.platform }}/debian:unstable-slim sh -ec "cd /gha && sh ./check.sh" + - uses: actions/upload-artifact@v4 with: - name: patchelf + name: patchelf-${{ matrix.platform }} path: dist/* publish: name: Publish tarballs & binaries - needs: [build_tarballs, build_binaries] + needs: [build_tarballs, build_windows, build_musl] if: github.event_name == 'push' && github.repository == 'NixOS/patchelf' && startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v5 with: - name: patchelf + pattern: patchelf-* + merge-multiple: true path: dist - name: Upload binaries to release uses: svenstaro/upload-release-action@v2 diff --git a/.gitignore b/.gitignore index c3f60a5d..df440b64 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,8 @@ Makefile .deps *.o +CMakeLists.txt.user + /tests/*.log /tests/*.trs /tests/no-rpath @@ -32,6 +34,7 @@ Makefile /tests/libbig-dynstr.debug /tests/contiguous-note-sections /tests/simple-pie +/tests/simple-execstack .direnv/ .vscode/ diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 00000000..442f64ef --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,26 @@ +queue_rules: + - name: default + merge_conditions: + - check-success=Build static musl binaries (amd64) + - check-success=Build static musl binaries (arm32v7) + - check-success=Build static musl binaries (arm64v8) + - check-success=Build static musl binaries (i386) + - check-success=Build static musl binaries (ppc64le) + - check-success=Build static musl binaries (riscv64) + - check-success=Build static musl binaries (s390x) + - check-success=Build tarballs + - check-success=Build windows executable + - check-success=Publish tarballs & binaries + - check-success=Test windows binaries + - check-success=nix + - check-success=shellcheck + - check-success=ubuntu + merge_method: rebase + batch_size: 5 +pull_request_rules: + - name: merge using the merge queue + conditions: + - base=master + - label~=merge-queue|dependencies + actions: + queue: {} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..6957362d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.5) + +project(patchelf) + +file(READ version VERSION) + +include(GNUInstallDirs) + +add_subdirectory(src) +# add_subdirectory(tests) # TODO + +install(FILES patchelf.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) + +install(FILES README.md DESTINATION ${CMAKE_INSTALL_DOCDIR}) diff --git a/COPYING b/COPYING index 94a9ed02..e6000869 100644 --- a/COPYING +++ b/COPYING @@ -1,7 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found. GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see . + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see -. +. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. +. diff --git a/README.md b/README.md index e0a2e3a0..6e2d112a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# PatchELF + PatchELF is a simple utility for modifying existing ELF executables and libraries. In particular, it can do the following: @@ -70,7 +72,7 @@ libraries. In particular, it can do the following: ## Compiling and Testing -### Via Autotools +### Via [GNU Autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html) ```console ./bootstrap.sh ./configure @@ -78,6 +80,27 @@ make make check sudo make install ``` + +### Via [CMake](https://cmake.org/) (and [Ninja](https://ninja-build.org/)) + +```console +mkdir build +cd build +cmake .. -GNinja +ninja all +sudo ninja install +``` + +### Via [Meson](https://mesonbuild.com/) (and [Ninja](https://ninja-build.org/)) + +```console +mkdir build +meson configure build +cd build +ninja all +sudo ninja install +``` + ### Via Nix You can build with Nix in several ways. @@ -86,6 +109,10 @@ You can build with Nix in several ways. 2. You can launch a development environment with `nix develop` and follow the autotools steps above. If you would like to develop with _musl_ try `nix develop .#musl` +## Help and resources + +- Matrix: [#patchelf:nixos.org](https://matrix.to/#/#patchelf:nixos.org) + ## Author Copyright 2004-2019 Eelco Dolstra . diff --git a/configure.ac b/configure.ac index 73156fc9..fee6302f 100644 --- a/configure.ac +++ b/configure.ac @@ -3,11 +3,19 @@ AC_INIT([patchelf], m4_esyscmd([printf $(cat ./version)])) AC_CONFIG_SRCDIR([src/patchelf.cc]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([1.11.1 -Wall -Werror dist-bzip2 foreign color-tests parallel-tests]) +AC_CONFIG_MACRO_DIR([m4]) AC_CHECK_TOOL([STRIP], [strip]) +# Those are only used in tests, hence we gracefully degrate if they are not found. +AC_CHECK_TOOL([NM], [nm], [nm]) +AC_CHECK_TOOL([OBJDUMP], [objdump], [objdump]) +AC_CHECK_TOOL([OBJCOPY], [objcopy], [objcopy]) +AC_CHECK_TOOL([READELF], [readelf], [readelf]) +AC_CHECK_TOOL([STRINGS], [strings], [strings]) AM_PROG_CC_C_O AC_PROG_CXX +AC_LANG([C++]) AM_PROG_AS DEFAULT_PAGESIZE=auto @@ -26,6 +34,8 @@ AC_ARG_WITH([asan], ) AM_CONDITIONAL([WITH_ASAN], [test x"$with_asan" = xyes]) +AX_CXX_COMPILE_STDCXX([17], [noext], []) + AC_ARG_WITH([ubsan], AS_HELP_STRING([--with-ubsan], [Build with undefined behavior sanitizer]) ) diff --git a/default.nix b/default.nix index 71d1a80a..00ec5b61 100644 --- a/default.nix +++ b/default.nix @@ -1,3 +1,3 @@ -(import (fetchTarball https://github.com/edolstra/flake-compat/archive/master.tar.gz) { +(import (fetchTarball "https://github.com/edolstra/flake-compat/archive/master.tar.gz") { src = ./.; }).defaultNix diff --git a/flake.lock b/flake.lock index 567877e2..3e2769b8 100644 --- a/flake.lock +++ b/flake.lock @@ -1,22 +1,70 @@ { "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1733312601, + "narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "git-hooks-nix": { + "inputs": { + "flake-compat": [], + "gitignore": [], + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1734279981, + "narHash": "sha256-NdaCraHPp8iYMWzdXAt5Nv6sA3MUzlCiGiR586TCwo0=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "aa9f40c906904ebd83da78e7f328cd8aeaeae785", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1637875414, - "narHash": "sha256-Ica++SXFuLyxX9Q7YxhfZulUif6/gwM8AEQYlUxqSgE=", + "lastModified": 1731763621, + "narHash": "sha256-ddcX4lQL0X05AYkrkV2LMFgGdRvgap7Ho8kgon3iWZk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3bea86e918d8b54aa49780505d2d4cd9261413be", + "rev": "c69a9bffbecde46b4b939465422ddc59493d3e4d", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "nixos-21.05", - "type": "indirect" + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" } }, "root": { "inputs": { + "flake-parts": "flake-parts", + "git-hooks-nix": "git-hooks-nix", "nixpkgs": "nixpkgs" } } diff --git a/flake.nix b/flake.nix index 8c3988c5..726836c4 100644 --- a/flake.nix +++ b/flake.nix @@ -1,111 +1,295 @@ { description = "A tool for modifying ELF executables and libraries"; - inputs.nixpkgs.url = "nixpkgs/nixos-21.05"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - outputs = { self, nixpkgs }: + # dev tooling + inputs.flake-parts.url = "github:hercules-ci/flake-parts"; + inputs.git-hooks-nix.url = "github:cachix/git-hooks.nix"; + # work around https://github.com/NixOS/nix/issues/7730 + inputs.flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; + inputs.git-hooks-nix.inputs.nixpkgs.follows = "nixpkgs"; + inputs.git-hooks-nix.inputs.nixpkgs-stable.follows = "nixpkgs"; + # work around 7730 and https://github.com/NixOS/nix/issues/7807 + inputs.git-hooks-nix.inputs.flake-compat.follows = ""; + inputs.git-hooks-nix.inputs.gitignore.follows = ""; + + outputs = + inputs@{ self, nixpkgs, ... }: let - supportedSystems = [ "x86_64-linux" "i686-linux" "aarch64-linux" ]; - forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system); + inherit (nixpkgs) lib; - nixpkgsFor = forAllSystems (system: - import nixpkgs { - inherit system; - overlays = [ self.overlay ]; - } - ); - version = builtins.readFile ./version; - pkgs = nixpkgsFor.${"x86_64-linux"}; - in + supportedSystems = [ + "x86_64-linux" + "i686-linux" + "aarch64-linux" + ]; + forAllSystems = lib.genAttrs supportedSystems; - { - overlay = final: prev: { - patchelf-new-musl = final.pkgsMusl.callPackage ./patchelf.nix { - inherit version; - src = self; - }; - patchelf-new = final.callPackage ./patchelf.nix { + version = lib.removeSuffix "\n" (builtins.readFile ./version); + pkgs = nixpkgs.legacyPackages.x86_64-linux; + + baseSrcFiles = [ + ./COPYING + ./README.md + ./patchelf.1 + ./patchelf.spec.in + (lib.fileset.difference ./src ( + lib.fileset.unions [ + ./src/Makefile.am + ./src/CMakeLists.txt + ./src/meson.build + ] + )) + (lib.fileset.difference ./tests ( + lib.fileset.unions [ + ./tests/Makefile.am + #./tests/CMakeLists.txt + #./tests/meson.build + ] + )) + ./version + ]; + + autotoolsSrcFiles = [ + ./Makefile.am + ./src/Makefile.am + ./tests/Makefile.am + ./configure.ac + ./m4 + ]; + + cmakeSrcFiles = [ + ./CMakeLists.txt + ./src/CMakeLists.txt + #./tests/CMakeLists.txt + ]; + + mesonSrcFiles = [ + ./meson.build + ./meson.options + ./src/meson.build + #./tests/meson.build + ]; + + autotoolsSrc = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions (baseSrcFiles ++ autotoolsSrcFiles); + }; + + patchelfFor = + pkgs: + pkgs.callPackage ./package-autotools.nix { inherit version; - src = self; + src = autotoolsSrc; }; + + # We don't apply flake-parts to the whole flake so that non-development attributes + # load without fetching any development inputs. + devFlake = inputs.flake-parts.lib.mkFlake { inherit inputs; } { + imports = [ ./maintainers/flake-module.nix ]; + systems = supportedSystems; + perSystem = + { system, ... }: + { + _module.args.pkgs = nixpkgs.legacyPackages.${system}; + }; + }; + + in + + { + overlays.default = final: prev: { + patchelf-new-musl = patchelfFor final.pkgsMusl; + patchelf-new = patchelfFor final; }; hydraJobs = { - tarball = - pkgs.releaseTools.sourceTarball rec { - name = "patchelf-tarball"; - inherit version; - versionSuffix = ""; # obsolete - src = self; - preAutoconf = "echo ${version} > version"; - postDist = '' - cp README.md $out/ - echo "doc readme $out/README.md" >> $out/nix-support/hydra-build-products - ''; + tarball = pkgs.releaseTools.sourceTarball rec { + name = "patchelf-tarball"; + inherit version; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions (baseSrcFiles ++ autotoolsSrcFiles ++ cmakeSrcFiles ++ mesonSrcFiles); }; + versionSuffix = ""; # obsolete + preAutoconf = "echo ${version} > version"; + + # portable configure shouldn't have a shebang pointing to the nix store + postConfigure = '' + sed -i '1s|^.*$|#!/bin/sh|' ./configure + ''; + postDist = '' + cp README.md $out/ + echo "doc readme $out/README.md" >> $out/nix-support/hydra-build-products + ''; + }; coverage = (pkgs.releaseTools.coverageAnalysis { name = "patchelf-coverage"; src = self.hydraJobs.tarball; - lcovFilter = ["*/tests/*"]; - }).overrideAttrs (old: { - preCheck = '' - # coverage cflag breaks this target - NIX_CFLAGS_COMPILE=''${NIX_CFLAGS_COMPILE//--coverage} make -C tests phdr-corruption.so - ''; - }); - - build = forAllSystems (system: nixpkgsFor.${system}.patchelf-new); - build-sanitized = forAllSystems (system: nixpkgsFor.${system}.patchelf-new.overrideAttrs (old: { - configureFlags = [ "--with-asan " "--with-ubsan" ]; - # -Wno-unused-command-line-argument is for clang, which does not like - # our cc wrapper arguments - CFLAGS = "-Werror -Wno-unused-command-line-argument"; - })); + lcovFilter = [ "*/tests/*" ]; + }).overrideAttrs + (old: { + preCheck = '' + # coverage cflag breaks this target + NIX_CFLAGS_COMPILE=''${NIX_CFLAGS_COMPILE//--coverage} make -C tests phdr-corruption.so + ''; + }); + + build = forAllSystems (system: self.packages.${system}.patchelf); + build-sanitized = forAllSystems ( + system: + self.packages.${system}.patchelf.overrideAttrs (old: { + configureFlags = [ + "--with-asan " + "--with-ubsan" + ]; + # -Wno-unused-command-line-argument is for clang, which does not like + # our cc wrapper arguments + CFLAGS = "-Werror -Wno-unused-command-line-argument"; + }) + ); + + build-cmake = forAllSystems (system: self.packages.${system}.patchelf-cmake); + + build-meson = forAllSystems (system: self.packages.${system}.patchelf-meson); # x86_64-linux seems to be only working clangStdenv at the moment - build-sanitized-clang = nixpkgs.lib.genAttrs [ "x86_64-linux" ] (system: self.hydraJobs.build-sanitized.${system}.override { - stdenv = nixpkgsFor.${system}.llvmPackages_latest.libcxxStdenv; - }); - - release = pkgs.releaseTools.aggregate - { name = "patchelf-${self.hydraJobs.tarball.version}"; - constituents = - [ self.hydraJobs.tarball - self.hydraJobs.build.x86_64-linux - self.hydraJobs.build.i686-linux - self.hydraJobs.build-sanitized.x86_64-linux - self.hydraJobs.build-sanitized.i686-linux - self.hydraJobs.build-sanitized-clang.x86_64-linux - ]; - meta.description = "Release-critical builds"; - }; + build-sanitized-clang = lib.genAttrs [ "x86_64-linux" ] ( + system: + self.hydraJobs.build-sanitized.${system}.override { + stdenv = nixpkgs.legacyPackages.${system}.llvmPackages_latest.libcxxStdenv; + } + ); - }; + # To get mingw compiler from hydra cache + inherit (self.packages.x86_64-linux) patchelf-win32 patchelf-win64; - checks = forAllSystems (system: { - build = self.hydraJobs.build.${system}; - }); + release = pkgs.releaseTools.aggregate { + name = "patchelf-${self.hydraJobs.tarball.version}"; + constituents = [ + self.hydraJobs.tarball + self.hydraJobs.build.x86_64-linux + self.hydraJobs.build.i686-linux + self.hydraJobs.build-cmake.x86_64-linux + self.hydraJobs.build-meson.x86_64-linux + # FIXME: add aarch64 emulation to our github action... + #self.hydraJobs.build.aarch64-linux + self.hydraJobs.build-sanitized.x86_64-linux + #self.hydraJobs.build-sanitized.aarch64-linux + self.hydraJobs.build-sanitized.i686-linux + self.hydraJobs.build-sanitized-clang.x86_64-linux + ]; + meta.description = "Release-critical builds"; + }; - devShell = forAllSystems (system: self.devShells.${system}.glibc); + }; - devShells = forAllSystems (system: + checks = forAllSystems ( + system: { - glibc = self.packages.${system}.patchelf; - musl = self.packages.${system}.patchelf-musl; - }); + build = self.hydraJobs.build.${system}; + } + // devFlake.checks.${system} or { } + ); - defaultPackage = forAllSystems (system: - self.packages.${system}.patchelf + devShells = forAllSystems ( + system: + let + mkShell = + patchelf: + patchelf.overrideAttrs ( + old: + let + pkgs = nixpkgs.legacyPackages.${system}; + modular = devFlake.getSystem pkgs.stdenv.buildPlatform.system; + in + { + env = (old.env or { }) // { + _NIX_PRE_COMMIT_HOOKS_CONFIG = "${(pkgs.formats.yaml { }).generate "pre-commit-config.yaml" + modular.pre-commit.settings.rawConfig + }"; + }; + nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ + #pkgs.buildPackages.cmake + #pkgs.buildPackages.meson + #pkgs.buildPackages.ninja + modular.pre-commit.settings.package + (pkgs.buildPackages.writeScriptBin "pre-commit-hooks-install" modular.pre-commit.settings.installationScript) + ]; + } + ); + in + { + glibc = mkShell self.packages.${system}.patchelf; + default = self.devShells.${system}.glibc; + } + // lib.optionalAttrs (system != "i686-linux") { + musl = mkShell self.packages.${system}.patchelf-musl; + } ); - packages = forAllSystems (system: + packages = forAllSystems ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + patchelfForWindowsStatic = + pkgs: + (pkgs.callPackage ./package-autotools.nix { + inherit version; + src = autotoolsSrc; + # On windows we use win32 threads to get a static binary, + # otherwise `-static` below doesn't work. + stdenv = pkgs.stdenv.override (old: { + cc = old.cc.override (old: { + cc = old.cc.override { + threadsCross = { + model = "win32"; + package = null; + }; + }; + }); + }); + }).overrideAttrs + (old: { + NIX_CFLAGS_COMPILE = "-static"; + }); + in { - patchelf = nixpkgsFor.${system}.patchelf-new; - patchelf-musl = nixpkgsFor.${system}.patchelf-new-musl; - }); + patchelf = patchelfFor pkgs; + default = self.packages.${system}.patchelf; + + patchelf-cmake = pkgs.callPackage ./package-cmake.nix { + inherit version; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions (baseSrcFiles ++ cmakeSrcFiles); + }; + }; + + patchelf-meson = pkgs.callPackage ./package-meson.nix { + inherit version; + src = lib.fileset.toSource { + root = ./.; + fileset = lib.fileset.unions (baseSrcFiles ++ mesonSrcFiles); + }; + }; + + # This is a good test to see if packages can be cross-compiled. It also + # tests if our testsuite uses target-prefixed executable names. + patchelf-musl-cross = patchelfFor pkgs.pkgsCross.musl64; + patchelf-netbsd-cross = patchelfFor pkgs.pkgsCross.x86_64-netbsd; + patchelf-win32 = patchelfForWindowsStatic pkgs.pkgsCross.mingw32; + patchelf-win64 = patchelfForWindowsStatic pkgs.pkgsCross.mingwW64; + } + // lib.optionalAttrs (system != "i686-linux") { + patchelf-musl = patchelfFor nixpkgs.legacyPackages.${system}.pkgsMusl; + } + ); }; } diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 00000000..a3d964c6 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,1009 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for +# the respective C++ standard version. +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for no added switch, and then for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 15 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +dnl Test body for checking C++17 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +#elif __cplusplus < 201103L && !defined _MSC_VER + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L && !defined _MSC_VER + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L && !defined _MSC_VER + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L && !defined _MSC_VER + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L && !defined _MSC_VER + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L && !defined _MSC_VER + +]]) diff --git a/maintainers/flake-module.nix b/maintainers/flake-module.nix new file mode 100644 index 00000000..26eff46c --- /dev/null +++ b/maintainers/flake-module.nix @@ -0,0 +1,96 @@ +{ + lib, + getSystem, + inputs, + ... +}: + +{ + imports = [ + inputs.git-hooks-nix.flakeModule + ]; + + perSystem = + { config, pkgs, ... }: + { + + # https://flake.parts/options/git-hooks-nix#options + pre-commit.settings = { + hooks = { + # Conflicts are usually found by other checks, but not those in docs, + # and potentially other places. + check-merge-conflicts.enable = true; + # built-in check-merge-conflicts seems ineffective against those produced by mergify backports + check-merge-conflicts-2 = { + enable = true; + entry = "${pkgs.writeScript "check-merge-conflicts" '' + #!${pkgs.runtimeShell} + conflicts=false + for file in "$@"; do + if grep --with-filename --line-number -E '^>>>>>>> ' -- "$file"; then + conflicts=true + fi + done + if $conflicts; then + echo "ERROR: found merge/patch conflicts in files" + exit 1 + fi + ''}"; + }; + cmake-format = { + enable = true; + }; + meson-format = + let + meson = pkgs.meson.overrideAttrs { + doCheck = false; + doInstallCheck = false; + patches = [ + (pkgs.fetchpatch { + url = "https://github.com/mesonbuild/meson/commit/38d29b4dd19698d5cad7b599add2a69b243fd88a.patch"; + hash = "sha256-PgPBvGtCISKn1qQQhzBW5XfknUe91i5XGGBcaUK4yeE="; + }) + ]; + }; + in + { + enable = true; + files = "(meson.build|meson.options)$"; + entry = "${pkgs.writeScript "format-meson" '' + #!${pkgs.runtimeShell} + for file in "$@"; do + ${lib.getExe meson} format -ic ${../meson.format} "$file" + done + ''}"; + }; + nixfmt-rfc-style = { + enable = true; + }; + clang-format = { + enable = true; + # https://github.com/cachix/git-hooks.nix/pull/532 + package = pkgs.llvmPackages_latest.clang-tools; + # Not yet formatted + excludes = [ + ''^src/elf.h$'' + ''^src/patchelf.cc$'' + ''^src/patchelf.h$'' + ''^tests/bar.c$'' + ''^tests/foo.c$'' + ''^tests/main.c$'' + ''^tests/no-rpath.c$'' + ''^tests/simple.c$'' + ''^tests/too-many-strtab.c$'' + ''^tests/void.c$'' + ]; + }; + shellcheck = { + enable = true; + }; + }; + }; + }; + + # We'll be pulling from this in the main flake + flake.getSystem = getSystem; +} diff --git a/maintainers/format.sh b/maintainers/format.sh new file mode 100755 index 00000000..b2902e6d --- /dev/null +++ b/maintainers/format.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +if ! type -p pre-commit &>/dev/null; then + echo "format.sh: pre-commit not found. Please use \`nix develop -c ./maintainers/format.sh\`."; + exit 1; +fi; +if test -z "$_NIX_PRE_COMMIT_HOOKS_CONFIG"; then + echo "format.sh: _NIX_PRE_COMMIT_HOOKS_CONFIG not set. Please use \`nix develop -c ./maintainers/format.sh\`."; + exit 1; +fi; + +while ! pre-commit run --config "$_NIX_PRE_COMMIT_HOOKS_CONFIG" --all-files; do + if [ "${1:-}" != "--until-stable" ]; then + exit 1 + fi +done diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..ad8042c2 --- /dev/null +++ b/meson.build @@ -0,0 +1,31 @@ +project( + 'patchelf', + 'cpp', + 'c', + version : files('version'), + default_options : { + 'cpp_std' : 'c++17', + 'warning_level' : '2', + }, + meson_version : '>=1.2', +) + +subdir('src') +#subdir('tests') # TODO + +install_man('patchelf.1') + +#specfile = configure_file( +# output : 'patchelf.spec', +# configuration : {'PACKAGE_VERSION' : meson.project_version()}, +#) + +# Commented things out should only be for `meson dist`. Need to +# reimplement for that. +install_data( + 'README.md', + #'COPYING', + #specfile, + #'version', + install_dir : get_option('datadir') / 'doc' / 'patchelf', +) diff --git a/meson.format b/meson.format new file mode 100644 index 00000000..4876dd96 --- /dev/null +++ b/meson.format @@ -0,0 +1,7 @@ +indent_by = ' ' +space_array = true +kwargs_force_multiline = false +wide_colon = true +group_arg_value = true +indent_before_comments = ' ' +use_editor_config = true diff --git a/meson.options b/meson.options new file mode 100644 index 00000000..21ae69e7 --- /dev/null +++ b/meson.options @@ -0,0 +1,7 @@ +option( + 'page_size', + type : 'combo', + value : 'auto', + choices : [ 'auto', '4096', '65536', '16384', '8192' ], + description : 'Default page size, or "auto" to detect at runtime', +) diff --git a/patchelf.nix b/package-autotools.nix similarity index 71% rename from patchelf.nix rename to package-autotools.nix index fdeba6b8..c0e334fa 100644 --- a/patchelf.nix +++ b/package-autotools.nix @@ -1,4 +1,9 @@ -{ stdenv, autoreconfHook, version, src }: +{ + stdenv, + autoreconfHook, + version, + src, +}: stdenv.mkDerivation { pname = "patchelf"; diff --git a/package-cmake.nix b/package-cmake.nix new file mode 100644 index 00000000..de8efe20 --- /dev/null +++ b/package-cmake.nix @@ -0,0 +1,17 @@ +{ + stdenv, + cmake, + ninja, + version, + src, +}: + +stdenv.mkDerivation { + pname = "patchelf"; + inherit version src; + nativeBuildInputs = [ + cmake + ninja + ]; + doCheck = true; +} diff --git a/package-meson.nix b/package-meson.nix new file mode 100644 index 00000000..8e7c4656 --- /dev/null +++ b/package-meson.nix @@ -0,0 +1,17 @@ +{ + stdenv, + meson, + ninja, + version, + src, +}: + +stdenv.mkDerivation { + pname = "patchelf"; + inherit version src; + nativeBuildInputs = [ + meson + ninja + ]; + doCheck = true; +} diff --git a/patchelf.1 b/patchelf.1 index e25793be..f5bb78aa 100644 --- a/patchelf.1 +++ b/patchelf.1 @@ -1,5 +1,5 @@ .\" Process this file with -.\" groff -man -Tascii foo.1 +.\" groff -man -Tascii patchelf.1 .\" .TH PATCHELF 1 "JUNE 2010" PATCHELF "User Manuals" .SH NAME diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..2e6620ed --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,12 @@ +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_EXTENSIONS OFF) + +set(PAGESIZE 4096) + +add_executable(${PROJECT_NAME} patchelf.cc elf.h patchelf.h) + +target_compile_definitions( + patchelf PRIVATE PAGESIZE=${PAGESIZE} + PACKAGE_STRING="patchelf ${VERSION_STRING}") + +install(TARGETS patchelf RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/src/Makefile.am b/src/Makefile.am index fa0a9cc1..93e92d8c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -AM_CXXFLAGS = -Wall -std=c++17 -D_FILE_OFFSET_BITS=64 +AM_CXXFLAGS = -Wall -Wextra -Wcast-qual -std=c++17 -D_FILE_OFFSET_BITS=64 if WITH_ASAN AM_CXXFLAGS += -fsanitize=address -fsanitize-address-use-after-scope diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 00000000..c6204efc --- /dev/null +++ b/src/meson.build @@ -0,0 +1,18 @@ +# Configure DEFAULT_PAGESIZE via config.h +confdata = configuration_data() +page_size = get_option('page_size') +if page_size != 'auto' + confdata.set_quoted('DEFAULT_PAGESIZE', page_size) +else + # For "auto", leave it undefined so runtime detection happens +endif + +config_h = configure_file(output : 'config.h', configuration : confdata) + +executable( + 'patchelf', + [ 'patchelf.cc', 'patchelf.h', config_h ], + include_directories : include_directories('.'), + cpp_args : [ '-include', meson.current_build_dir() / 'config.h' ], + install : true, +) From 06b8a412142b539ab68e7846c2db0fe46029e9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 6 Nov 2022 15:38:38 +0100 Subject: [PATCH 02/30] make objdump/objcopy/readelf configurable and respect cross-compiling related prefixes (cherry picked from commit b0599fe776e063156f5d18f5b9b2c7a23f7c62ae) --- tests/Makefile.am | 2 +- tests/add-debug-tag.sh | 5 +++-- tests/build-id.sh | 6 +----- tests/force-rpath.sh | 3 ++- tests/set-rpath-rel-map.sh | 10 ++++++---- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index bbea1ba4..291ced70 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,7 +50,7 @@ TESTS = $(src_TESTS) $(build_TESTS) EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness -TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 +TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 OBJDUMP=$(OBJDUMP) READELF=$(READELF) $(no_rpath_arch_TESTS): no-rpath-prebuild.sh @ln -s $< $@ diff --git a/tests/add-debug-tag.sh b/tests/add-debug-tag.sh index 203a0bc0..4fbbfa4b 100755 --- a/tests/add-debug-tag.sh +++ b/tests/add-debug-tag.sh @@ -1,5 +1,6 @@ #! /bin/sh -e SCRATCH=scratch/$(basename $0 .sh) +READELF=${READELF:-readelf} rm -rf ${SCRATCH} mkdir -p ${SCRATCH} @@ -7,7 +8,7 @@ mkdir -p ${SCRATCH} cp libsimple.so ${SCRATCH}/ # check there is no DT_DEBUG tag -debugTag=$(readelf -d ${SCRATCH}/libsimple.so) +debugTag=$($READELF -d ${SCRATCH}/libsimple.so) echo ".dynamic before: $debugTag" if echo "$debugTag" | grep -q DEBUG; then echo "failed --add-debug-tag test. Expected no line with (DEBUG), got: $debugTag" @@ -18,7 +19,7 @@ fi ../src/patchelf --add-debug-tag ${SCRATCH}/libsimple.so # check there is DT_DEBUG tag -debugTag=$(readelf -d ${SCRATCH}/libsimple.so) +debugTag=$($READELF -d ${SCRATCH}/libsimple.so) echo ".dynamic before: $debugTag" if ! echo "$debugTag" | grep -q DEBUG; then echo "failed --add-debug-tag test. Expected line with (DEBUG), got: $debugTag" diff --git a/tests/build-id.sh b/tests/build-id.sh index 81b8f060..94ddc4c6 100755 --- a/tests/build-id.sh +++ b/tests/build-id.sh @@ -1,10 +1,6 @@ #! /bin/sh -e SCRATCH=scratch/$(basename $0 .sh) - -if ! command -v readelf >/dev/null; then - echo "No readelf found; skip test" - exit 0 -fi +READELF=${READELF:-readelf} rm -rf "${SCRATCH}" mkdir -p "${SCRATCH}" diff --git a/tests/force-rpath.sh b/tests/force-rpath.sh index 92569056..6b1422a7 100755 --- a/tests/force-rpath.sh +++ b/tests/force-rpath.sh @@ -1,5 +1,6 @@ #! /bin/sh -e SCRATCH=scratch/$(basename $0 .sh) +OBJDUMP=${OBJDDUMP:-objdump} rm -rf ${SCRATCH} mkdir -p ${SCRATCH} @@ -13,7 +14,7 @@ doit() { } expect() { - out=$(echo $(objdump -x $SCRATCHFILE | grep PATH)) + out=$(echo $($OBJDUMP -x $SCRATCHFILE | grep PATH)) if [ "$out" != "$*" ]; then echo "Expected '$*' but got '$out'" diff --git a/tests/set-rpath-rel-map.sh b/tests/set-rpath-rel-map.sh index efc09437..48bc361b 100755 --- a/tests/set-rpath-rel-map.sh +++ b/tests/set-rpath-rel-map.sh @@ -1,12 +1,14 @@ #! /bin/sh -e -if ! objdump -p main | grep -q MIPS_RLD_MAP_REL; then +SCRATCH=scratch/$(basename $0 .sh) +OBJDUMP=${OBJDUMP:-objdump} +OBJCOPY=${OBJCOPY:-objcopy} + +if ! $OBJDUMP -p main | grep -q MIPS_RLD_MAP_REL; then echo "No MIPS_RLD_MAP_REL dynamic section entry, skipping" exit 0 fi -SCRATCH=scratch/$(basename $0 .sh) - rm -rf ${SCRATCH} mkdir -p ${SCRATCH} mkdir -p ${SCRATCH}/libsA @@ -17,7 +19,7 @@ cp libfoo.so ${SCRATCH}/libsA/ cp libbar.so ${SCRATCH}/libsB/ # break the main executable by removing .rld_map section -objcopy --remove-section .rld_map ${SCRATCH}/main +${OBJCOPY} --remove-section .rld_map ${SCRATCH}/main oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main) if test -z "$oldRPath"; then oldRPath="/oops"; fi From 33e3e8b6171bb68f063c1b607bdb97db24004878 Mon Sep 17 00:00:00 2001 From: Bo Anderson Date: Mon, 10 Oct 2022 15:14:31 +0100 Subject: [PATCH 03/30] tests/contiguous-note-sections.sh: use scratch directory (cherry picked from commit a93de9d4cea8eba211dcc3ad5d0d0ba43c01e19d) --- tests/contiguous-note-sections.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/contiguous-note-sections.sh b/tests/contiguous-note-sections.sh index 07c9354c..65abf0c6 100755 --- a/tests/contiguous-note-sections.sh +++ b/tests/contiguous-note-sections.sh @@ -1,6 +1,13 @@ #! /bin/sh -e +SCRATCH=scratch/$(basename $0 .sh) + +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" + +cp contiguous-note-sections "${SCRATCH}/" + # Running --set-interpreter on this binary should not produce the following # error: # patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections -../src/patchelf --set-interpreter ld-linux-x86-64.so.2 contiguous-note-sections +../src/patchelf --set-interpreter ld-linux-x86-64.so.2 ${SCRATCH}/contiguous-note-sections From 2d18660af71fb26cb39d7e051b96a0f1b1f45484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 6 Nov 2022 22:39:38 +0100 Subject: [PATCH 04/30] fix checkPhase for cross builds fixes https://github.com/NixOS/patchelf/issues/417 (cherry picked from commit f7b184c0044d32924f01b8b8003e59d1ac49ba00) --- tests/Makefile.am | 2 +- tests/build-id.sh | 2 +- tests/force-rpath.sh | 2 +- tests/no-gnu-hash.sh | 3 ++- tests/no-rpath-pie-powerpc.sh | 3 ++- tests/phdr-corruption.sh | 3 ++- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 291ced70..d9bf5d2a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,7 +50,7 @@ TESTS = $(src_TESTS) $(build_TESTS) EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness -TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 OBJDUMP=$(OBJDUMP) READELF=$(READELF) +TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 OBJDUMP=$(OBJDUMP) READELF=$(READELF) OBJCOPY=$(OBJCOPY) $(no_rpath_arch_TESTS): no-rpath-prebuild.sh @ln -s $< $@ diff --git a/tests/build-id.sh b/tests/build-id.sh index 94ddc4c6..dc44a7ae 100755 --- a/tests/build-id.sh +++ b/tests/build-id.sh @@ -13,4 +13,4 @@ long_rpath="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --set-rpath "$long_rpath" "${SCRATCH}/libbuildid.so" # older readelf versions do not recognize build id, but we can grep by constant -readelf -n "${SCRATCH}/libbuildid.so" | grep -q -F -e 'Build ID' -e 'Unknown note type: (0x00000003)' +${READELF} -n "${SCRATCH}/libbuildid.so" | grep -q -F -e 'Build ID' -e 'Unknown note type: (0x00000003)' diff --git a/tests/force-rpath.sh b/tests/force-rpath.sh index 6b1422a7..c9b9a5d0 100755 --- a/tests/force-rpath.sh +++ b/tests/force-rpath.sh @@ -1,6 +1,6 @@ #! /bin/sh -e SCRATCH=scratch/$(basename $0 .sh) -OBJDUMP=${OBJDDUMP:-objdump} +OBJDUMP=${OBJDUMP:-objdump} rm -rf ${SCRATCH} mkdir -p ${SCRATCH} diff --git a/tests/no-gnu-hash.sh b/tests/no-gnu-hash.sh index a98f4599..0ce93f40 100755 --- a/tests/no-gnu-hash.sh +++ b/tests/no-gnu-hash.sh @@ -1,12 +1,13 @@ #! /bin/sh -e SCRATCH=scratch/$(basename $0 .sh) +STRIP=${STRIP:-strip} rm -rf ${SCRATCH} mkdir -p ${SCRATCH} cp simple ${SCRATCH}/ -strip --remove-section=.gnu.hash ${SCRATCH}/simple +${STRIP} --remove-section=.gnu.hash ${SCRATCH}/simple # Check if patchelf handles binaries with GNU_HASH in dynamic section but # without .gnu.hash section diff --git a/tests/no-rpath-pie-powerpc.sh b/tests/no-rpath-pie-powerpc.sh index 5bdb7857..b469f9bf 100755 --- a/tests/no-rpath-pie-powerpc.sh +++ b/tests/no-rpath-pie-powerpc.sh @@ -1,6 +1,7 @@ #! /bin/sh -e set -x SCRATCH=scratch/no-rpath-pie-powerpc +READELF=${READELF:-readelf} no_rpath_bin="${srcdir}/no-rpath-prebuild/no-rpath-pie-powerpc" @@ -27,7 +28,7 @@ if ! echo "$newRPath" | grep -q '/foo:/bar'; then fi # Tests for powerpc PIE endianness regressions -readelfData=$(readelf -l ${SCRATCH}/no-rpath 2>&1) +readelfData=$(${READELF} -l ${SCRATCH}/no-rpath 2>&1) if [ $(echo "$readelfData" | grep --count "PHDR") != 1 ]; then # Triggered if PHDR errors appear on stderr diff --git a/tests/phdr-corruption.sh b/tests/phdr-corruption.sh index 0a368828..1e621016 100755 --- a/tests/phdr-corruption.sh +++ b/tests/phdr-corruption.sh @@ -4,6 +4,7 @@ PATCHELF="../src/patchelf" SONAME="phdr-corruption.so" SCRATCH="scratch/$(basename $0 .sh)" SCRATCH_SO="${SCRATCH}/${SONAME}" +READELF=${READELF:-readelf} rm -rf "${SCRATCH}" mkdir -p "${SCRATCH}" @@ -12,7 +13,7 @@ cp "${SONAME}" "${SCRATCH}" "${PATCHELF}" --set-rpath "$(pwd)" "${SCRATCH_SO}" # Check for PT_PHDR entry VirtAddr corruption -readelfData=$(readelf -l "${SCRATCH_SO}" 2>&1) +readelfData=$(${READELF} -l "${SCRATCH_SO}" 2>&1) if [ $(echo "$readelfData" | grep --count "PHDR") != 1 ]; then # Triggered if PHDR errors appear on stderr From 61fdb6e999e8b3f0fd047b2a5649093bff69a4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 19 Feb 2023 08:55:11 +0100 Subject: [PATCH 05/30] tests: apply suggestions from shellcheck (cherry picked from commit be4b84635f806998853825e23d94b14723e37b55) --- tests/add-debug-tag.sh | 14 +++---- tests/add-rpath.sh | 25 ++++++------ tests/args-from-file.sh | 20 +++++----- tests/big-dynstr.sh | 25 ++++++------ tests/build-id.sh | 2 +- tests/contiguous-note-sections.sh | 4 +- tests/endianness.sh | 14 +++---- tests/force-rpath.sh | 28 ++++++++------ tests/grow-file.sh | 14 +++---- tests/invalid-elf.sh | 4 +- tests/no-gnu-hash.sh | 12 +++--- tests/no-rpath-pie-powerpc.sh | 2 +- tests/no-rpath-prebuild.sh | 22 +++++------ tests/no-rpath.sh | 16 ++++---- tests/output-flag.sh | 29 +++++++------- tests/phdr-corruption.sh | 4 +- tests/plain-needed.sh | 8 ++-- tests/replace-add-needed.sh | 24 ++++++------ tests/replace-needed.sh | 17 ++++----- tests/set-empty-rpath.sh | 12 +++--- tests/set-interpreter-long.sh | 18 ++++----- tests/set-interpreter-short.sh | 12 +++--- tests/set-rpath-library.sh | 34 ++++++++--------- tests/set-rpath-rel-map.sh | 27 ++++++------- tests/set-rpath.sh | 25 ++++++------ tests/shrink-rpath-with-allowed-prefixes.sh | 42 ++++++++++----------- tests/shrink-rpath.sh | 16 ++++---- tests/soname.sh | 18 ++++----- tests/too-many-strtab.sh | 12 +++--- 29 files changed, 254 insertions(+), 246 deletions(-) diff --git a/tests/add-debug-tag.sh b/tests/add-debug-tag.sh index 4fbbfa4b..37bf957d 100755 --- a/tests/add-debug-tag.sh +++ b/tests/add-debug-tag.sh @@ -1,14 +1,14 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) READELF=${READELF:-readelf} -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp libsimple.so ${SCRATCH}/ +cp libsimple.so "${SCRATCH}"/ # check there is no DT_DEBUG tag -debugTag=$($READELF -d ${SCRATCH}/libsimple.so) +debugTag=$($READELF -d "${SCRATCH}/libsimple.so") echo ".dynamic before: $debugTag" if echo "$debugTag" | grep -q DEBUG; then echo "failed --add-debug-tag test. Expected no line with (DEBUG), got: $debugTag" @@ -16,10 +16,10 @@ if echo "$debugTag" | grep -q DEBUG; then fi # set DT_DEBUG -../src/patchelf --add-debug-tag ${SCRATCH}/libsimple.so +../src/patchelf --add-debug-tag "${SCRATCH}/libsimple.so" # check there is DT_DEBUG tag -debugTag=$($READELF -d ${SCRATCH}/libsimple.so) +debugTag=$($READELF -d "${SCRATCH}/libsimple.so") echo ".dynamic before: $debugTag" if ! echo "$debugTag" | grep -q DEBUG; then echo "failed --add-debug-tag test. Expected line with (DEBUG), got: $debugTag" diff --git a/tests/add-rpath.sh b/tests/add-rpath.sh index 33687081..1f9f7f93 100755 --- a/tests/add-rpath.sh +++ b/tests/add-rpath.sh @@ -1,24 +1,25 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -mkdir -p ${SCRATCH}/libsA -mkdir -p ${SCRATCH}/libsB +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +mkdir -p "${SCRATCH}/libsA" +mkdir -p "${SCRATCH}/libsB" -cp main ${SCRATCH}/ -cp libfoo.so ${SCRATCH}/libsA/ -cp libbar.so ${SCRATCH}/libsB/ +cp main "${SCRATCH}"/ +cp libfoo.so "${SCRATCH}/libsA/" +cp libbar.so "${SCRATCH}/libsB/" -../src/patchelf --force-rpath --add-rpath $(pwd)/${SCRATCH}/libsA ${SCRATCH}/main -../src/patchelf --force-rpath --add-rpath $(pwd)/${SCRATCH}/libsB ${SCRATCH}/main +../src/patchelf --force-rpath --add-rpath "$(pwd)/${SCRATCH}/libsA" "${SCRATCH}/main" +../src/patchelf --force-rpath --add-rpath "$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/main" if test "$(uname)" = FreeBSD; then - export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB + LD_LIBRARY_PATH="$(pwd)/${SCRATCH}/libsB" + export LD_LIBRARY_PATH fi exitCode=0 -(cd ${SCRATCH} && ./main) || exitCode=$? +(cd "${SCRATCH}" && ./main) || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" diff --git a/tests/args-from-file.sh b/tests/args-from-file.sh index c0d1a548..107031e8 100755 --- a/tests/args-from-file.sh +++ b/tests/args-from-file.sh @@ -1,16 +1,16 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp main ${SCRATCH}/ -RANDOM_PATH=$(pwd)/${SCRATCH}/$RANDOM -echo -n ${RANDOM_PATH} >> ${SCRATCH}/add-rpath +cp main "${SCRATCH}"/ +SOME_PATH=$(pwd)/${SCRATCH}/some-path +printf "%s" "$SOME_PATH" >> "${SCRATCH}"/add-rpath -! ../src/patchelf --print-rpath ${SCRATCH}/main | grep $RANDOM_PATH -../src/patchelf --add-rpath @${SCRATCH}/add-rpath ${SCRATCH}/main -../src/patchelf --print-rpath ${SCRATCH}/main | grep $RANDOM_PATH + ../src/patchelf --print-rpath "${SCRATCH}"/main | grep "$SOME_PATH" && exit 1 +../src/patchelf --add-rpath @"${SCRATCH}"/add-rpath "${SCRATCH}"/main +../src/patchelf --print-rpath "${SCRATCH}"/main | grep "$SOME_PATH" # should print error message and fail -../src/patchelf --set-rpath @${SCRATCH}/does-not-exist ${SCRATCH}/main 2>&1 | grep "getting info about" +../src/patchelf --set-rpath @"${SCRATCH}"/does-not-exist "${SCRATCH}"/main 2>&1 | grep "getting info about" diff --git a/tests/big-dynstr.sh b/tests/big-dynstr.sh index 19adad14..89c53557 100755 --- a/tests/big-dynstr.sh +++ b/tests/big-dynstr.sh @@ -1,25 +1,26 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -mkdir -p ${SCRATCH}/libsA -mkdir -p ${SCRATCH}/libsB +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +mkdir -p "${SCRATCH}/libsA" +mkdir -p "${SCRATCH}/libsB" -cp big-dynstr ${SCRATCH}/ -cp libfoo.so ${SCRATCH}/libsA/ -cp libbar.so ${SCRATCH}/libsB/ +cp big-dynstr "${SCRATCH}/" +cp libfoo.so "${SCRATCH}/libsA/" +cp libbar.so "${SCRATCH}/libsB/" -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/big-dynstr) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}/big-dynstr") if test -z "$oldRPath"; then oldRPath="/oops"; fi -../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/big-dynstr +../src/patchelf --force-rpath --set-rpath "$oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/big-dynstr" if test "$(uname)" = FreeBSD; then - export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB + LD_LIBRARY_PATH="$(pwd)/${SCRATCH}/libsB" + export LD_LIBRARY_PATH fi exitCode=0 -cd ${SCRATCH} && ./big-dynstr || exitCode=$? +cd "${SCRATCH}" && ./big-dynstr || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" diff --git a/tests/build-id.sh b/tests/build-id.sh index dc44a7ae..c9bf7124 100755 --- a/tests/build-id.sh +++ b/tests/build-id.sh @@ -1,5 +1,5 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) READELF=${READELF:-readelf} rm -rf "${SCRATCH}" diff --git a/tests/contiguous-note-sections.sh b/tests/contiguous-note-sections.sh index 65abf0c6..aa1f84a1 100755 --- a/tests/contiguous-note-sections.sh +++ b/tests/contiguous-note-sections.sh @@ -1,6 +1,6 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) rm -rf "${SCRATCH}" mkdir -p "${SCRATCH}" @@ -10,4 +10,4 @@ cp contiguous-note-sections "${SCRATCH}/" # Running --set-interpreter on this binary should not produce the following # error: # patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections -../src/patchelf --set-interpreter ld-linux-x86-64.so.2 ${SCRATCH}/contiguous-note-sections +../src/patchelf --set-interpreter ld-linux-x86-64.so.2 "${SCRATCH}/contiguous-note-sections" diff --git a/tests/endianness.sh b/tests/endianness.sh index 4f84a080..fc2994b5 100755 --- a/tests/endianness.sh +++ b/tests/endianness.sh @@ -1,23 +1,23 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) PATCHELF="../src/patchelf" for arch in ppc64 ppc64le; do - rm -rf ${SCRATCH} - mkdir -p ${SCRATCH} + rm -rf "${SCRATCH}" + mkdir -p "${SCRATCH}" - cp ${srcdir}/endianness/${arch}/main ${srcdir}/endianness/${arch}/libtest.so ${SCRATCH}/ + cp "${srcdir}/endianness/${arch}/main" "${srcdir}/endianness/${arch}/libtest.so" "${SCRATCH}/" rpath="${PWD}/${SCRATCH}" # set rpath to scratch dir - ${PATCHELF} --output ${SCRATCH}/main-rpath --set-rpath $rpath ${SCRATCH}/main + ${PATCHELF} --output "${SCRATCH}/main-rpath" --set-rpath "$rpath" "${SCRATCH}/main" # attempt to shrink rpath, should not result in empty rpath - ${PATCHELF} --output ${SCRATCH}/main-shrunk --shrink-rpath --debug ${SCRATCH}/main-rpath + ${PATCHELF} --output "${SCRATCH}/main-shrunk" --shrink-rpath --debug "${SCRATCH}/main-rpath" # check whether rpath is still present - if ! ${PATCHELF} --print-rpath ${SCRATCH}/main-shrunk | grep -q "$rpath"; then + if ! ${PATCHELF} --print-rpath "${SCRATCH}/main-shrunk" | grep -q "$rpath"; then echo "rpath was removed for ${arch}" exit 1 fi diff --git a/tests/force-rpath.sh b/tests/force-rpath.sh index c9b9a5d0..a673f201 100755 --- a/tests/force-rpath.sh +++ b/tests/force-rpath.sh @@ -1,29 +1,33 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) OBJDUMP=${OBJDUMP:-objdump} -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" SCRATCHFILE=${SCRATCH}/libfoo.so -cp libfoo.so $SCRATCHFILE +cp libfoo.so "$SCRATCHFILE" doit() { - echo patchelf $* - ../src/patchelf $* $SCRATCHFILE + set +x + ../src/patchelf "$@" "$SCRATCHFILE" + set -x } expect() { - out=$(echo $($OBJDUMP -x $SCRATCHFILE | grep PATH)) + out=$("$OBJDUMP" -x "$SCRATCHFILE" | grep PATH || true) - if [ "$out" != "$*" ]; then - echo "Expected '$*' but got '$out'" - exit 1 - fi + for i in $out; do + if [ "$i" != "$1" ]; then + echo "Expected '$*' but got '$out'" + exit 1 + fi + shift + done } doit --remove-rpath -expect +expect "" doit --set-rpath foo expect RUNPATH foo doit --force-rpath --set-rpath foo diff --git a/tests/grow-file.sh b/tests/grow-file.sh index 4c405df8..ec5957d0 100755 --- a/tests/grow-file.sh +++ b/tests/grow-file.sh @@ -1,16 +1,16 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp simple-pie ${SCRATCH}/simple-pie +cp simple-pie "${SCRATCH}/simple-pie" # Add a 40MB rpath -tr -cd 'a-z0-9' < /dev/urandom | dd count=40 bs=1000000 > ${SCRATCH}/foo.bin +tr -cd 'a-z0-9' < /dev/urandom | dd count=40 bs=1000000 > "${SCRATCH}/foo.bin" # Grow the file -../src/patchelf --add-rpath @${SCRATCH}/foo.bin ${SCRATCH}/simple-pie +../src/patchelf --add-rpath @"${SCRATCH}/foo.bin" "${SCRATCH}/simple-pie" # Make sure we can still run it -${SCRATCH}/simple-pie +"${SCRATCH}/simple-pie" diff --git a/tests/invalid-elf.sh b/tests/invalid-elf.sh index 0f020e8e..c124501d 100755 --- a/tests/invalid-elf.sh +++ b/tests/invalid-elf.sh @@ -6,12 +6,12 @@ # by a signal. This works because the exit code of processes that were # killed by a signal is 128 plus the signal number. killed_by_signal() { - [ $1 -ge 128 ] + [ "$1" -ge 128 ] } # The directory containing all our input files. -TEST_DIR=$(dirname $(readlink -f $0))/invalid-elf +TEST_DIR=$(dirname "$(readlink -f "$0")")/invalid-elf # Each test case is listed here. The names should roughly indicate # what makes the given ELF file invalid. diff --git a/tests/no-gnu-hash.sh b/tests/no-gnu-hash.sh index 0ce93f40..b12542ea 100755 --- a/tests/no-gnu-hash.sh +++ b/tests/no-gnu-hash.sh @@ -1,14 +1,14 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) STRIP=${STRIP:-strip} -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp simple ${SCRATCH}/ +cp simple "${SCRATCH}/" -${STRIP} --remove-section=.gnu.hash ${SCRATCH}/simple +${STRIP} --remove-section=.gnu.hash "${SCRATCH}/simple" # Check if patchelf handles binaries with GNU_HASH in dynamic section but # without .gnu.hash section -../src/patchelf --set-interpreter /oops ${SCRATCH}/simple +../src/patchelf --set-interpreter /oops "${SCRATCH}/simple" diff --git a/tests/no-rpath-pie-powerpc.sh b/tests/no-rpath-pie-powerpc.sh index b469f9bf..963797c6 100755 --- a/tests/no-rpath-pie-powerpc.sh +++ b/tests/no-rpath-pie-powerpc.sh @@ -30,7 +30,7 @@ fi # Tests for powerpc PIE endianness regressions readelfData=$(${READELF} -l ${SCRATCH}/no-rpath 2>&1) -if [ $(echo "$readelfData" | grep --count "PHDR") != 1 ]; then +if [ $(echo "$readelfData" | grep "PHDR" | wc -l) != 1 ]; then # Triggered if PHDR errors appear on stderr echo "Unexpected number of occurences of PHDR in readelf results" exit 1 diff --git a/tests/no-rpath-prebuild.sh b/tests/no-rpath-prebuild.sh index c58cf8eb..143c55ce 100755 --- a/tests/no-rpath-prebuild.sh +++ b/tests/no-rpath-prebuild.sh @@ -4,35 +4,35 @@ ARCH="$1" PAGESIZE=4096 if [ -z "$ARCH" ]; then - ARCH=$(basename $0 .sh | sed -e 's/^no-rpath-//') + ARCH=$(basename "$0" .sh | sed -e 's/^no-rpath-//') fi SCRATCH=scratch/no-rpath-$ARCH -if [ -z "$ARCH" ] || [ $ARCH = prebuild ] ; then +if [ -z "$ARCH" ] || [ "$ARCH" = prebuild ] ; then echo "Architecture required" exit 1 fi no_rpath_bin="${srcdir}/no-rpath-prebuild/no-rpath-$ARCH" -if [ ! -f $no_rpath_bin ]; then +if [ ! -f "$no_rpath_bin" ]; then echo "no 'no-rpath' binary for '$ARCH' in '${srcdir}/no-rpath-prebuild'" exit 1 fi -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp $no_rpath_bin ${SCRATCH}/no-rpath +cp "$no_rpath_bin" "${SCRATCH}"/no-rpath -oldRPath=$(../src/patchelf --page-size ${PAGESIZE} --print-rpath ${SCRATCH}/no-rpath) +oldRPath=$(../src/patchelf --page-size "${PAGESIZE}" --print-rpath "${SCRATCH}/no-rpath") if test -n "$oldRPath"; then exit 1; fi -../src/patchelf --page-size ${PAGESIZE} \ - --set-interpreter "$(../src/patchelf --page-size ${PAGESIZE} --print-interpreter ../src/patchelf)" \ - --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath +../src/patchelf --page-size "${PAGESIZE}" \ + --set-interpreter "$(../src/patchelf --page-size "${PAGESIZE}" --print-interpreter ../src/patchelf)" \ + --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx "${SCRATCH}"/no-rpath -newRPath=$(../src/patchelf --page-size ${PAGESIZE} --print-rpath ${SCRATCH}/no-rpath) +newRPath=$(../src/patchelf --page-size "${PAGESIZE}" --print-rpath "${SCRATCH}/no-rpath") if ! echo "$newRPath" | grep -q '/foo:/bar'; then echo "incomplete RPATH" exit 1 diff --git a/tests/no-rpath.sh b/tests/no-rpath.sh index 3efa7f10..7fe03725 100755 --- a/tests/no-rpath.sh +++ b/tests/no-rpath.sh @@ -1,21 +1,21 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp no-rpath ${SCRATCH}/ +cp no-rpath "${SCRATCH}/" -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}/no-rpath") if test -n "$oldRPath"; then exit 1; fi ../src/patchelf \ --set-interpreter "$(../src/patchelf --print-interpreter ../src/patchelf)" \ - --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx ${SCRATCH}/no-rpath + --set-rpath /foo:/bar:/xxxxxxxxxxxxxxx "${SCRATCH}/no-rpath" -newRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) +newRPath=$(../src/patchelf --print-rpath "${SCRATCH}/no-rpath") if ! echo "$newRPath" | grep -q '/foo:/bar'; then echo "incomplete RPATH" exit 1 fi -cd ${SCRATCH} && ./no-rpath +cd "${SCRATCH}" && ./no-rpath diff --git a/tests/output-flag.sh b/tests/output-flag.sh index 5da26b57..26e87829 100755 --- a/tests/output-flag.sh +++ b/tests/output-flag.sh @@ -1,28 +1,29 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -mkdir -p ${SCRATCH}/libsA -mkdir -p ${SCRATCH}/libsB +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +mkdir -p "${SCRATCH}/libsA" +mkdir -p "${SCRATCH}/libsB" -cp main ${SCRATCH}/ -cp libfoo.so ${SCRATCH}/libsA/ -cp libbar.so ${SCRATCH}/libsB/ +cp main "${SCRATCH}"/ +cp libfoo.so "${SCRATCH}/libsA/" +cp libbar.so "${SCRATCH}/libsB/" -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}/main") if test -z "$oldRPath"; then oldRPath="/oops"; fi -../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main --output ${SCRATCH}/main2 +../src/patchelf --force-rpath --set-rpath "$oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/main" --output "${SCRATCH}/main2" # make sure it copies even when there is nothing to do (because rpath is already set) -../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main2 --output ${SCRATCH}/main3 +../src/patchelf --force-rpath --set-rpath "$oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/main2" --output "${SCRATCH}/main3" if test "$(uname)" = FreeBSD; then - export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB + LD_LIBRARY_PATH="$(pwd)/${SCRATCH}/libsB" + export LD_LIBRARY_PATH fi exitCode=0 -(cd ${SCRATCH} && ./main2) || exitCode=$? +(cd "${SCRATCH}" && ./main2) || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" @@ -30,7 +31,7 @@ if test "$exitCode" != 46; then fi exitCode=0 -(cd ${SCRATCH} && ./main3) || exitCode=$? +(cd "${SCRATCH}" && ./main3) || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" diff --git a/tests/phdr-corruption.sh b/tests/phdr-corruption.sh index 1e621016..4f6e9019 100755 --- a/tests/phdr-corruption.sh +++ b/tests/phdr-corruption.sh @@ -2,7 +2,7 @@ PATCHELF="../src/patchelf" SONAME="phdr-corruption.so" -SCRATCH="scratch/$(basename $0 .sh)" +SCRATCH="scratch/$(basename "$0" .sh)" SCRATCH_SO="${SCRATCH}/${SONAME}" READELF=${READELF:-readelf} @@ -15,7 +15,7 @@ cp "${SONAME}" "${SCRATCH}" # Check for PT_PHDR entry VirtAddr corruption readelfData=$(${READELF} -l "${SCRATCH_SO}" 2>&1) -if [ $(echo "$readelfData" | grep --count "PHDR") != 1 ]; then +if [ "$(echo "$readelfData" | grep "PHDR" | wc -l)" != 1 ]; then # Triggered if PHDR errors appear on stderr echo "ERROR: Unexpected number of occurences of PHDR in readelf results!" exit 1 diff --git a/tests/plain-needed.sh b/tests/plain-needed.sh index 89673039..e44293b1 100755 --- a/tests/plain-needed.sh +++ b/tests/plain-needed.sh @@ -1,14 +1,14 @@ #! /bin/sh set -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) MAIN_ELF="${SCRATCH}/main" PATCHELF="../src/patchelf" -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -cp main ${SCRATCH}/ +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +cp main "${SCRATCH}"/ echo "Confirming main requires libfoo" ${PATCHELF} --print-needed "${MAIN_ELF}" | grep -q libfoo.so diff --git a/tests/replace-add-needed.sh b/tests/replace-add-needed.sh index ab0d3532..c9966427 100755 --- a/tests/replace-add-needed.sh +++ b/tests/replace-add-needed.sh @@ -1,15 +1,15 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) PATCHELF=$(readlink -f "../src/patchelf") -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp simple ${SCRATCH}/ -cp libfoo.so ${SCRATCH}/ -cp libbar.so ${SCRATCH}/ +cp simple "${SCRATCH}"/ +cp libfoo.so "${SCRATCH}"/ +cp libbar.so "${SCRATCH}"/ -cd ${SCRATCH} +cd "${SCRATCH}" libcldd=$(ldd ./simple | awk '/ => / { print $3 }' | grep -E "(libc.so|ld-musl)") @@ -22,11 +22,11 @@ ${PATCHELF} --add-needed libbar.so ./simple # Make the NEEDED in libfoo the same as simple # This is a current "bug" in musl # https://www.openwall.com/lists/musl/2021/12/21/1 -${PATCHELF} --replace-needed libbar.so $(readlink -f ./libbar.so) ./libfoo.so +${PATCHELF} --replace-needed libbar.so "$(readlink -f ./libbar.so)" ./libfoo.so -${PATCHELF} --replace-needed libc.so.6 ${libcldd} \ - --replace-needed libbar.so $(readlink -f ./libbar.so) \ - --add-needed $(readlink -f ./libfoo.so) \ +${PATCHELF} --replace-needed libc.so.6 "${libcldd}" \ + --replace-needed libbar.so "$(readlink -f ./libbar.so)" \ + --add-needed "$(readlink -f ./libfoo.so)" \ ./simple exitCode=0 @@ -35,4 +35,4 @@ exitCode=0 if test "$exitCode" != 0; then ldd ./simple exit 1 -fi \ No newline at end of file +fi diff --git a/tests/replace-needed.sh b/tests/replace-needed.sh index 0a5581ce..6099d937 100755 --- a/tests/replace-needed.sh +++ b/tests/replace-needed.sh @@ -1,21 +1,20 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -oldNeeded=$(../src/patchelf --print-needed big-dynstr) oldLibc=$(../src/patchelf --print-needed big-dynstr | grep -v 'foo\.so') -../src/patchelf --output ${SCRATCH}/big-needed --replace-needed ${oldLibc} long_long_very_long_libc.so.6 --replace-needed libfoo.so lf.so big-dynstr +../src/patchelf --output "${SCRATCH}/big-needed" --replace-needed "${oldLibc}" long_long_very_long_libc.so.6 --replace-needed libfoo.so lf.so big-dynstr -if [ -z "$(../src/patchelf --print-needed ${SCRATCH}/big-needed | grep -Fx "long_long_very_long_libc.so.6")" ]; then +if ! ../src/patchelf --print-needed "${SCRATCH}/big-needed" | grep -Fxq "long_long_very_long_libc.so.6"; then echo "library long_long_very_long_libc.so.6 not found as NEEDED" - ../src/patchelf --print-needed ${SCRATCH}/big-needed + ../src/patchelf --print-needed "${SCRATCH}/big-needed" exit 1 fi -if [ -z "$(../src/patchelf --print-needed ${SCRATCH}/big-needed | grep -Fx "lf.so")" ]; then +if ! ../src/patchelf --print-needed "${SCRATCH}/big-needed" | grep -Fxq "lf.so"; then echo "library lf.so not found as NEEDED" - ../src/patchelf --print-needed ${SCRATCH}/big-needed + ../src/patchelf --print-needed "${SCRATCH}/big-needed" exit 1 fi diff --git a/tests/set-empty-rpath.sh b/tests/set-empty-rpath.sh index de846a27..b6408227 100755 --- a/tests/set-empty-rpath.sh +++ b/tests/set-empty-rpath.sh @@ -1,11 +1,11 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp simple ${SCRATCH}/simple +cp simple "${SCRATCH}"/simple -../src/patchelf --force-rpath --set-rpath "" ${SCRATCH}/simple +../src/patchelf --force-rpath --set-rpath "" "${SCRATCH}/simple" -${SCRATCH}/simple +"${SCRATCH}"/simple diff --git a/tests/set-interpreter-long.sh b/tests/set-interpreter-long.sh index 058ccd22..f1e0d2f9 100755 --- a/tests/set-interpreter-long.sh +++ b/tests/set-interpreter-long.sh @@ -1,5 +1,5 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) ./simple @@ -11,24 +11,24 @@ if test "$(uname)" = Linux; then "$oldInterpreter" ./simple fi -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -newInterpreter=$(pwd)/${SCRATCH}/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii -cp simple ${SCRATCH}/ -../src/patchelf --set-interpreter "$newInterpreter" ${SCRATCH}/simple +newInterpreter="$(pwd)/${SCRATCH}/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" +cp simple "${SCRATCH}/" +../src/patchelf --set-interpreter "$newInterpreter" "${SCRATCH}/simple" echo "running with missing interpreter..." -if ${SCRATCH}/simple; then +if "${SCRATCH}"/simple; then echo "simple works, but it shouldn't" exit 1 fi echo "running with new interpreter..." ln -s "$oldInterpreter" "$newInterpreter" -${SCRATCH}/simple +"${SCRATCH}"/simple if test "$(uname)" = Linux; then echo "running with explicit interpreter..." - "$oldInterpreter" ${SCRATCH}/simple + "$oldInterpreter" "${SCRATCH}/simple" fi diff --git a/tests/set-interpreter-short.sh b/tests/set-interpreter-short.sh index 2c9f4eb4..69746dae 100755 --- a/tests/set-interpreter-short.sh +++ b/tests/set-interpreter-short.sh @@ -1,19 +1,19 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) ./simple oldInterpreter=$(../src/patchelf --print-interpreter ./simple) echo "current interpreter is $oldInterpreter" -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp simple ${SCRATCH}/ -../src/patchelf --set-interpreter /oops ${SCRATCH}/simple +cp simple "${SCRATCH}"/ +../src/patchelf --set-interpreter /oops "${SCRATCH}/simple" echo "running with missing interpreter..." -if ${SCRATCH}/simple; then +if "${SCRATCH}/simple"; then echo "simple works, but it shouldn't" exit 1 fi diff --git a/tests/set-rpath-library.sh b/tests/set-rpath-library.sh index a5c8ca79..55661a13 100755 --- a/tests/set-rpath-library.sh +++ b/tests/set-rpath-library.sh @@ -1,40 +1,40 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) if test "$(uname)" = FreeBSD; then echo "skipping on FreeBSD" exit 0 fi -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -mkdir -p ${SCRATCH}/libsA -mkdir -p ${SCRATCH}/libsB +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +mkdir -p "${SCRATCH}/libsA" +mkdir -p "${SCRATCH}/libsB" -cp main-scoped ${SCRATCH}/ -cp libfoo-scoped.so ${SCRATCH}/libsA/ -cp libbar-scoped.so ${SCRATCH}/libsB/ +cp main-scoped "${SCRATCH}/" +cp libfoo-scoped.so "${SCRATCH}/libsA/" +cp libbar-scoped.so "${SCRATCH}/libsB/" -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main-scoped) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}"/main-scoped) if test -z "$oldRPath"; then oldRPath="/oops"; fi -../src/patchelf --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main-scoped +../src/patchelf --set-rpath "$oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/main-scoped" # "main" contains libbar in its RUNPATH, but that's ignored when # resolving libfoo. So libfoo won't find libbar and this will fail. exitCode=0 -(cd ${SCRATCH} && ./main-scoped) || exitCode=$? +(cd "${SCRATCH}" && ./main-scoped) || exitCode=$? if test "$exitCode" = 46; then echo "expected failure" fi # So set an RUNPATH on libfoo as well. -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/libsA/libfoo-scoped.so) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}/libsA/libfoo-scoped.so") if test -z "$oldRPath"; then oldRPath="/oops"; fi -../src/patchelf --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/libsA/libfoo-scoped.so +../src/patchelf --set-rpath "$oldRPath:$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/libsA/libfoo-scoped.so" exitCode=0 -(cd ${SCRATCH} && ./main-scoped) || exitCode=$? +(cd "${SCRATCH}" && ./main-scoped) || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" @@ -42,15 +42,15 @@ if test "$exitCode" != 46; then fi # Remove the libbar PATH from main using --shrink-rpath. -../src/patchelf --shrink-rpath ${SCRATCH}/main-scoped -if ../src/patchelf --print-rpath ${SCRATCH}/main-scoped | grep /libsB; then +../src/patchelf --shrink-rpath "${SCRATCH}/main-scoped" +if ../src/patchelf --print-rpath "${SCRATCH}/main-scoped" | grep /libsB; then echo "shrink failed" exit 1 fi # And it should still run. exitCode=0 -(cd ${SCRATCH} && ./main-scoped) || exitCode=$? +(cd "${SCRATCH}" && ./main-scoped) || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" diff --git a/tests/set-rpath-rel-map.sh b/tests/set-rpath-rel-map.sh index 48bc361b..2f890f20 100755 --- a/tests/set-rpath-rel-map.sh +++ b/tests/set-rpath-rel-map.sh @@ -1,6 +1,6 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) OBJDUMP=${OBJDUMP:-objdump} OBJCOPY=${OBJCOPY:-objcopy} @@ -9,29 +9,30 @@ if ! $OBJDUMP -p main | grep -q MIPS_RLD_MAP_REL; then exit 0 fi -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -mkdir -p ${SCRATCH}/libsA -mkdir -p ${SCRATCH}/libsB +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +mkdir -p "${SCRATCH}/libsA" +mkdir -p "${SCRATCH}/libsB" -cp main ${SCRATCH}/ -cp libfoo.so ${SCRATCH}/libsA/ -cp libbar.so ${SCRATCH}/libsB/ +cp main "${SCRATCH}/" +cp libfoo.so "${SCRATCH}/libsA/" +cp libbar.so "${SCRATCH}/libsB/" # break the main executable by removing .rld_map section -${OBJCOPY} --remove-section .rld_map ${SCRATCH}/main +${OBJCOPY} --remove-section .rld_map "${SCRATCH}/main" -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}/main") if test -z "$oldRPath"; then oldRPath="/oops"; fi -../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main +../src/patchelf --force-rpath --set-rpath "$oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/main" if test "$(uname)" = FreeBSD; then - export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB + LD_LIBRARY_PATH=$(pwd)/"${SCRATCH}"/libsB + export LD_LIBRARY_PATH fi exitCode=0 -(cd ${SCRATCH} && ./main) || exitCode=$? +(cd "${SCRATCH}" && ./main) || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" diff --git a/tests/set-rpath.sh b/tests/set-rpath.sh index 90452f9f..565582ae 100755 --- a/tests/set-rpath.sh +++ b/tests/set-rpath.sh @@ -1,25 +1,26 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -mkdir -p ${SCRATCH}/libsA -mkdir -p ${SCRATCH}/libsB +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +mkdir -p "${SCRATCH}"/libsA +mkdir -p "${SCRATCH}"/libsB -cp main ${SCRATCH}/ -cp libfoo.so ${SCRATCH}/libsA/ -cp libbar.so ${SCRATCH}/libsB/ +cp main "${SCRATCH}"/ +cp libfoo.so "${SCRATCH}/libsA/" +cp libbar.so "${SCRATCH}/libsB/" -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}/main") if test -z "$oldRPath"; then oldRPath="/oops"; fi -../src/patchelf --force-rpath --set-rpath $oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB ${SCRATCH}/main +../src/patchelf --force-rpath --set-rpath "$oldRPath:$(pwd)/${SCRATCH}/libsA:$(pwd)/${SCRATCH}/libsB" "${SCRATCH}/main" if test "$(uname)" = FreeBSD; then - export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB + LD_LIBRARY_PATH="$(pwd)/${SCRATCH}/libsB" + export LD_LIBRARY_PATH fi exitCode=0 -(cd ${SCRATCH} && ./main) || exitCode=$? +(cd "${SCRATCH}" && ./main) || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" diff --git a/tests/shrink-rpath-with-allowed-prefixes.sh b/tests/shrink-rpath-with-allowed-prefixes.sh index db24da28..aca8d069 100755 --- a/tests/shrink-rpath-with-allowed-prefixes.sh +++ b/tests/shrink-rpath-with-allowed-prefixes.sh @@ -1,47 +1,47 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -mkdir -p ${SCRATCH}/libsA -mkdir -p ${SCRATCH}/libsB +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +mkdir -p "${SCRATCH}/libsA" +mkdir -p "${SCRATCH}/libsB" -cp main ${SCRATCH}/ -cp libfoo.so libbar.so ${SCRATCH}/libsA/ -cp libfoo.so libbar.so ${SCRATCH}/libsB/ +cp main "${SCRATCH}"/ +cp libfoo.so libbar.so "${SCRATCH}/libsA/" +cp libfoo.so libbar.so "${SCRATCH}/libsB/" -oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/main) +oldRPath=$(../src/patchelf --print-rpath "${SCRATCH}/main") if test -z "$oldRPath"; then oldRPath="/oops"; fi pathA="$(pwd)/${SCRATCH}/libsA" pathB="$(pwd)/${SCRATCH}/libsB" -../src/patchelf --force-rpath --set-rpath $oldRPath:$pathA:$pathB ${SCRATCH}/main +../src/patchelf --force-rpath --set-rpath "$oldRPath:$pathA:$pathB" "${SCRATCH}/main" -cp ${SCRATCH}/main ${SCRATCH}/mainA -cp ${SCRATCH}/main ${SCRATCH}/mainB +cp "${SCRATCH}"/main "${SCRATCH}/mainA" +cp "${SCRATCH}"/main "${SCRATCH}/mainB" -../src/patchelf --shrink-rpath ${SCRATCH}/main -../src/patchelf --shrink-rpath --allowed-rpath-prefixes $oldRPath:$pathA ${SCRATCH}/mainA -../src/patchelf --shrink-rpath --allowed-rpath-prefixes $oldRPath:$pathB ${SCRATCH}/mainB +../src/patchelf --shrink-rpath "${SCRATCH}/main" +../src/patchelf --shrink-rpath --allowed-rpath-prefixes "$oldRPath:$pathA" "${SCRATCH}/mainA" +../src/patchelf --shrink-rpath --allowed-rpath-prefixes "$oldRPath:$pathB" "${SCRATCH}/mainB" check() { exe=$1 mustContain=$2 mustNotContain=$3 - rpath=$(../src/patchelf --print-rpath $exe) + rpath=$(../src/patchelf --print-rpath "$exe") echo "RPATH of $exe after: $rpath" - if ! echo "$rpath" | grep -q $mustContain; then + if ! echo "$rpath" | grep -q "$mustContain"; then echo "RPATH didn't contain '$mustContain' when it should have" exit 1 fi - if echo "$rpath" | grep -q $mustNotContain; then + if echo "$rpath" | grep -q "$mustNotContain"; then echo "RPATH contained '$mustNotContain' when it shouldn't have" exit 1 fi } -check ${SCRATCH}/main $pathA $pathB -check ${SCRATCH}/mainA $pathA $pathB -check ${SCRATCH}/mainB $pathB $pathA +check "${SCRATCH}/main" "$pathA" "$pathB" +check "${SCRATCH}/mainA" "$pathA" "$pathB" +check "${SCRATCH}/mainB" "$pathB" "$pathA" diff --git a/tests/shrink-rpath.sh b/tests/shrink-rpath.sh index 3adc8465..6944a442 100755 --- a/tests/shrink-rpath.sh +++ b/tests/shrink-rpath.sh @@ -1,5 +1,5 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) rpath=$(../src/patchelf --print-rpath ./libbar.so) echo "RPATH before: $rpath" @@ -8,22 +8,22 @@ if ! echo "$rpath" | grep -q /no-such-path; then exit 1 fi -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -cp libbar.so ${SCRATCH}/ -../src/patchelf --shrink-rpath ${SCRATCH}/libbar.so +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +cp libbar.so "${SCRATCH}"/ +../src/patchelf --shrink-rpath "${SCRATCH}/libbar.so" -rpath=$(../src/patchelf --print-rpath ${SCRATCH}/libbar.so) +rpath=$(../src/patchelf --print-rpath "${SCRATCH}/libbar.so") echo "RPATH after: $rpath" if echo "$rpath" | grep -q /no-such-path; then echo "RPATH not shrunk" exit 1 fi -cp libfoo.so ${SCRATCH}/ +cp libfoo.so "${SCRATCH}/" exitCode=0 -cd ${SCRATCH} && LD_LIBRARY_PATH=. ../../main || exitCode=$? +cd "${SCRATCH}" && LD_LIBRARY_PATH=. ../../main || exitCode=$? if test "$exitCode" != 46; then echo "bad exit code!" diff --git a/tests/soname.sh b/tests/soname.sh index 4a8fb96e..683e481f 100755 --- a/tests/soname.sh +++ b/tests/soname.sh @@ -1,29 +1,29 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp libsimple.so ${SCRATCH}/ +cp libsimple.so "${SCRATCH}/" # set an initial DT_SONAME entry -../src/patchelf --set-soname libsimple.so.1.0 ${SCRATCH}/libsimple.so -newSoname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so) +../src/patchelf --set-soname libsimple.so.1.0 "${SCRATCH}/libsimple.so" +newSoname=$(../src/patchelf --print-soname "${SCRATCH}/libsimple.so") if test "$newSoname" != libsimple.so.1.0; then echo "failed --set-soname test. Expected newSoname: libsimple.so.1.0, got: $newSoname" exit 1 fi # print DT_SONAME -soname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so) +soname=$(../src/patchelf --print-soname "${SCRATCH}/libsimple.so") if test "$soname" != libsimple.so.1.0; then echo "failed --print-soname test. Expected soname: libsimple.so.1.0, got: $soname" exit 1 fi # replace DT_SONAME entry -../src/patchelf --set-soname libsimple.so.1.1 ${SCRATCH}/libsimple.so -newSoname=$(../src/patchelf --print-soname ${SCRATCH}/libsimple.so) +../src/patchelf --set-soname libsimple.so.1.1 "${SCRATCH}/libsimple.so" +newSoname=$(../src/patchelf --print-soname "${SCRATCH}/libsimple.so") if test "$newSoname" != libsimple.so.1.1; then echo "failed --set-soname test. Expected newSoname: libsimple.so.1.1, got: $newSoname" exit 1 diff --git a/tests/too-many-strtab.sh b/tests/too-many-strtab.sh index 3ef158f7..96006a4b 100755 --- a/tests/too-many-strtab.sh +++ b/tests/too-many-strtab.sh @@ -1,19 +1,19 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp libtoomanystrtab.so ${SCRATCH}/ +cp libtoomanystrtab.so "${SCRATCH}"/ # Set a RUNPATH on the library -../src/patchelf --set-rpath '$ORIGIN' ${SCRATCH}/libtoomanystrtab.so +../src/patchelf --set-rpath "\$ORIGIN" "${SCRATCH}/libtoomanystrtab.so" # Check that patchelf is able to patch it again without crashing. Previously, # it will wrongly identify the lib as a static object because there was no # .dynamic section exitCode=0 -(../src/patchelf --set-rpath '$ORIGIN' ${SCRATCH}/libtoomanystrtab.so) || exitCode=$? +(../src/patchelf --set-rpath "\$ORIGIN" "${SCRATCH}/libtoomanystrtab.so") || exitCode=$? if test "$exitCode" != 0; then echo "bad exit code!" exit 1 From a97bfdf479930c8ba3c457bc4eb5caf6a60bc0b2 Mon Sep 17 00:00:00 2001 From: Breno Rodrigues Guimaraes Date: Sat, 11 Mar 2023 11:34:25 -0300 Subject: [PATCH 06/30] Fix all shellcheck issues (cherry picked from commit 8adc31ed7b30b689e50314c1c8a1842bc6e164af) --- tests/endianness.sh | 2 +- tests/no-rpath-pie-powerpc.sh | 10 +++++----- tests/no-rpath-prebuild.sh | 4 ++-- tests/phdr-corruption.sh | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/endianness.sh b/tests/endianness.sh index fc2994b5..41890f0a 100755 --- a/tests/endianness.sh +++ b/tests/endianness.sh @@ -6,7 +6,7 @@ for arch in ppc64 ppc64le; do rm -rf "${SCRATCH}" mkdir -p "${SCRATCH}" - cp "${srcdir}/endianness/${arch}/main" "${srcdir}/endianness/${arch}/libtest.so" "${SCRATCH}/" + cp "${srcdir:?}/endianness/${arch}/main" "${srcdir}/endianness/${arch}/libtest.so" "${SCRATCH}/" rpath="${PWD}/${SCRATCH}" diff --git a/tests/no-rpath-pie-powerpc.sh b/tests/no-rpath-pie-powerpc.sh index 963797c6..c2b50fe5 100755 --- a/tests/no-rpath-pie-powerpc.sh +++ b/tests/no-rpath-pie-powerpc.sh @@ -3,17 +3,17 @@ set -x SCRATCH=scratch/no-rpath-pie-powerpc READELF=${READELF:-readelf} -no_rpath_bin="${srcdir}/no-rpath-prebuild/no-rpath-pie-powerpc" +no_rpath_bin="${srcdir:?}/no-rpath-prebuild/no-rpath-pie-powerpc" -if [ ! -f $no_rpath_bin ]; then - echo "no 'no-rpath' binary for '$ARCH' in '${srcdir}/no-rpath-prebuild'" +if [ ! -f "$no_rpath_bin" ]; then + echo "no 'no-rpath' binary for '$ARCH' in '${srcdir:?}/no-rpath-prebuild'" exit 1 fi rm -rf ${SCRATCH} mkdir -p ${SCRATCH} -cp $no_rpath_bin ${SCRATCH}/no-rpath +cp "$no_rpath_bin" ${SCRATCH}/no-rpath oldRPath=$(../src/patchelf --print-rpath ${SCRATCH}/no-rpath) if test -n "$oldRPath"; then exit 1; fi @@ -30,7 +30,7 @@ fi # Tests for powerpc PIE endianness regressions readelfData=$(${READELF} -l ${SCRATCH}/no-rpath 2>&1) -if [ $(echo "$readelfData" | grep "PHDR" | wc -l) != 1 ]; then +if [ "$(echo "$readelfData" | grep -c "PHDR")" != 1 ]; then # Triggered if PHDR errors appear on stderr echo "Unexpected number of occurences of PHDR in readelf results" exit 1 diff --git a/tests/no-rpath-prebuild.sh b/tests/no-rpath-prebuild.sh index 143c55ce..aeeecf80 100755 --- a/tests/no-rpath-prebuild.sh +++ b/tests/no-rpath-prebuild.sh @@ -14,10 +14,10 @@ if [ -z "$ARCH" ] || [ "$ARCH" = prebuild ] ; then exit 1 fi -no_rpath_bin="${srcdir}/no-rpath-prebuild/no-rpath-$ARCH" +no_rpath_bin="${srcdir:?}/no-rpath-prebuild/no-rpath-$ARCH" if [ ! -f "$no_rpath_bin" ]; then - echo "no 'no-rpath' binary for '$ARCH' in '${srcdir}/no-rpath-prebuild'" + echo "no 'no-rpath' binary for '$ARCH' in '${srcdir:?}/no-rpath-prebuild'" exit 1 fi diff --git a/tests/phdr-corruption.sh b/tests/phdr-corruption.sh index 4f6e9019..274d6f1f 100755 --- a/tests/phdr-corruption.sh +++ b/tests/phdr-corruption.sh @@ -15,7 +15,7 @@ cp "${SONAME}" "${SCRATCH}" # Check for PT_PHDR entry VirtAddr corruption readelfData=$(${READELF} -l "${SCRATCH_SO}" 2>&1) -if [ "$(echo "$readelfData" | grep "PHDR" | wc -l)" != 1 ]; then +if [ "$(echo "$readelfData" | grep -c "PHDR")" != 1 ]; then # Triggered if PHDR errors appear on stderr echo "ERROR: Unexpected number of occurences of PHDR in readelf results!" exit 1 From 344efe7cefb4eeb7ac8bdce5898906e5ff775fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sat, 16 Jul 2022 08:48:47 +0200 Subject: [PATCH 07/30] README: move release history to ChangeLog.md John thinks its better that we keep this information in-repo. It just doesn't need to go in the read-em. Co-Authored-By: John Ericson --- ChangeLog.md | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 160 --------------------------------------------------- 2 files changed, 159 insertions(+), 160 deletions(-) create mode 100644 ChangeLog.md diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 00000000..85be876d --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,159 @@ +## Release History + +0.14.5 (February 21, 2022): + +* fix faulty version in 0.14.4 + +0.14.4 (February 21, 2022): + +* Several test fixes to fix patchelf test suite on openbsd by @klemensn +* Allow multiple modifications in same call by @fzakaria in https://github.com/NixOS/patchelf/pull/361 +* Add support to build with musl by @fzakaria in https://github.com/NixOS/patchelf/pull/362 +* Fix typo: s/folllow/follow/ by @bjornfor in https://github.com/NixOS/patchelf/pull/366 +* mips: fix incorrect polarity on dyn_offset; closes #364 by @a-m-joseph in https://github.com/NixOS/patchelf/pull/365 + +0.14.3 (December 05, 2021): + +* this release adds support for static, pre-compiled patchelf binaries + +0.14.2 (November 29, 2021): + +* make version number in tarball easier to use for packagers + +0.14.1 (November 28, 2021): + +* build fix: add missing include + +0.14 (November 27, 2021): + +Changes compared to 0.13: + +* Bug fixes: + - Fix corrupted library names when using --replace-needed multiple times + - Fix setting an empty rpath + - Don't try to parse .dynamic section of type NOBITS + - Fix use-after-free in normalizeNoteSegments + - Correct EINTR handling in writeFile + - MIPS: Adjust PT_MIPS_ABIFLAGS segment and DT_MIPS_RLD_MAP_REL dynamic section if present + - Fix binaries without .gnu.hash section +* Support loongarch architecture +* Remove limits on output file size for elf files +* Allow reading rpath from file +* Requires now C++17 for building + +0.13.1 (November 27, 2021): + +* Bug fixes: + - fix setting empty rpath + - use memcpy instead of strcpy to set rpath + - Don't try to parse .dynamic section of type NOBITS + - fix use-after-free in normalizeNoteSegments + - correct EINTR handling in writeFile + - Adjust PT_MIPS_ABIFLAGS segment if present + - Adjust DT_MIPS_RLD_MAP_REL dynamic section entry if present + - fix binaries without .gnu.hash section + +0.13 (August 5, 2021): + +* New `--add-rpath` flag. + +* Bug fixes. + +0.12 (August 27, 2020): + +* New `--clear-symbol-version` flag. + +* Better support for relocating NOTE sections/segments. + +* Improved the default section alignment choice. + +* Bug fixes. + +0.11 (June 9, 2020): + +* New `--output` flag. + +* Some bug fixes. + +0.10 (March 28, 2019): + +* Many bug fixes. Please refer to the Git commit log: + + https://github.com/NixOS/patchelf/commits/master + + This release has contributions from Adam Trhoň, Benjamin Hipple, + Bernardo Ramos, Bjørn Forsman, Domen Kožar, Eelco Dolstra, Ezra + Cooper, Felipe Sateler, Jakub Wilk, James Le Cuirot, Karl Millar, + Linus Heckemann, Nathaniel J. Smith, Richard Purdie, Stanislav + Markevich and Tuomas Tynkkynen. + +0.9 (February 29, 2016): + +* Lots of new features. Please refer to the Git commit log: + + https://github.com/NixOS/patchelf/commits/master + + This release has contributions from Aaron D. Marasco, Adrien + Devresse, Alexandre Pretyman, Changli Gao, Chingis Dugarzhapov, + darealshinji, David Sveningsson, Eelco Dolstra, Felipe Sateler, + Jeremy Sanders, Jonas Kuemmerlin, Thomas Tuegel, Tuomas Tynkkynen, + Vincent Danjean and Vladimír Čunát. + +0.8 (January 15, 2014): + +* Fix a segfault caused by certain illegal entries in symbol tables. + +0.7 (January 7, 2014): + +* Rewrite section indices in symbol tables. This for instance allows + gdb to show proper backtraces. + +* Added `--remove-needed' option. + +0.6 (November 7, 2011): + +* Hacky support for executables created by the Gold linker. + +* Support segments with an alignment of 0 (contributed by Zack + Weinberg). + +* Added a manual page (contributed by Jeremy Sanders + ). + +0.5 (November 4, 2009): + +* Various bugfixes. + +* `--force-rpath' now deletes the DT_RUNPATH if it is present. + +0.4 (June 4, 2008): + +* Support for growing the RPATH on dynamic libraries. + +* IA-64 support (not tested) and related 64-bit fixes. + +* FreeBSD support. + +* `--set-rpath', `--shrink-rpath' and `--print-rpath' now prefer + DT_RUNPATH over DT_RPATH, which is obsolete. When updating, if both + are present, both are updated. If only DT_RPATH is present, it is + converted to DT_RUNPATH unless `--force-rpath' is specified. If + neither is present, a DT_RUNPATH is added unless `--force-rpath' is + specified, in which case a DT_RPATH is added. + +0.3 (May 24, 2007): + +* Support for 64-bit ELF binaries (such as on x86_64-linux). + +* Support for big-endian ELF binaries (such as on powerpc-linux). + +* Various bugfixes. + +0.2 (January 15, 2007): + +* Provides a hack to get certain programs (such as the + Belastingaangifte 2005) to work. + +0.1 (October 11, 2005): + +* Initial release. diff --git a/README.md b/README.md index 6e2d112a..0b433771 100644 --- a/README.md +++ b/README.md @@ -131,163 +131,3 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . - -## Release History - -0.14.5 (February 21, 2022): - -* fix faulty version in 0.14.4 - -0.14.4 (February 21, 2022): - -* Several test fixes to fix patchelf test suite on openbsd by @klemensn -* Allow multiple modifications in same call by @fzakaria in https://github.com/NixOS/patchelf/pull/361 -* Add support to build with musl by @fzakaria in https://github.com/NixOS/patchelf/pull/362 -* Fix typo: s/folllow/follow/ by @bjornfor in https://github.com/NixOS/patchelf/pull/366 -* mips: fix incorrect polarity on dyn_offset; closes #364 by @a-m-joseph in https://github.com/NixOS/patchelf/pull/365 - -0.14.3 (December 05, 2021): - -* this release adds support for static, pre-compiled patchelf binaries - -0.14.2 (November 29, 2021): - -* make version number in tarball easier to use for packagers - -0.14.1 (November 28, 2021): - -* build fix: add missing include - -0.14 (November 27, 2021): - -Changes compared to 0.13: - -* Bug fixes: - - Fix corrupted library names when using --replace-needed multiple times - - Fix setting an empty rpath - - Don't try to parse .dynamic section of type NOBITS - - Fix use-after-free in normalizeNoteSegments - - Correct EINTR handling in writeFile - - MIPS: Adjust PT_MIPS_ABIFLAGS segment and DT_MIPS_RLD_MAP_REL dynamic section if present - - Fix binaries without .gnu.hash section -* Support loongarch architecture -* Remove limits on output file size for elf files -* Allow reading rpath from file -* Requires now C++17 for building - -0.13.1 (November 27, 2021): - -* Bug fixes: - - fix setting empty rpath - - use memcpy instead of strcpy to set rpath - - Don't try to parse .dynamic section of type NOBITS - - fix use-after-free in normalizeNoteSegments - - correct EINTR handling in writeFile - - Adjust PT_MIPS_ABIFLAGS segment if present - - Adjust DT_MIPS_RLD_MAP_REL dynamic section entry if present - - fix binaries without .gnu.hash section - -0.13 (August 5, 2021): - -* New `--add-rpath` flag. - -* Bug fixes. - -0.12 (August 27, 2020): - -* New `--clear-symbol-version` flag. - -* Better support for relocating NOTE sections/segments. - -* Improved the default section alignment choice. - -* Bug fixes. - -0.11 (June 9, 2020): - -* New `--output` flag. - -* Some bug fixes. - -0.10 (March 28, 2019): - -* Many bug fixes. Please refer to the Git commit log: - - https://github.com/NixOS/patchelf/commits/master - - This release has contributions from Adam Trhoň, Benjamin Hipple, - Bernardo Ramos, Bjørn Forsman, Domen Kožar, Eelco Dolstra, Ezra - Cooper, Felipe Sateler, Jakub Wilk, James Le Cuirot, Karl Millar, - Linus Heckemann, Nathaniel J. Smith, Richard Purdie, Stanislav - Markevich and Tuomas Tynkkynen. - -0.9 (February 29, 2016): - -* Lots of new features. Please refer to the Git commit log: - - https://github.com/NixOS/patchelf/commits/master - - This release has contributions from Aaron D. Marasco, Adrien - Devresse, Alexandre Pretyman, Changli Gao, Chingis Dugarzhapov, - darealshinji, David Sveningsson, Eelco Dolstra, Felipe Sateler, - Jeremy Sanders, Jonas Kuemmerlin, Thomas Tuegel, Tuomas Tynkkynen, - Vincent Danjean and Vladimír Čunát. - -0.8 (January 15, 2014): - -* Fix a segfault caused by certain illegal entries in symbol tables. - -0.7 (January 7, 2014): - -* Rewrite section indices in symbol tables. This for instance allows - gdb to show proper backtraces. - -* Added `--remove-needed' option. - -0.6 (November 7, 2011): - -* Hacky support for executables created by the Gold linker. - -* Support segments with an alignment of 0 (contributed by Zack - Weinberg). - -* Added a manual page (contributed by Jeremy Sanders - ). - -0.5 (November 4, 2009): - -* Various bugfixes. - -* `--force-rpath' now deletes the DT_RUNPATH if it is present. - -0.4 (June 4, 2008): - -* Support for growing the RPATH on dynamic libraries. - -* IA-64 support (not tested) and related 64-bit fixes. - -* FreeBSD support. - -* `--set-rpath', `--shrink-rpath' and `--print-rpath' now prefer - DT_RUNPATH over DT_RPATH, which is obsolete. When updating, if both - are present, both are updated. If only DT_RPATH is present, it is - converted to DT_RUNPATH unless `--force-rpath' is specified. If - neither is present, a DT_RUNPATH is added unless `--force-rpath' is - specified, in which case a DT_RPATH is added. - -0.3 (May 24, 2007): - -* Support for 64-bit ELF binaries (such as on x86_64-linux). - -* Support for big-endian ELF binaries (such as on powerpc-linux). - -* Various bugfixes. - -0.2 (January 15, 2007): - -* Provides a hack to get certain programs (such as the - Belastingaangifte 2005) to work. - -0.1 (October 11, 2005): - -* Initial release. From c0ee925daf8dfc38d2e8a6bdeb4157f720fdb834 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Aug 2025 15:13:53 -0400 Subject: [PATCH 08/30] Add 0.15 release info Taken for retroactive documentation from GitHub. --- ChangeLog.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 85be876d..e52d27c4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,15 @@ ## Release History +0.15.0 (Jul 16, 2022): + +* Add --add-debug option by @deadw00d in https://github.com/NixOS/patchelf/pull/367 +* Add O_BINARY flag when opening files to allow compilation for Windows by @JagoGyselinck in https://github.com/NixOS/patchelf/pull/372 +* Document --print-needed by @klemensn in https://github.com/NixOS/patchelf/pull/375 +* modifyRPath: return early if new and old rpath are empty by @ehmry in https://github.com/NixOS/patchelf/pull/376 +* Add comment explaining calculation for DT_MIPS_RLD_MAP_REL by @amjoseph-nixpkgs in https://github.com/NixOS/patchelf/pull/379 +* Add --no-sort option by @amjoseph-nixpkgs in https://github.com/NixOS/patchelf/pull/378 +* Handle DT_MIPS_XHASH and .MIPS.xhash by @amjoseph-nixpkgs in https://github.com/NixOS/patchelf/pull/380 + 0.14.5 (February 21, 2022): * fix faulty version in 0.14.4 From 5baeaeecd58045871182f8e511ef187d022b3ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:44 +0100 Subject: [PATCH 09/30] Add required includes in header file Enable to parse the header file on its own, e.g. for language servers (clangd). (cherry picked from commit ce5907fc40d5e355872a4288fde3de7586e6e766) --- src/patchelf.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/patchelf.h b/src/patchelf.h index 33ecfc3f..97fa3830 100644 --- a/src/patchelf.h +++ b/src/patchelf.h @@ -1,3 +1,12 @@ +#include +#include +#include +#include +#include +#include + +#include "elf.h" + using FileContents = std::shared_ptr>; #define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn, class Elf_Sym, class Elf_Verneed, class Elf_Versym From 728797dbed16fd3b8e8357b01ba8b72b0aca57fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:52 +0100 Subject: [PATCH 10/30] Add misc functions annotations Make the behavior of functions more explicit. (cherry picked from commit fbb12a72ad1a98c079597b820364196fcfc512af) --- src/patchelf.cc | 8 ++++---- src/patchelf.h | 32 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index 49accae1..fa4b770e 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -90,7 +90,7 @@ static bool hasAllowedPrefix(const std::string & s, const std::vector template -I ElfFile::rdi(I i) const +constexpr I ElfFile::rdi(I i) const noexcept { I r = 0; if (littleEndian) { @@ -117,7 +117,7 @@ static void debug(const char * format, ...) } -void fmt2(std::ostringstream & out) +static void fmt2([[maybe_unused]] std::ostringstream & out) { } @@ -295,7 +295,7 @@ ElfFile::ElfFile(FileContents fContents) template -unsigned int ElfFile::getPageSize() const +unsigned int ElfFile::getPageSize() const noexcept { if (forcedPageSize > 0) return forcedPageSize; @@ -498,7 +498,7 @@ std::optional> ElfFile::tryF template -unsigned int ElfFile::getSectionIndex(const SectionName & sectionName) +unsigned int ElfFile::getSectionIndex(const SectionName & sectionName) const { for (unsigned int i = 1; i < rdi(hdr()->e_shnum); ++i) if (getSectionName(shdrs.at(i)) == sectionName) return i; diff --git a/src/patchelf.h b/src/patchelf.h index 97fa3830..9231806a 100644 --- a/src/patchelf.h +++ b/src/patchelf.h @@ -39,14 +39,14 @@ class ElfFile /* Align on 4 or 8 bytes boundaries on 32- or 64-bit platforms respectively. */ - size_t sectionAlignment = sizeof(Elf_Off); + static constexpr size_t sectionAlignment = sizeof(Elf_Off); std::vector sectionsByOldIndex; public: explicit ElfFile(FileContents fileContents); - bool isChanged() + [[nodiscard]] bool isChanged() const noexcept { return changed; } @@ -55,8 +55,8 @@ class ElfFile struct CompPhdr { - ElfFile * elfFile; - bool operator ()(const Elf_Phdr & x, const Elf_Phdr & y) + const ElfFile * elfFile; + bool operator ()(const Elf_Phdr & x, const Elf_Phdr & y) const noexcept { // A PHDR comes before everything else. if (elfFile->rdi(y.p_type) == PT_PHDR) return false; @@ -73,8 +73,8 @@ class ElfFile struct CompShdr { - ElfFile * elfFile; - bool operator ()(const Elf_Shdr & x, const Elf_Shdr & y) + const ElfFile * elfFile; + bool operator ()(const Elf_Shdr & x, const Elf_Shdr & y) const noexcept { return elfFile->rdi(x.sh_offset) < elfFile->rdi(y.sh_offset); } @@ -82,24 +82,24 @@ class ElfFile friend struct CompShdr; - unsigned int getPageSize() const; + [[nodiscard]] unsigned int getPageSize() const noexcept; void sortShdrs(); void shiftFile(unsigned int extraPages, Elf_Addr startPage); - std::string getSectionName(const Elf_Shdr & shdr) const; + [[nodiscard]] std::string getSectionName(const Elf_Shdr & shdr) const; Elf_Shdr & findSectionHeader(const SectionName & sectionName); - std::optional> tryFindSectionHeader(const SectionName & sectionName); + [[nodiscard]] std::optional> tryFindSectionHeader(const SectionName & sectionName); - unsigned int getSectionIndex(const SectionName & sectionName); + [[nodiscard]] unsigned int getSectionIndex(const SectionName & sectionName) const; std::string & replaceSection(const SectionName & sectionName, unsigned int size); - bool haveReplacedSection(const SectionName & sectionName) const; + [[nodiscard]] bool haveReplacedSection(const SectionName & sectionName) const; void writeReplacedSections(Elf_Off & curOff, Elf_Addr startAddr, Elf_Off startOffset); @@ -116,7 +116,7 @@ class ElfFile void rewriteSections(); - std::string getInterpreter(); + [[nodiscard]] std::string getInterpreter(); typedef enum { printSoname, replaceSoname } sonameMode; @@ -150,21 +150,21 @@ class ElfFile specified by the ELF header) to this platform's integer representation. */ template - I rdi(I i) const; + constexpr I rdi(I i) const noexcept; /* Convert back to the ELF representation. */ template - I wri(I & t, unsigned long long i) const + constexpr I wri(I & t, unsigned long long i) const { t = rdi((I) i); return i; } - Elf_Ehdr *hdr() { + [[nodiscard]] Elf_Ehdr *hdr() noexcept { return (Elf_Ehdr *)fileContents->data(); } - const Elf_Ehdr *hdr() const { + [[nodiscard]] const Elf_Ehdr *hdr() const noexcept { return (const Elf_Ehdr *)fileContents->data(); } }; From 547d8d7bd2a5e830f67e1ccdd418d44884d0ca06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:54 +0100 Subject: [PATCH 11/30] Drop unnecessary friend declarations (cherry picked from commit 09673eb553b3dc7c67627b51c34a8b9cc2f8d0f4) --- src/patchelf.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/patchelf.h b/src/patchelf.h index 9231806a..9fa218b3 100644 --- a/src/patchelf.h +++ b/src/patchelf.h @@ -67,8 +67,6 @@ class ElfFile } }; - friend struct CompPhdr; - void sortPhdrs(); struct CompShdr @@ -80,8 +78,6 @@ class ElfFile } }; - friend struct CompShdr; - [[nodiscard]] unsigned int getPageSize() const noexcept; void sortShdrs(); From d8de74379910820ec87760fa648b58da719965f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:55 +0100 Subject: [PATCH 12/30] Use C++ casts instead of raw C ones in hdr() (cherry picked from commit 404761cf4df321580b40baacd50cd3d3e5cb643f) --- src/patchelf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patchelf.h b/src/patchelf.h index 9fa218b3..3ae57f00 100644 --- a/src/patchelf.h +++ b/src/patchelf.h @@ -157,10 +157,10 @@ class ElfFile } [[nodiscard]] Elf_Ehdr *hdr() noexcept { - return (Elf_Ehdr *)fileContents->data(); + return reinterpret_cast(fileContents->data()); } [[nodiscard]] const Elf_Ehdr *hdr() const noexcept { - return (const Elf_Ehdr *)fileContents->data(); + return reinterpret_cast(fileContents->data()); } }; From de48fab274b159f37d968795ebfb8cd0d298dd33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:56 +0100 Subject: [PATCH 13/30] Avoid unnecessary copies in splitColonDelimitedString() Avoid creating a stringstream by using find(). (cherry picked from commit a3934549633550ea625604c03e25724664048f40) --- src/patchelf.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index fa4b770e..dde7a45a 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -69,14 +70,18 @@ static int forcedPageSize = -1; #define EM_LOONGARCH 258 #endif - -static std::vector splitColonDelimitedString(const char * s) +[[nodiscard]] static std::vector splitColonDelimitedString(std::string_view s) { - std::string item; std::vector parts; - std::stringstream ss(s); - while (std::getline(ss, item, ':')) - parts.push_back(item); + + size_t pos; + while ((pos = s.find(':')) != std::string_view::npos) { + parts.emplace_back(s.substr(0, pos)); + s = s.substr(pos + 1); + } + + if (!s.empty()) + parts.emplace_back(s); return parts; } From 45a6dcee396a643f6b3f036a5aa3f516777d184b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:57 +0100 Subject: [PATCH 14/30] Close file before potentially throwing (cherry picked from commit c00676a28af82f4c73c19916b803d7058f02d104) --- src/patchelf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index dde7a45a..2e1589d9 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -182,11 +182,11 @@ static FileContents readFile(const std::string & fileName, while ((portion = read(fd, contents->data() + bytesRead, size - bytesRead)) > 0) bytesRead += portion; + close(fd); + if (bytesRead != size) throw SysError(fmt("reading '", fileName, "'")); - close(fd); - return contents; } From 2b9700b6433211930881f9e235e625dfc5969407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:58 +0100 Subject: [PATCH 15/30] Drop unnecessary casts in getElfType() Also declare the function static and warn if return value not used. (cherry picked from commit 98d1813f2516aa4c771dd8824e7cada98393049f) --- src/patchelf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index 2e1589d9..6da5a5fa 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -198,10 +198,10 @@ struct ElfType }; -ElfType getElfType(const FileContents & fileContents) +[[nodiscard]] static ElfType getElfType(const FileContents & fileContents) { /* Check the ELF header for basic validity. */ - if (fileContents->size() < static_cast(sizeof(Elf32_Ehdr))) + if (fileContents->size() < sizeof(Elf32_Ehdr)) error("missing ELF header"); auto contents = fileContents->data(); From 602405bb135a409eb766bec903c4737c85bef018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:40:59 +0100 Subject: [PATCH 16/30] Avoid potential overflows in checkPointer() Prevent overflows in the addtion of q and size, and avoid truncations in callers by using size_t as type for size. (cherry picked from commit e8832294372f0e7c69948d701f3613183a4f78a2) --- src/patchelf.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index 6da5a5fa..20add452 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -222,10 +222,9 @@ struct ElfType } -static void checkPointer(const FileContents & contents, void * p, unsigned int size) +static void checkPointer(const FileContents & contents, const void * p, size_t size) { - auto q = static_cast(p); - if (!(q >= contents->data() && q + size <= contents->data() + contents->size())) + if (p < contents->data() || size > contents->size() || p > contents->data() + contents->size() - size) error("data region extends past file end"); } From 986a0aeebadea56f7376577a95426e81c3bd35ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:41:01 +0100 Subject: [PATCH 17/30] Use C++11 [[noreturn]] (cherry picked from commit b2897ab819812060c43ebc9fafa1483b1843536b) --- src/patchelf.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index 20add452..c11e595e 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -153,7 +153,7 @@ struct SysError : std::runtime_error { } }; -__attribute__((noreturn)) static void error(const std::string & msg) +[[noreturn]] static void error(const std::string & msg) { if (errno) throw SysError(msg); From a188583fb0254d5dc5045a10e7f8475285245d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:41:02 +0100 Subject: [PATCH 18/30] Drop superfluous semicolons (cherry picked from commit 1c2d1fffaffb1cd97b49d48c503d8dde03f56696) --- src/patchelf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index c11e595e..edbee44f 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -1320,7 +1320,7 @@ void ElfFile::modifyRPath(RPathOp op, case rpPrint: { printf("%s\n", rpath ? rpath : ""); return; - }; + } case rpRemove: { if (!rpath) { debug("no RPATH to delete\n"); @@ -1333,7 +1333,7 @@ void ElfFile::modifyRPath(RPathOp op, if (!rpath) { debug("no RPATH to shrink\n"); return; - ;} + } newRPath = shrinkRPath(rpath, neededLibs, allowedRpathPrefixes); break; } From 86c3d0f4419a1cf28f026c73eeb2fcf8f4fe70e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:41:03 +0100 Subject: [PATCH 19/30] Declare file local functions static (cherry picked from commit 889350de509de7d5d6724b66c18ef1e09c92cbb1) --- src/patchelf.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index edbee44f..d326b5cf 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -1827,7 +1827,7 @@ static void patchElf() } } -std::string resolveArgument(const char *arg) { +[[nodiscard]] static std::string resolveArgument(const char *arg) { if (strlen(arg) > 0 && arg[0] == '@') { FileContents cnts = readFile(arg + 1); return std::string((char *)cnts->data(), cnts->size()); @@ -1837,7 +1837,7 @@ std::string resolveArgument(const char *arg) { } -void showHelp(const std::string & progName) +static void showHelp(const std::string & progName) { fprintf(stderr, "syntax: %s\n\ [--set-interpreter FILENAME]\n\ @@ -1867,7 +1867,7 @@ void showHelp(const std::string & progName) } -int mainWrapped(int argc, char * * argv) +static int mainWrapped(int argc, char * * argv) { if (argc <= 1) { showHelp(argv[0]); From daba6af2927a4d2e4046597e0d6c3928d8e188e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:41:04 +0100 Subject: [PATCH 20/30] Avoid dropping const qualifier (cherry picked from commit b5b59ca4cbdc7bc9ba30c46fb6307edfdfe90c94) --- src/patchelf.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index d326b5cf..4e5338ff 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -558,7 +558,7 @@ void ElfFile::writeReplacedSections(Elf_Off & curOff, debug("rewriting section '%s' from offset 0x%x (size %d) to offset 0x%x (size %d)\n", sectionName.c_str(), rdi(shdr.sh_offset), rdi(shdr.sh_size), curOff, i.second.size()); - memcpy(fileContents->data() + curOff, (unsigned char *) i.second.c_str(), + memcpy(fileContents->data() + curOff, i.second.c_str(), i.second.size()); /* Update the section header for this section. */ @@ -1165,7 +1165,7 @@ void ElfFile::modifySoname(sonameMode op, const std::string & std::string & newDynamic = replaceSection(".dynamic", rdi(shdrDynamic.sh_size) + sizeof(Elf_Dyn)); unsigned int idx = 0; - for (; rdi(((Elf_Dyn *) newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++); + for (; rdi(reinterpret_cast(newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++); debug("DT_NULL index is %d\n", idx); /* Shift all entries down by one. */ @@ -1399,7 +1399,7 @@ void ElfFile::modifyRPath(RPathOp op, rdi(shdrDynamic.sh_size) + sizeof(Elf_Dyn)); unsigned int idx = 0; - for ( ; rdi(((Elf_Dyn *) newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; + for ( ; rdi(reinterpret_cast(newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; debug("DT_NULL index is %d\n", idx); /* Shift all entries down by one. */ @@ -1601,7 +1601,7 @@ void ElfFile::addNeeded(const std::set & libs) rdi(shdrDynamic.sh_size) + sizeof(Elf_Dyn) * libs.size()); unsigned int idx = 0; - for ( ; rdi(((Elf_Dyn *) newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; + for ( ; rdi(reinterpret_cast(newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; debug("DT_NULL index is %d\n", idx); /* Shift all entries down by the number of new entries. */ @@ -1663,7 +1663,7 @@ void ElfFile::noDefaultLib() rdi(shdrDynamic.sh_size) + sizeof(Elf_Dyn)); unsigned int idx = 0; - for ( ; rdi(((Elf_Dyn *) newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; + for ( ; rdi(reinterpret_cast(newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; debug("DT_NULL index is %d\n", idx); /* Shift all entries down by one. */ @@ -1696,7 +1696,7 @@ void ElfFile::addDebugTag() rdi(shdrDynamic.sh_size) + sizeof(Elf_Dyn)); unsigned int idx = 0; - for ( ; rdi(((Elf_Dyn *) newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; + for ( ; rdi(reinterpret_cast(newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ; debug("DT_NULL index is %d\n", idx); /* Shift all entries down by one. */ From 90bad95364d4ec4bb840cad5dc18c8bb4da11106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:41:06 +0100 Subject: [PATCH 21/30] Avoid implicit value truncations in wri() Abort on truncation of values being written to the ELF data, to prevent silent behavior mismatch. (cherry picked from commit 28e95b30f3e7f1920a51a43ae275ec6f3508b495) --- src/patchelf.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/patchelf.h b/src/patchelf.h index 3ae57f00..095b4c47 100644 --- a/src/patchelf.h +++ b/src/patchelf.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -149,11 +150,14 @@ class ElfFile constexpr I rdi(I i) const noexcept; /* Convert back to the ELF representation. */ - template - constexpr I wri(I & t, unsigned long long i) const + template + constexpr inline I wri(I & t, U i) const { - t = rdi((I) i); - return i; + I val = static_cast(i); + if (static_cast(val) != i) + throw std::runtime_error { "value truncation" }; + t = rdi(val); + return val; } [[nodiscard]] Elf_Ehdr *hdr() noexcept { From 89d970597ff9d5819a96a414098c7d00c0564452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Tue, 21 Feb 2023 19:41:07 +0100 Subject: [PATCH 22/30] Avoid implicit conversion Use auto to avoid implicit type conversion, hiding possible value truncation. (cherry picked from commit 00d1e82f2b1e415ec66d9aacb7e760d3ff617f02) --- src/patchelf.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patchelf.cc b/src/patchelf.cc index 4e5338ff..22ce7c70 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -276,11 +276,11 @@ ElfFile::ElfFile(FileContents fContents) /* Get the section header string table section (".shstrtab"). Its index in the section header table is given by e_shstrndx field of the ELF header. */ - unsigned int shstrtabIndex = rdi(hdr()->e_shstrndx); + auto shstrtabIndex = rdi(hdr()->e_shstrndx); if (shstrtabIndex >= shdrs.size()) error("string table index out of bounds"); - unsigned int shstrtabSize = rdi(shdrs[shstrtabIndex].sh_size); + auto shstrtabSize = rdi(shdrs[shstrtabIndex].sh_size); char * shstrtab = (char * ) fileContents->data() + rdi(shdrs[shstrtabIndex].sh_offset); checkPointer(fileContents, shstrtab, shstrtabSize); From 4ac172be9afa01147c157066afb113c4578b445f Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Aug 2025 15:48:41 -0400 Subject: [PATCH 23/30] Format markdown in the commit log --- ChangeLog.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index e52d27c4..e00da50c 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,6 @@ ## Release History -0.15.0 (Jul 16, 2022): +## 0.15.0 (Jul 16, 2022) * Add --add-debug option by @deadw00d in https://github.com/NixOS/patchelf/pull/367 * Add O_BINARY flag when opening files to allow compilation for Windows by @JagoGyselinck in https://github.com/NixOS/patchelf/pull/372 @@ -10,11 +10,11 @@ * Add --no-sort option by @amjoseph-nixpkgs in https://github.com/NixOS/patchelf/pull/378 * Handle DT_MIPS_XHASH and .MIPS.xhash by @amjoseph-nixpkgs in https://github.com/NixOS/patchelf/pull/380 -0.14.5 (February 21, 2022): +## 0.14.5 (February 21, 2022) * fix faulty version in 0.14.4 -0.14.4 (February 21, 2022): +## 0.14.4 (February 21, 2022) * Several test fixes to fix patchelf test suite on openbsd by @klemensn * Allow multiple modifications in same call by @fzakaria in https://github.com/NixOS/patchelf/pull/361 @@ -22,19 +22,19 @@ * Fix typo: s/folllow/follow/ by @bjornfor in https://github.com/NixOS/patchelf/pull/366 * mips: fix incorrect polarity on dyn_offset; closes #364 by @a-m-joseph in https://github.com/NixOS/patchelf/pull/365 -0.14.3 (December 05, 2021): +## 0.14.3 (December 05, 2021) * this release adds support for static, pre-compiled patchelf binaries -0.14.2 (November 29, 2021): +## 0.14.2 (November 29, 2021) * make version number in tarball easier to use for packagers -0.14.1 (November 28, 2021): +## 0.14.1 (November 28, 2021) * build fix: add missing include -0.14 (November 27, 2021): +## 0.14 (November 27, 2021) Changes compared to 0.13: @@ -51,7 +51,7 @@ Changes compared to 0.13: * Allow reading rpath from file * Requires now C++17 for building -0.13.1 (November 27, 2021): +## 0.13.1 (November 27, 2021) * Bug fixes: - fix setting empty rpath @@ -63,13 +63,13 @@ Changes compared to 0.13: - Adjust DT_MIPS_RLD_MAP_REL dynamic section entry if present - fix binaries without .gnu.hash section -0.13 (August 5, 2021): +## 0.13 (August 5, 2021) * New `--add-rpath` flag. * Bug fixes. -0.12 (August 27, 2020): +## 0.12 (August 27, 2020) * New `--clear-symbol-version` flag. @@ -79,13 +79,13 @@ Changes compared to 0.13: * Bug fixes. -0.11 (June 9, 2020): +## 0.11 (June 9, 2020) * New `--output` flag. * Some bug fixes. -0.10 (March 28, 2019): +## 0.10 (March 28, 2019) * Many bug fixes. Please refer to the Git commit log: @@ -97,7 +97,7 @@ Changes compared to 0.13: Linus Heckemann, Nathaniel J. Smith, Richard Purdie, Stanislav Markevich and Tuomas Tynkkynen. -0.9 (February 29, 2016): +## 0.9 (February 29, 2016) * Lots of new features. Please refer to the Git commit log: @@ -109,18 +109,18 @@ Changes compared to 0.13: Jeremy Sanders, Jonas Kuemmerlin, Thomas Tuegel, Tuomas Tynkkynen, Vincent Danjean and Vladimír Čunát. -0.8 (January 15, 2014): +## 0.8 (January 15, 2014) * Fix a segfault caused by certain illegal entries in symbol tables. -0.7 (January 7, 2014): +## 0.7 (January 7, 2014) * Rewrite section indices in symbol tables. This for instance allows gdb to show proper backtraces. * Added `--remove-needed' option. -0.6 (November 7, 2011): +## 0.6 (November 7, 2011) * Hacky support for executables created by the Gold linker. @@ -130,13 +130,13 @@ Changes compared to 0.13: * Added a manual page (contributed by Jeremy Sanders ). -0.5 (November 4, 2009): +## 0.5 (November 4, 2009) * Various bugfixes. * `--force-rpath' now deletes the DT_RUNPATH if it is present. -0.4 (June 4, 2008): +## 0.4 (June 4, 2008) * Support for growing the RPATH on dynamic libraries. @@ -151,7 +151,7 @@ Changes compared to 0.13: neither is present, a DT_RUNPATH is added unless `--force-rpath' is specified, in which case a DT_RPATH is added. -0.3 (May 24, 2007): +## 0.3 (May 24, 2007) * Support for 64-bit ELF binaries (such as on x86_64-linux). @@ -159,11 +159,11 @@ Changes compared to 0.13: * Various bugfixes. -0.2 (January 15, 2007): +## 0.2 (January 15, 2007) * Provides a hack to get certain programs (such as the Belastingaangifte 2005) to work. -0.1 (October 11, 2005): +## 0.1 (October 11, 2005) * Initial release. From 64e8cf5c1221ddaa76b2aa362a81db63ae63dc86 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Aug 2025 15:57:44 -0400 Subject: [PATCH 24/30] Add change log for a potential, not-yet-released 0.15.1 --- ChangeLog.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index e00da50c..133a84f3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,15 @@ ## Release History +## 0.15.1 (not yet released) + +The objective is to prepare a very conservative patch release which can be bumped in Nixpkgs immediately. + +* Backport infra changes from later master (August 2025) +* Backport shellcheck fixes to test suite +* Backport C++ code quality fixes (all of https://github.com/NixOS/patchelf/pull/464 but the final two commits) + +The behavior of this version should be essentially the same as 0.15.0. + ## 0.15.0 (Jul 16, 2022) * Add --add-debug option by @deadw00d in https://github.com/NixOS/patchelf/pull/367 From db8cbe93f20d5b676c82ac2e093e94b87f249ceb Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Aug 2025 16:10:17 -0400 Subject: [PATCH 25/30] Release 0.15.1 --- ChangeLog.md | 4 ++-- version | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 133a84f3..8f1778cc 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,6 @@ ## Release History -## 0.15.1 (not yet released) +## 0.15.1 (August 12, 2025) The objective is to prepare a very conservative patch release which can be bumped in Nixpkgs immediately. @@ -10,7 +10,7 @@ The objective is to prepare a very conservative patch release which can be bumpe The behavior of this version should be essentially the same as 0.15.0. -## 0.15.0 (Jul 16, 2022) +## 0.15.0 (July 16, 2022) * Add --add-debug option by @deadw00d in https://github.com/NixOS/patchelf/pull/367 * Add O_BINARY flag when opening files to allow compilation for Windows by @JagoGyselinck in https://github.com/NixOS/patchelf/pull/372 diff --git a/version b/version index 7092c7c4..e815b861 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.15.0 \ No newline at end of file +0.15.1 From edec2a9ad7572bcc27ced962728f1b80fd0cc7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 19 Feb 2023 08:55:11 +0100 Subject: [PATCH 26/30] tests: apply suggestions from shellcheck Re-cherry-pick for the files that were not in the last cherry-pick. (cherry picked from commit be4b84635f806998853825e23d94b14723e37b55) --- tests/change-abi.sh | 45 +++++++++++++++------------------------------ tests/empty-note.sh | 10 +++++----- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/tests/change-abi.sh b/tests/change-abi.sh index 26a151dc..03c5f9b0 100755 --- a/tests/change-abi.sh +++ b/tests/change-abi.sh @@ -1,44 +1,29 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" -cp simple-pie ${SCRATCH}/simple-pie +cp simple-pie "${SCRATCH}/simple-pie" # Save the old OS ABI -OLDABI=`../src/patchelf --print-os-abi ${SCRATCH}/simple-pie` +OLDABI=$(../src/patchelf --print-os-abi "${SCRATCH}/simple-pie") # Ensure it's not empty test -n "$OLDABI" # Change OS ABI and verify it has been changed -{ - echo "System V" - echo "HP-UX" - echo "NetBSD" - echo "Linux" - echo "GNU Hurd" - echo "Solaris" - echo "AIX" - echo "IRIX" - echo "FreeBSD" - echo "Tru64" - echo "OpenBSD" - echo "OpenVMS" -} | { - while IFS="\n" read ABI; do - echo "Set OS ABI to '$ABI'..." - ../src/patchelf --set-os-abi "$ABI" ${SCRATCH}/simple-pie - - echo "Check is OS ABI is '$ABI'..." - NEWABI=`../src/patchelf --print-os-abi ${SCRATCH}/simple-pie` - test "$NEWABI" = "$ABI" - done -} +for ABI in "System V" "HP-UX" "NetBSD" "Linux" "GNU Hurd" "Solaris" "AIX" "IRIX" "FreeBSD" "Tru64" "OpenBSD" "OpenVMS"; do + echo "Set OS ABI to '$ABI'..." + ../src/patchelf --set-os-abi "$ABI" "${SCRATCH}/simple-pie" + + echo "Check is OS ABI is '$ABI'..." + NEWABI=$(../src/patchelf --print-os-abi "${SCRATCH}/simple-pie") + test "$NEWABI" = "$ABI" +done # Reset OS ABI to the saved one -../src/patchelf --set-os-abi "$OLDABI" ${SCRATCH}/simple-pie +../src/patchelf --set-os-abi "$OLDABI" "${SCRATCH}/simple-pie" # Verify we still can run the executable -${SCRATCH}/simple-pie +"${SCRATCH}/simple-pie" diff --git a/tests/empty-note.sh b/tests/empty-note.sh index c127d8cc..57656fbc 100755 --- a/tests/empty-note.sh +++ b/tests/empty-note.sh @@ -1,12 +1,12 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) -rm -rf ${SCRATCH} -mkdir -p ${SCRATCH} -cp $(dirname $(readlink -f $0))/empty-note ${SCRATCH}/ +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" +cp "$(dirname "$(readlink -f "$0")")/empty-note" "${SCRATCH}/" # Running --set-interpreter on this binary should not produce the following # error: # patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections -../src/patchelf --set-interpreter ld-linux-x86-64.so.2 ${SCRATCH}/empty-note +../src/patchelf --set-interpreter ld-linux-x86-64.so.2 "${SCRATCH}/empty-note" From 3449f5fa8d06e07f8502fab79b88c8e318740baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Sun, 19 Feb 2023 08:55:11 +0100 Subject: [PATCH 27/30] tests: apply suggestions from shellcheck Re-cherry-pick for the files that were not in the last cherry-pick. (cherry picked from commit be4b84635f806998853825e23d94b14723e37b55) --- tests/add-debug-tag.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/add-debug-tag.sh b/tests/add-debug-tag.sh index 16d9bb50..37bf957d 100755 --- a/tests/add-debug-tag.sh +++ b/tests/add-debug-tag.sh @@ -1,5 +1,5 @@ #! /bin/sh -e -SCRATCH=scratch/$(basename $0 .sh) +SCRATCH=scratch/$(basename "$0" .sh) READELF=${READELF:-readelf} rm -rf "${SCRATCH}" From 731fcc20efee0dad96e1151e4974fc1532e8444e Mon Sep 17 00:00:00 2001 From: Heiko Becker Date: Mon, 7 Nov 2022 23:16:24 +0100 Subject: [PATCH 28/30] Also pass STRIP to the tests It is used in tests/no-gnu-hash.sh. (cherry picked from commit d9ff3986346beafb2cc79b6316c9c9541f5e36b8) --- tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index d9bf5d2a..ca8c3804 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,7 +50,7 @@ TESTS = $(src_TESTS) $(build_TESTS) EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness -TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 OBJDUMP=$(OBJDUMP) READELF=$(READELF) OBJCOPY=$(OBJCOPY) +TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 STRIP=$(STRIP) OBJDUMP=$(OBJDUMP) READELF=$(READELF) OBJCOPY=$(OBJCOPY) $(no_rpath_arch_TESTS): no-rpath-prebuild.sh @ln -s $< $@ From 6b0d9338877f14ee35334d90b6e3945f9ec1eeb0 Mon Sep 17 00:00:00 2001 From: Heiko Becker Date: Mon, 24 Apr 2023 22:10:10 +0200 Subject: [PATCH 29/30] Also respect a prefixed nm and strings too (cherry picked from commit 1ab6930d154b4bd6cee8f2751dd4429d92a4a67d) --- tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index ca8c3804..a11e4d7d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,7 +50,7 @@ TESTS = $(src_TESTS) $(build_TESTS) EXTRA_DIST = no-rpath-prebuild $(src_TESTS) no-rpath-prebuild.sh invalid-elf endianness -TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 STRIP=$(STRIP) OBJDUMP=$(OBJDUMP) READELF=$(READELF) OBJCOPY=$(OBJCOPY) +TESTS_ENVIRONMENT = PATCHELF_DEBUG=1 STRIP=$(STRIP) NM=$(NM) OBJDUMP=$(OBJDUMP) READELF=$(READELF) OBJCOPY=$(OBJCOPY) STRINGS=$(STRINGS) $(no_rpath_arch_TESTS): no-rpath-prebuild.sh @ln -s $< $@ From 58f5b195036b1e37ee2e15301dfa96a2673327da Mon Sep 17 00:00:00 2001 From: John Ericson Date: Tue, 12 Aug 2025 17:16:59 -0400 Subject: [PATCH 30/30] Release 0.15.2 Very minor, just a build system thing. See change log. --- ChangeLog.md | 6 ++++++ version | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 8f1778cc..1f408ab1 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,11 @@ ## Release History +## 0.15.2 (August 12, 2025) + +* In the autotools build system for the tests, pass a few more tool env vars in `TESTS_ENVIRONMENT`. + + Some of them are not used yet (at all, or at least not in this backport to the `0.15-maintenance` branch), but at least `STRIP` is. + ## 0.15.1 (August 12, 2025) The objective is to prepare a very conservative patch release which can be bumped in Nixpkgs immediately. diff --git a/version b/version index e815b861..4312e0d0 100644 --- a/version +++ b/version @@ -1 +1 @@ -0.15.1 +0.15.2