Hello community, here is the log from the commit of package patchelf for openSUSE:Factory checked in at 2020-09-21 17:11:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/patchelf (Old) and /work/SRC/openSUSE:Factory/.patchelf.new.4249 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "patchelf" Mon Sep 21 17:11:07 2020 rev:13 rq:835417 version:0.12 Changes: -------- --- /work/SRC/openSUSE:Factory/patchelf/patchelf.changes 2020-08-19 18:46:19.447512389 +0200 +++ /work/SRC/openSUSE:Factory/.patchelf.new.4249/patchelf.changes 2020-09-21 17:12:46.587426574 +0200 @@ -1,0 +2,11 @@ +Fri Sep 11 21:00:31 UTC 2020 - Dirk Mueller <[email protected]> + +- update to 0.12: + * skip overwriting r(un)path data when old_rpath = new_rpath. + * patchelf: Check ELF endianness before writing new runpath + * use stable_sort to maintain relative order for equal elemnts + * add --clear-symbol-version + * Improve the default section alignment choice + * Some const-correctness and C++11 auto + +------------------------------------------------------------------- Old: ---- patchelf-0.11.tar.bz2 New: ---- patchelf-0.12.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ patchelf.spec ++++++ --- /var/tmp/diff_new_pack.PQs3P9/_old 2020-09-21 17:12:50.411430012 +0200 +++ /var/tmp/diff_new_pack.PQs3P9/_new 2020-09-21 17:12:50.411430012 +0200 @@ -17,13 +17,13 @@ Name: patchelf -Version: 0.11 +Version: 0.12 Release: 0 Summary: A utility for patching ELF binaries License: GPL-3.0-only Group: Development/Libraries/C and C++ URL: https://nixos.org/patchelf.html -Source: https://nixos.org/releases/patchelf/patchelf-%{version}/patchelf-%{version}.tar.bz2 +Source: https://github.com/NixOS/patchelf/releases/download/%{version}/patchelf-%{version}.tar.bz2 BuildRequires: gcc-c++ %description @@ -32,7 +32,7 @@ executables and change the RPATH of executables and libraries. %prep -%setup -q -n %{name}-0.11.20200609.d6b2a72 +%setup -q -n %{name}-0.12.20200827.8d3a16e %build %configure ++++++ patchelf-0.11.tar.bz2 -> patchelf-0.12.tar.bz2 ++++++ ++++ 2033 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/README.md new/patchelf-0.12.20200827.8d3a16e/README.md --- old/patchelf-0.11.20200609.d6b2a72/README.md 1970-01-01 01:00:01.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/README.md 1970-01-01 01:00:01.000000000 +0100 @@ -3,69 +3,86 @@ * Change the dynamic loader ("ELF interpreter") of executables: + ```console $ patchelf --set-interpreter /lib/my-ld-linux.so.2 my-program + ``` -* Change the RPATH of executables and libraries: +* Change the `RPATH` of executables and libraries: + ```console $ patchelf --set-rpath /opt/my-libs/lib:/other-libs my-program + ``` -* Shrink the RPATH of executables and libraries: +* Shrink the `RPATH` of executables and libraries: + ```console $ patchelf --shrink-rpath my-program + ``` - This removes from the RPATH all directories that do not contain a - library referenced by DT_NEEDED fields of the executable or library. - For instance, if an executable references one library libfoo.so, has - an RPATH "/lib:/usr/lib:/foo/lib", and libfoo.so can only be found - in /foo/lib, then the new RPATH will be "/foo/lib". - - In addition, the '--allowed-rpath-prefixes' option can be used for - further rpath tuning. For instance, if an executable has an RPATH - "/tmp/build-foo/.libs:/foo/lib", it is probably desirable to keep - the "/foo/lib" reference instead of the "/tmp" entry. To accomplish + This removes from the `RPATH` all directories that do not contain a + library referenced by `DT_NEEDED` fields of the executable or library. + For instance, if an executable references one library `libfoo.so`, has + an RPATH `/lib:/usr/lib:/foo/lib`, and `libfoo.so` can only be found + in `/foo/lib`, then the new `RPATH` will be `/foo/lib`. + + In addition, the `--allowed-rpath-prefixes` option can be used for + further rpath tuning. For instance, if an executable has an `RPATH` + `/tmp/build-foo/.libs:/foo/lib`, it is probably desirable to keep + the `/foo/lib` reference instead of the `/tmp` entry. To accomplish that, use: + ```console $ patchelf --shrink-rpath --allowed-rpath-prefixes /usr/lib:/foo/lib my-program + ``` -* Remove declared dependencies on dynamic libraries (DT_NEEDED +* Remove declared dependencies on dynamic libraries (`DT_NEEDED` entries): + ```console $ patchelf --remove-needed libfoo.so.1 my-program + ``` This option can be given multiple times. -* Add a declared dependency on a dynamic library (DT_NEEDED): +* Add a declared dependency on a dynamic library (`DT_NEEDED`): + ```console $ patchelf --add-needed libfoo.so.1 my-program + ``` This option can be give multiple times. * Replace a declared dependency on a dynamic library with another one - (DT_NEEDED): + (`DT_NEEDED`): + ```console $ patchelf --replace-needed liboriginal.so.1 libreplacement.so.1 my-program + ``` This option can be give multiple times. -* Change SONAME of a dynamic library: +* Change `SONAME` of a dynamic library: + ```console $ patchelf --set-soname libnewname.so.3.4.5 path/to/libmylibrary.so.1.2.3 + ``` -## COMPILING & TESTING +## Compiling and Testing - ./bootstrap.sh - ./configure - make - sudo make install - make check +```console +./bootstrap.sh +./configure +make +make check +sudo make install +``` -## AUTHOR +## Author Copyright 2004-2019 Eelco Dolstra <[email protected]>. - -## LICENSE +## License This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -80,7 +97,17 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. -## RELEASE HISTORY +## Release History + +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): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/build-aux/test-driver new/patchelf-0.12.20200827.8d3a16e/build-aux/test-driver --- old/patchelf-0.11.20200609.d6b2a72/build-aux/test-driver 1970-01-01 01:00:00.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/build-aux/test-driver 2020-08-27 14:12:59.000000000 +0200 @@ -0,0 +1,148 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 2011-2018 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU 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 <https://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <[email protected]> or send patches to +# <[email protected]>. + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <<END +Usage: + test-driver --test-name=NAME --log-file=PATH --trs-file=PATH + [--expect-failure={yes|no}] [--color-tests={yes|no}] + [--enable-hard-errors={yes|no}] [--] + TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] +The '--test-name', '--log-file' and '--trs-file' options are mandatory. +END +} + +test_name= # Used for reporting. +log_file= # Where to save the output of the test script. +trs_file= # Where to save the metadata of the test run. +expect_failure=no +color_tests=no +enable_hard_errors=yes +while test $# -gt 0; do + case $1 in + --help) print_usage; exit $?;; + --version) echo "test-driver $scriptversion"; exit $?;; + --test-name) test_name=$2; shift;; + --log-file) log_file=$2; shift;; + --trs-file) trs_file=$2; shift;; + --color-tests) color_tests=$2; shift;; + --expect-failure) expect_failure=$2; shift;; + --enable-hard-errors) enable_hard_errors=$2; shift;; + --) shift; break;; + -*) usage_error "invalid option: '$1'";; + *) break;; + esac + shift +done + +missing_opts= +test x"$test_name" = x && missing_opts="$missing_opts --test-name" +test x"$log_file" = x && missing_opts="$missing_opts --log-file" +test x"$trs_file" = x && missing_opts="$missing_opts --trs-file" +if test x"$missing_opts" != x; then + usage_error "the following mandatory options are missing:$missing_opts" +fi + +if test $# -eq 0; then + usage_error "missing argument" +fi + +if test $color_tests = yes; then + # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'. + red='[0;31m' # Red. + grn='[0;32m' # Green. + lgn='[1;32m' # Light green. + blu='[1;34m' # Blue. + mgn='[0;35m' # Magenta. + std='[m' # No color. +else + red= grn= lgn= blu= mgn= std= +fi + +do_exit='rm -f $log_file $trs_file; (exit $st); exit $st' +trap "st=129; $do_exit" 1 +trap "st=130; $do_exit" 2 +trap "st=141; $do_exit" 13 +trap "st=143; $do_exit" 15 + +# Test script is run here. +"$@" >$log_file 2>&1 +estatus=$? + +if test $enable_hard_errors = no && test $estatus -eq 99; then + tweaked_estatus=1 +else + tweaked_estatus=$estatus +fi + +case $tweaked_estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/configure.ac new/patchelf-0.12.20200827.8d3a16e/configure.ac --- old/patchelf-0.11.20200609.d6b2a72/configure.ac 1970-01-01 01:00:01.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/configure.ac 1970-01-01 01:00:01.000000000 +0100 @@ -1,28 +1,27 @@ +AC_PREREQ([2.62]) AC_INIT([patchelf], m4_esyscmd([printf $(cat ./version)])) AC_CONFIG_SRCDIR([src/patchelf.cc]) AC_CONFIG_AUX_DIR([build-aux]) -AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2 foreign color-tests serial-tests]) +AM_INIT_AUTOMAKE([1.11.1 -Wall -Werror dist-bzip2 foreign color-tests parallel-tests]) AM_PROG_CC_C_O AC_PROG_CXX -PAGESIZE=auto +DEFAULT_PAGESIZE=auto AC_ARG_WITH([page-size], AS_HELP_STRING([--with-page-size=SIZE], [Specify default pagesize (default auto)]), - PAGESIZE=$withval + DEFAULT_PAGESIZE=$withval ) -if test "$PAGESIZE" = auto; then - if command -v getconf >/dev/null; then - PAGESIZE=$(getconf PAGESIZE || getconf PAGE_SIZE) - fi - if test "$PAGESIZE" = auto -o -z "$PAGESIZE"; then - PAGESIZE=4096 - fi +if test "$DEFAULT_PAGESIZE" != auto; then + AC_DEFINE_UNQUOTED(DEFAULT_PAGESIZE, ${DEFAULT_PAGESIZE}) + AC_MSG_RESULT([Setting page size to ${DEFAULT_PAGESIZE}]) fi -AC_DEFINE_UNQUOTED(PAGESIZE, ${PAGESIZE}) -AC_MSG_RESULT([Setting page size to ${PAGESIZE}]) +AC_ARG_WITH([asan], + AS_HELP_STRING([--with-asan], [Link with libasan]) +) +AM_CONDITIONAL([WITH_ASAN], [test x"$with_asan" = xyes]) AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile patchelf.spec]) AC_OUTPUT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/patchelf.spec new/patchelf-0.12.20200827.8d3a16e/patchelf.spec --- old/patchelf-0.11.20200609.d6b2a72/patchelf.spec 2020-06-09 14:58:21.000000000 +0200 +++ new/patchelf-0.12.20200827.8d3a16e/patchelf.spec 2020-08-27 14:13:00.000000000 +0200 @@ -1,7 +1,7 @@ Summary: A utility for patching ELF binaries Name: patchelf -Version: 0.11.20200609.d6b2a72 +Version: 0.12.20200827.8d3a16e Release: 1 License: GPL Group: Development/Tools diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/src/Makefile.am new/patchelf-0.12.20200827.8d3a16e/src/Makefile.am --- old/patchelf-0.11.20200609.d6b2a72/src/Makefile.am 1970-01-01 01:00:01.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/src/Makefile.am 1970-01-01 01:00:01.000000000 +0100 @@ -1,5 +1,9 @@ AM_CXXFLAGS = -Wall -std=c++11 -D_FILE_OFFSET_BITS=64 +if WITH_ASAN +AM_CXXFLAGS += -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1 +endif + bin_PROGRAMS = patchelf patchelf_SOURCES = patchelf.cc elf.h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/src/patchelf.cc new/patchelf-0.12.20200827.8d3a16e/src/patchelf.cc --- old/patchelf-0.11.20200609.d6b2a72/src/patchelf.cc 1970-01-01 01:00:01.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/src/patchelf.cc 1970-01-01 01:00:01.000000000 +0100 @@ -48,13 +48,17 @@ static std::vector<std::string> fileNames; static std::string outputFileName; static bool alwaysWrite = false; -static int pageSize = PAGESIZE; +#ifdef DEFAULT_PAGESIZE +static int forcedPageSize = DEFAULT_PAGESIZE; +#else +static int forcedPageSize = -1; +#endif typedef std::shared_ptr<std::vector<unsigned char>> FileContents; -#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 -#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Verneed +#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 +#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Verneed, Elf_Versym static std::vector<std::string> splitColonDelimitedString(const char * s) @@ -81,12 +85,6 @@ } -static unsigned int getPageSize() -{ - return pageSize; -} - - template<ElfFileParams> class ElfFile { @@ -161,11 +159,13 @@ friend struct CompShdr; + unsigned int getPageSize() const; + void sortShdrs(); void shiftFile(unsigned int extraPages, Elf_Addr startPage); - std::string getSectionName(const Elf_Shdr & shdr); + std::string getSectionName(const Elf_Shdr & shdr) const; Elf_Shdr & findSection(const SectionName & sectionName); @@ -176,7 +176,7 @@ std::string & replaceSection(const SectionName & sectionName, unsigned int size); - bool haveReplacedSection(const SectionName & sectionName); + bool haveReplacedSection(const SectionName & sectionName) const; void writeReplacedSections(Elf_Off & curOff, Elf_Addr startAddr, Elf_Off startOffset); @@ -187,6 +187,8 @@ void rewriteSectionsExecutable(); + void normalizeNoteSegments(); + public: void rewriteSections(); @@ -209,21 +211,23 @@ void replaceNeeded(const std::map<std::string, std::string> & libs); - void printNeededLibs(); + void printNeededLibs() /* should be const */; void noDefaultLib(); + void clearSymbolVersions(const std::set<std::string> & syms); + private: /* Convert an integer in big or little endian representation (as specified by the ELF header) to this platform's integer representation. */ template<class I> - I rdi(I i); + I rdi(I i) const; /* Convert back to the ELF representation. */ template<class I> - I wri(I & t, unsigned long long i) + I wri(I & t, unsigned long long i) const { t = rdi((I) i); return i; @@ -235,7 +239,7 @@ why... */ template<ElfFileParams> template<class I> -I ElfFile<ElfFileParamNames>::rdi(I i) +I ElfFile<ElfFileParamNames>::rdi(I i) const { I r = 0; if (littleEndian) { @@ -251,10 +255,6 @@ } -/* Ugly: used to erase DT_RUNPATH when using --force-rpath. */ -#define DT_IGNORE 0x00726e67 - - static void debug(const char * format, ...) { if (debugMode) { @@ -445,12 +445,35 @@ template<ElfFileParams> +unsigned int ElfFile<ElfFileParamNames>::getPageSize() const +{ + if (forcedPageSize > 0) + return forcedPageSize; + + // Architectures (and ABIs) can have different minimum section alignment + // requirements. There is no authoritative list of these values. The + // current list is extracted from GNU gold's source code (abi_pagesize). + switch (hdr->e_machine) { + case EM_SPARC: + case EM_MIPS: + case EM_PPC: + case EM_PPC64: + case EM_AARCH64: + case EM_TILEGX: + return 0x10000; + default: + return 0x1000; + } +} + + +template<ElfFileParams> void ElfFile<ElfFileParamNames>::sortPhdrs() { /* Sort the segments by offset. */ CompPhdr comp; comp.elfFile = this; - sort(phdrs.begin(), phdrs.end(), comp); + stable_sort(phdrs.begin(), phdrs.end(), comp); } @@ -477,7 +500,7 @@ /* Sort the sections by offset. */ CompShdr comp; comp.elfFile = this; - sort(shdrs.begin() + 1, shdrs.end(), comp); + stable_sort(shdrs.begin() + 1, shdrs.end(), comp); /* Restore the sh_link mappings. */ for (unsigned int i = 1; i < rdi(hdr->e_shnum); ++i) @@ -569,7 +592,7 @@ template<ElfFileParams> -std::string ElfFile<ElfFileParamNames>::getSectionName(const Elf_Shdr & shdr) +std::string ElfFile<ElfFileParamNames>::getSectionName(const Elf_Shdr & shdr) const { return std::string(sectionNames.c_str() + rdi(shdr.sh_name)); } @@ -578,7 +601,7 @@ template<ElfFileParams> Elf_Shdr & ElfFile<ElfFileParamNames>::findSection(const SectionName & sectionName) { - Elf_Shdr * shdr = findSection2(sectionName); + auto shdr = findSection2(sectionName); if (!shdr) { std::string extraMsg = ""; if (sectionName == ".interp" || sectionName == ".dynamic" || sectionName == ".dynstr") @@ -592,7 +615,7 @@ template<ElfFileParams> Elf_Shdr * ElfFile<ElfFileParamNames>::findSection2(const SectionName & sectionName) { - unsigned int i = findSection3(sectionName); + auto i = findSection3(sectionName); return i ? &shdrs[i] : 0; } @@ -606,13 +629,9 @@ } template<ElfFileParams> -bool ElfFile<ElfFileParamNames>::haveReplacedSection(const SectionName & sectionName) +bool ElfFile<ElfFileParamNames>::haveReplacedSection(const SectionName & sectionName) const { - ReplacedSections::iterator i = replacedSections.find(sectionName); - - if (i != replacedSections.end()) - return true; - return false; + return (replacedSections.find(sectionName) != replacedSections.end()); } template<ElfFileParams> @@ -625,7 +644,7 @@ if (i != replacedSections.end()) { s = std::string(i->second); } else { - Elf_Shdr & shdr = findSection(sectionName); + auto shdr = findSection(sectionName); s = std::string((char *) contents + rdi(shdr.sh_offset), rdi(shdr.sh_size)); } @@ -652,7 +671,8 @@ for (auto & i : replacedSections) { std::string sectionName = i.first; - Elf_Shdr & shdr = findSection(sectionName); + auto & shdr = findSection(sectionName); + Elf_Shdr orig_shdr = shdr; 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()); @@ -687,6 +707,41 @@ } } + /* If this is a note section, there might be a PT_NOTE segment that + must be sync'ed with it. Note that normalizeNoteSegments() will have + already taken care of PT_NOTE segments containing multiple note + sections. At this point, we can assume that the segment will map to + exactly one section. + + Note sections also have particular alignment constraints: the + data inside the section is formatted differently depending on the + section alignment. Keep the original alignment if possible. */ + if (rdi(shdr.sh_type) == SHT_NOTE) { + if (orig_shdr.sh_addralign < sectionAlignment) + shdr.sh_addralign = orig_shdr.sh_addralign; + + for (unsigned int j = 0; j < phdrs.size(); ++j) + if (rdi(phdrs[j].p_type) == PT_NOTE) { + Elf_Off p_start = rdi(phdrs[j].p_offset); + Elf_Off p_end = p_start + rdi(phdrs[j].p_filesz); + Elf_Off s_start = rdi(orig_shdr.sh_offset); + Elf_Off s_end = s_start + rdi(orig_shdr.sh_size); + + /* Skip if no overlap. */ + if (!(s_start >= p_start && s_start < p_end) && + !(s_end > p_start && s_end <= p_end)) + continue; + + /* We only support exact matches. */ + if (p_start != s_start || p_end != s_end) + error("unsupported overlap of SHT_NOTE and PT_NOTE"); + + phdrs[j].p_offset = shdr.sh_offset; + phdrs[j].p_vaddr = phdrs[j].p_paddr = shdr.sh_addr; + phdrs[j].p_filesz = phdrs[j].p_memsz = shdr.sh_size; + } + } + curOff += roundUp(i.second.size(), sectionAlignment); } @@ -709,13 +764,20 @@ debug("last page is 0x%llx\n", (unsigned long long) startPage); + /* When normalizing note segments we will in the worst case be adding + 1 program header for each SHT_NOTE section. */ + unsigned int num_notes = 0; + for (const auto & shdr : shdrs) + if (rdi(shdr.sh_type) == SHT_NOTE) + num_notes++; + /* Because we're adding a new section header, we're necessarily increasing the size of the program header table. This can cause the first section to overlap the program header table in memory; we need to shift the first few segments to someplace else. */ /* Some sections may already be replaced so account for that */ unsigned int i = 1; - Elf_Addr pht_size = sizeof(Elf_Ehdr) + (phdrs.size() + 1)*sizeof(Elf_Phdr); + Elf_Addr pht_size = sizeof(Elf_Ehdr) + (phdrs.size() + num_notes + 1)*sizeof(Elf_Phdr); while( shdrs[i].sh_addr <= pht_size && i < rdi(hdr->e_shnum) ) { if (not haveReplacedSection(getSectionName(shdrs[i]))) replaceSection(getSectionName(shdrs[i]), shdrs[i].sh_size); @@ -737,7 +799,7 @@ ET_DYN as does LD when linking with pie. If we move PT_PHDR, it has to stay in the first PT_LOAD segment or any subsequent ones if they're continuous in memory due to linux kernel constraints - (see BUGS). Since the end of the file would be after bss, we can't + (see BUGS). Since the end of the file would be after bss, we can't move PHDR there, we therefore choose to leave PT_PHDR where it is but move enough following sections such that we can add the extra PT_LOAD section to it. This PT_LOAD segment ensures the sections at the end of @@ -764,6 +826,9 @@ wri(phdr.p_align, getPageSize()); + normalizeNoteSegments(); + + /* Write out the replaced sections. */ Elf_Off curOff = startOffset; writeReplacedSections(curOff, startPage, startOffset); @@ -851,6 +916,9 @@ } + normalizeNoteSegments(); + + /* Compute the total space needed for the replaced sections, the ELF header, and the program headers. */ size_t neededSpace = sizeof(Elf_Ehdr) + phdrs.size() * sizeof(Elf_Phdr); @@ -896,6 +964,67 @@ template<ElfFileParams> +void ElfFile<ElfFileParamNames>::normalizeNoteSegments() +{ + /* Break up PT_NOTE segments containing multiple SHT_NOTE sections. This + is to avoid having to deal with moving multiple sections together if + one of them has to be replaced. */ + + /* We don't need to do anything if no note segments were replaced. */ + bool replaced_note = false; + for (const auto & i : replacedSections) { + if (rdi(findSection(i.first).sh_type) == SHT_NOTE) + replaced_note = true; + } + if (!replaced_note) return; + + size_t orig_count = phdrs.size(); + for (size_t i = 0; i < orig_count; ++i) { + auto & phdr = phdrs[i]; + if (rdi(phdr.p_type) != PT_NOTE) continue; + + size_t start_off = rdi(phdr.p_offset); + size_t curr_off = start_off; + size_t end_off = start_off + rdi(phdr.p_filesz); + while (curr_off < end_off) { + /* Find a section that starts at the current offset. If we can't + find one, it means the SHT_NOTE sections weren't contiguous + within the segment. */ + size_t size = 0; + for (const auto & shdr : shdrs) { + if (rdi(shdr.sh_type) != SHT_NOTE) continue; + if (rdi(shdr.sh_offset) != curr_off) continue; + size = rdi(shdr.sh_size); + break; + } + if (size == 0) + error("cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections"); + if (curr_off + size > end_off) + error("cannot normalize PT_NOTE segment: partially mapped SHT_NOTE section"); + + /* Build a new phdr for this note section. */ + Elf_Phdr new_phdr = phdr; + wri(new_phdr.p_offset, curr_off); + wri(new_phdr.p_vaddr, rdi(phdr.p_vaddr) + (curr_off - start_off)); + wri(new_phdr.p_paddr, rdi(phdr.p_paddr) + (curr_off - start_off)); + wri(new_phdr.p_filesz, size); + wri(new_phdr.p_memsz, size); + + /* If we haven't yet, reuse the existing phdr entry. Otherwise add + a new phdr to the table. */ + if (curr_off == start_off) + phdr = new_phdr; + else + phdrs.push_back(new_phdr); + + curr_off += size; + } + } + wri(hdr->e_phnum, phdrs.size()); +} + + +template<ElfFileParams> void ElfFile<ElfFileParamNames>::rewriteSections() { if (replacedSections.empty()) return; @@ -947,7 +1076,7 @@ /* Update all those nasty virtual addresses in the .dynamic section. Note that not all executables have .dynamic sections (e.g., those produced by klibc's klcc). */ - Elf_Shdr * shdrDynamic = findSection2(".dynamic"); + auto shdrDynamic = findSection2(".dynamic"); if (shdrDynamic) { Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic->sh_offset)); unsigned int d_tag; @@ -963,14 +1092,14 @@ else if (d_tag == DT_GNU_HASH) dyn->d_un.d_ptr = findSection(".gnu.hash").sh_addr; else if (d_tag == DT_JMPREL) { - Elf_Shdr * shdr = findSection2(".rel.plt"); + auto shdr = findSection2(".rel.plt"); if (!shdr) shdr = findSection2(".rela.plt"); /* 64-bit Linux, x86-64 */ if (!shdr) shdr = findSection2(".rela.IA_64.pltoff"); /* 64-bit Linux, IA-64 */ if (!shdr) error("cannot find section corresponding to DT_JMPREL"); dyn->d_un.d_ptr = shdr->sh_addr; } else if (d_tag == DT_REL) { /* !!! hack! */ - Elf_Shdr * shdr = findSection2(".rel.dyn"); + auto shdr = findSection2(".rel.dyn"); /* no idea if this makes sense, but it was needed for some program */ if (!shdr) shdr = findSection2(".rel.got"); @@ -980,7 +1109,7 @@ dyn->d_un.d_ptr = shdr->sh_addr; } else if (d_tag == DT_RELA) { - Elf_Shdr * shdr = findSection2(".rela.dyn"); + auto shdr = findSection2(".rela.dyn"); /* some programs lack this section, but it doesn't seem to be a problem */ if (!shdr) continue; @@ -1009,7 +1138,7 @@ } std::string section = sectionsByOldIndex.at(shndx); assert(!section.empty()); - unsigned int newIndex = findSection3(section); // inefficient + auto newIndex = findSection3(section); // inefficient //debug("rewriting symbol %d: index = %d (%s) -> %d\n", entry, shndx, section.c_str(), newIndex); wri(sym->st_shndx, newIndex); /* Rewrite st_value. FIXME: we should do this for all @@ -1033,7 +1162,7 @@ template<ElfFileParams> std::string ElfFile<ElfFileParamNames>::getInterpreter() { - Elf_Shdr & shdr = findSection(".interp"); + auto shdr = findSection(".interp"); return std::string((char *) contents + rdi(shdr.sh_offset), rdi(shdr.sh_size)); } @@ -1045,8 +1174,8 @@ return; } - Elf_Shdr & shdrDynamic = findSection(".dynamic"); - Elf_Shdr & shdrDynStr = findSection(".dynstr"); + auto shdrDynamic = findSection(".dynamic"); + auto shdrDynStr = findSection(".dynstr"); char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); /* Walk through the dynamic section, look for the DT_SONAME entry. */ @@ -1130,11 +1259,11 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath) { - Elf_Shdr & shdrDynamic = findSection(".dynamic"); + auto shdrDynamic = findSection(".dynamic"); /* !!! We assume that the virtual address in the DT_STRTAB entry of the dynamic section corresponds to the .dynstr section. */ - Elf_Shdr & shdrDynStr = findSection(".dynstr"); + auto shdrDynStr = findSection(".dynstr"); char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); @@ -1252,14 +1381,18 @@ if (!forceRPath && dynRPath && !dynRunPath) { /* convert DT_RPATH to DT_RUNPATH */ - dynRPath->d_tag = DT_RUNPATH; + wri(dynRPath->d_tag, DT_RUNPATH); dynRunPath = dynRPath; dynRPath = 0; + changed = true; } else if (forceRPath && dynRunPath) { /* convert DT_RUNPATH to DT_RPATH */ - dynRunPath->d_tag = DT_RPATH; + wri(dynRunPath->d_tag, DT_RPATH); dynRPath = dynRunPath; dynRunPath = 0; - } else if (std::string(rpath ? rpath : "") == newRPath) { + changed = true; + } + + if (std::string(rpath ? rpath : "") == newRPath) { return; } @@ -1322,8 +1455,8 @@ { if (libs.empty()) return; - Elf_Shdr & shdrDynamic = findSection(".dynamic"); - Elf_Shdr & shdrDynStr = findSection(".dynstr"); + auto shdrDynamic = findSection(".dynamic"); + auto shdrDynStr = findSection(".dynstr"); char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); @@ -1350,8 +1483,8 @@ { if (libs.empty()) return; - Elf_Shdr & shdrDynamic = findSection(".dynamic"); - Elf_Shdr & shdrDynStr = findSection(".dynstr"); + auto shdrDynamic = findSection(".dynamic"); + auto shdrDynStr = findSection(".dynstr"); char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); @@ -1396,7 +1529,7 @@ // be replaced. if (verNeedNum) { - Elf_Shdr & shdrVersionR = findSection(".gnu.version_r"); + auto shdrVersionR = findSection(".gnu.version_r"); // The filename strings in the .gnu.version_r are different from the // ones in .dynamic: instead of being in .dynstr, they're in some // arbitrary section and we have to look in ->sh_link to figure out @@ -1446,8 +1579,8 @@ { if (libs.empty()) return; - Elf_Shdr & shdrDynamic = findSection(".dynamic"); - Elf_Shdr & shdrDynStr = findSection(".dynstr"); + auto shdrDynamic = findSection(".dynamic"); + auto shdrDynStr = findSection(".dynstr"); /* add all new libs to the dynstr string table */ unsigned int length = 0; @@ -1489,17 +1622,17 @@ } template<ElfFileParams> -void ElfFile<ElfFileParamNames>::printNeededLibs() +void ElfFile<ElfFileParamNames>::printNeededLibs() // const { - Elf_Shdr & shdrDynamic = findSection(".dynamic"); - Elf_Shdr & shdrDynStr = findSection(".dynstr"); - char *strTab = (char *)contents + rdi(shdrDynStr.sh_offset); + const auto shdrDynamic = findSection(".dynamic"); + const auto shdrDynStr = findSection(".dynstr"); + const char *strTab = (char *)contents + rdi(shdrDynStr.sh_offset); - Elf_Dyn *dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); + const Elf_Dyn *dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); for (; rdi(dyn->d_tag) != DT_NULL; dyn++) { if (rdi(dyn->d_tag) == DT_NEEDED) { - char *name = strTab + rdi(dyn->d_un.d_val); + const char *name = strTab + rdi(dyn->d_un.d_val); printf("%s\n", name); } } @@ -1509,7 +1642,7 @@ template<ElfFileParams> void ElfFile<ElfFileParamNames>::noDefaultLib() { - Elf_Shdr & shdrDynamic = findSection(".dynamic"); + auto shdrDynamic = findSection(".dynamic"); Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); Elf_Dyn * dynFlags1 = 0; @@ -1545,6 +1678,33 @@ changed = true; } +template<ElfFileParams> +void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string> & syms) +{ + if (syms.empty()) return; + + auto shdrDynStr = findSection(".dynstr"); + auto shdrDynsym = findSection(".dynsym"); + auto shdrVersym = findSection(".gnu.version"); + + char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); + Elf_Sym * dynsyms = (Elf_Sym *) (contents + rdi(shdrDynsym.sh_offset)); + Elf_Versym * versyms = (Elf_Versym *) (contents + rdi(shdrVersym.sh_offset)); + size_t count = rdi(shdrDynsym.sh_size) / sizeof(Elf_Sym); + + if (count != rdi(shdrVersym.sh_size) / sizeof(Elf_Versym)) + error("versym size mismatch"); + + for (size_t i = 0; i < count; i++) { + auto dynsym = dynsyms[i]; + auto name = strTab + rdi(dynsym.st_name); + if (syms.find(name) != syms.end()) { + debug("clearing symbol version for %s\n", name); + wri(versyms[i], 1); + } + } + changed = true; +} static bool printInterpreter = false; static bool printSoname = false; @@ -1560,6 +1720,7 @@ static std::set<std::string> neededLibsToRemove; static std::map<std::string, std::string> neededLibsToReplace; static std::set<std::string> neededLibsToAdd; +static std::set<std::string> symbolsToClearVersion; static bool printNeeded = false; static bool noDefaultLib = false; @@ -1593,6 +1754,7 @@ elfFile.removeNeeded(neededLibsToRemove); elfFile.replaceNeeded(neededLibsToReplace); elfFile.addNeeded(neededLibsToAdd); + elfFile.clearSymbolVersions(symbolsToClearVersion); if (noDefaultLib) elfFile.noDefaultLib(); @@ -1613,15 +1775,13 @@ if (!printInterpreter && !printRPath && !printSoname && !printNeeded) debug("patching ELF file '%s'\n", fileName.c_str()); - debug("Kernel page size is %u bytes\n", getPageSize()); - auto fileContents = readFile(fileName); std::string outputFileName2 = outputFileName.empty() ? fileName : outputFileName; if (getElfType(fileContents).is32Bit) - patchElf2(ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed>(fileContents), fileContents, outputFileName2); + patchElf2(ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed, Elf32_Versym>(fileContents), fileContents, outputFileName2); else - patchElf2(ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed>(fileContents), fileContents, outputFileName2); + patchElf2(ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, Elf64_Versym>(fileContents), fileContents, outputFileName2); } } @@ -1645,6 +1805,7 @@ [--replace-needed LIBRARY NEW_LIBRARY]\n\ [--print-needed]\n\ [--no-default-lib]\n\ + [--clear-symbol-version SYMBOL]\n\ [--output FILE]\n\ [--debug]\n\ [--version]\n\ @@ -1670,8 +1831,8 @@ } else if (arg == "--page-size") { if (++i == argc) error("missing argument"); - pageSize = atoi(argv[i]); - if (pageSize <= 0) error("invalid argument to --page-size"); + forcedPageSize = atoi(argv[i]); + if (forcedPageSize <= 0) error("invalid argument to --page-size"); } else if (arg == "--print-interpreter") { printInterpreter = true; @@ -1732,6 +1893,10 @@ neededLibsToReplace[ argv[i+1] ] = argv[i+2]; i += 2; } + else if (arg == "--clear-symbol-version") { + if (++i == argc) error("missing argument"); + symbolsToClearVersion.insert(argv[i]); + } else if (arg == "--output") { if (++i == argc) error("missing argument"); outputFileName = argv[i]; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/tests/Makefile.am new/patchelf-0.12.20200827.8d3a16e/tests/Makefile.am --- old/patchelf-0.11.20200609.d6b2a72/tests/Makefile.am 1970-01-01 01:00:01.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/tests/Makefile.am 1970-01-01 01:00:01.000000000 +0100 @@ -23,7 +23,9 @@ set-interpreter-long.sh set-rpath.sh no-rpath.sh big-dynstr.sh \ set-rpath-library.sh soname.sh shrink-rpath-with-allowed-prefixes.sh \ force-rpath.sh \ - output-flag.sh + plain-needed.sh \ + output-flag.sh \ + build-id.sh build_TESTS = \ $(no_rpath_arch_TESTS) @@ -75,7 +77,10 @@ # - without libtool, only archives (static libraries) can be built by automake # - with libtool, it is difficult to control options # - with libtool, it is not possible to compile convenience *dynamic* libraries :-( -check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so +check_PROGRAMS += libfoo.so libfoo-scoped.so libbar.so libbar-scoped.so libsimple.so libbuildid.so + +libbuildid_so_SOURCES = simple.c +libbuildid_so_LDFLAGS = $(LDFLAGS_sharedlib) -Wl,-build-id libfoo_so_SOURCES = foo.c libfoo_so_LDADD = -lbar $(AM_LDADD) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/tests/build-id.sh new/patchelf-0.12.20200827.8d3a16e/tests/build-id.sh --- old/patchelf-0.11.20200609.d6b2a72/tests/build-id.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/tests/build-id.sh 1970-01-01 01:00:01.000000000 +0100 @@ -0,0 +1,19 @@ +#! /bin/sh -e +SCRATCH=scratch/$(basename $0 .sh) + +if ! command -v readelf >/dev/null; then + echo "No readelf found; skip test" + exit 0 +fi + +rm -rf "${SCRATCH}" +mkdir -p "${SCRATCH}" + +cp libbuildid.so "${SCRATCH}/" + +long_rpath="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + +../src/patchelf \ + --set-rpath "$long_rpath" "${SCRATCH}/libbuildid.so" + +readelf -n "${SCRATCH}/libbuildid.so" | grep -q "Build ID" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/tests/no-rpath-prebuild.sh new/patchelf-0.12.20200827.8d3a16e/tests/no-rpath-prebuild.sh --- old/patchelf-0.11.20200609.d6b2a72/tests/no-rpath-prebuild.sh 1970-01-01 01:00:01.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/tests/no-rpath-prebuild.sh 1970-01-01 01:00:01.000000000 +0100 @@ -4,7 +4,7 @@ PAGESIZE=4096 if [ -z "$ARCH" ]; then - ARCH=$(basename $0 .sh | sed -e 's/.*-//') + ARCH=$(basename $0 .sh | sed -e 's/^no-rpath-//') fi SCRATCH=scratch/no-rpath-$ARCH diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/tests/plain-needed.sh new/patchelf-0.12.20200827.8d3a16e/tests/plain-needed.sh --- old/patchelf-0.11.20200609.d6b2a72/tests/plain-needed.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/patchelf-0.12.20200827.8d3a16e/tests/plain-needed.sh 1970-01-01 01:00:01.000000000 +0100 @@ -0,0 +1,4 @@ +#! /bin/sh +set -e +echo "Confirming main requires libfoo" +../src/patchelf --print-needed main | grep -q libfoo.so diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/patchelf-0.11.20200609.d6b2a72/version new/patchelf-0.12.20200827.8d3a16e/version --- old/patchelf-0.11.20200609.d6b2a72/version 2020-06-09 14:58:15.000000000 +0200 +++ new/patchelf-0.12.20200827.8d3a16e/version 2020-08-27 14:12:55.000000000 +0200 @@ -1 +1 @@ -0.11.20200609.d6b2a72 +0.12.20200827.8d3a16e
