From 71ed4401273f56bde1ad9f09ba74b5bd6892b889 Mon Sep 17 00:00:00 2001 From: "Dan L. Stahlke" Date: Fri, 29 May 2020 15:35:56 -0700 Subject: Added --output flag --- patchelf.1 | 3 +++ src/patchelf.cc | 25 +++++++++++++++++++++---- tests/Makefile.am | 3 ++- tests/output-flag.sh | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100755 tests/output-flag.sh diff --git a/patchelf.1 b/patchelf.1 index a51f726..8c998ad 100644 --- a/patchelf.1 +++ b/patchelf.1 @@ -83,6 +83,9 @@ option can be given multiple times. Marks the object that the search for dependencies of this object will ignore any default library search paths. +.IP "--output FILE" +Set the output file name. If not specified, the input will be modified in place. + .IP --debug Prints details of the changes made to the input file. diff --git a/src/patchelf.cc b/src/patchelf.cc index f7643d0..d560587 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -46,6 +46,8 @@ static bool debugMode = false; static bool forceRPath = false; static std::vector fileNames; +static std::string outputFileName; +static bool alwaysWrite = false; static int pageSize = PAGESIZE; typedef std::shared_ptr> FileContents; @@ -497,7 +499,9 @@ void ElfFile::sortShdrs() static void writeFile(std::string fileName, FileContents contents) { - int fd = open(fileName.c_str(), O_TRUNC | O_WRONLY); + debug("writing %s\n", fileName.c_str()); + + int fd = open(fileName.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0777); if (fd == -1) error("open"); @@ -1567,7 +1571,7 @@ static bool printNeeded = false; static bool noDefaultLib = false; template -static void patchElf2(ElfFile && elfFile, std::string fileName) +static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, std::string fileName) { if (printInterpreter) printf("%s\n", elfFile.getInterpreter().c_str()); @@ -1603,6 +1607,9 @@ static void patchElf2(ElfFile && elfFile, std::string fileName) if (elfFile.isChanged()){ elfFile.rewriteSections(); writeFile(fileName, elfFile.fileContents); + } else if (alwaysWrite) { + debug("not modified, but alwaysWrite=true\n"); + writeFile(fileName, fileContents); } } @@ -1616,11 +1623,12 @@ static void patchElf() 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(fileContents), fileName); + patchElf2(ElfFile(fileContents), fileContents, outputFileName2); else - patchElf2(ElfFile(fileContents), fileName); + patchElf2(ElfFile(fileContents), fileContents, outputFileName2); } } @@ -1644,6 +1652,7 @@ void showHelp(const std::string & progName) [--replace-needed LIBRARY NEW_LIBRARY]\n\ [--print-needed]\n\ [--no-default-lib]\n\ + [--output FILE]\n\ [--debug]\n\ [--version]\n\ FILENAME...\n", progName.c_str()); @@ -1730,6 +1739,11 @@ int mainWrapped(int argc, char * * argv) neededLibsToReplace[ argv[i+1] ] = argv[i+2]; i += 2; } + else if (arg == "--output") { + if (++i == argc) error("missing argument"); + outputFileName = argv[i]; + alwaysWrite = true; + } else if (arg == "--debug") { debugMode = true; } @@ -1751,6 +1765,9 @@ int mainWrapped(int argc, char * * argv) if (fileNames.empty()) error("missing filename"); + if (!outputFileName.empty() && fileNames.size() != 1) + error("--output option only allowed with single input file"); + patchElf(); return 0; diff --git a/tests/Makefile.am b/tests/Makefile.am index 32218e8..8ad7f20 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,7 +21,8 @@ no_rpath_arch_TESTS = \ src_TESTS = \ plain-fail.sh plain-run.sh shrink-rpath.sh set-interpreter-short.sh \ 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 + set-rpath-library.sh soname.sh shrink-rpath-with-allowed-prefixes.sh \ + output-flag.sh build_TESTS = \ $(no_rpath_arch_TESTS) diff --git a/tests/output-flag.sh b/tests/output-flag.sh new file mode 100755 index 0000000..5da26b5 --- /dev/null +++ b/tests/output-flag.sh @@ -0,0 +1,38 @@ +#! /bin/sh -e +SCRATCH=scratch/$(basename $0 .sh) + +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/ + +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 +# 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 + +if test "$(uname)" = FreeBSD; then + export LD_LIBRARY_PATH=$(pwd)/${SCRATCH}/libsB +fi + +exitCode=0 +(cd ${SCRATCH} && ./main2) || exitCode=$? + +if test "$exitCode" != 46; then + echo "bad exit code!" + exit 1 +fi + +exitCode=0 +(cd ${SCRATCH} && ./main3) || exitCode=$? + +if test "$exitCode" != 46; then + echo "bad exit code!" + exit 1 +fi -- cgit v0.12