Added --output flag

This commit is contained in:
Dan L. Stahlke
2020-05-29 15:35:56 -07:00
parent a4676c66ce
commit 71ed440127
4 changed files with 64 additions and 5 deletions

View File

@@ -83,6 +83,9 @@ option can be given multiple times.
Marks the object that the search for dependencies of this object will ignore any Marks the object that the search for dependencies of this object will ignore any
default library search paths. default library search paths.
.IP "--output FILE"
Set the output file name. If not specified, the input will be modified in place.
.IP --debug .IP --debug
Prints details of the changes made to the input file. Prints details of the changes made to the input file.

View File

@@ -46,6 +46,8 @@ static bool debugMode = false;
static bool forceRPath = false; static bool forceRPath = false;
static std::vector<std::string> fileNames; static std::vector<std::string> fileNames;
static std::string outputFileName;
static bool alwaysWrite = false;
static int pageSize = PAGESIZE; static int pageSize = PAGESIZE;
typedef std::shared_ptr<std::vector<unsigned char>> FileContents; typedef std::shared_ptr<std::vector<unsigned char>> FileContents;
@@ -497,7 +499,9 @@ void ElfFile<ElfFileParamNames>::sortShdrs()
static void writeFile(std::string fileName, FileContents contents) 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) if (fd == -1)
error("open"); error("open");
@@ -1567,7 +1571,7 @@ static bool printNeeded = false;
static bool noDefaultLib = false; static bool noDefaultLib = false;
template<class ElfFile> template<class ElfFile>
static void patchElf2(ElfFile && elfFile, std::string fileName) static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, std::string fileName)
{ {
if (printInterpreter) if (printInterpreter)
printf("%s\n", elfFile.getInterpreter().c_str()); printf("%s\n", elfFile.getInterpreter().c_str());
@@ -1603,6 +1607,9 @@ static void patchElf2(ElfFile && elfFile, std::string fileName)
if (elfFile.isChanged()){ if (elfFile.isChanged()){
elfFile.rewriteSections(); elfFile.rewriteSections();
writeFile(fileName, elfFile.fileContents); 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()); debug("Kernel page size is %u bytes\n", getPageSize());
auto fileContents = readFile(fileName); auto fileContents = readFile(fileName);
std::string outputFileName2 = outputFileName.empty() ? fileName : outputFileName;
if (getElfType(fileContents).is32Bit) if (getElfType(fileContents).is32Bit)
patchElf2(ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed>(fileContents), fileName); patchElf2(ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed>(fileContents), fileContents, outputFileName2);
else else
patchElf2(ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed>(fileContents), fileName); patchElf2(ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed>(fileContents), fileContents, outputFileName2);
} }
} }
@@ -1644,6 +1652,7 @@ void showHelp(const std::string & progName)
[--replace-needed LIBRARY NEW_LIBRARY]\n\ [--replace-needed LIBRARY NEW_LIBRARY]\n\
[--print-needed]\n\ [--print-needed]\n\
[--no-default-lib]\n\ [--no-default-lib]\n\
[--output FILE]\n\
[--debug]\n\ [--debug]\n\
[--version]\n\ [--version]\n\
FILENAME...\n", progName.c_str()); FILENAME...\n", progName.c_str());
@@ -1730,6 +1739,11 @@ int mainWrapped(int argc, char * * argv)
neededLibsToReplace[ argv[i+1] ] = argv[i+2]; neededLibsToReplace[ argv[i+1] ] = argv[i+2];
i += 2; i += 2;
} }
else if (arg == "--output") {
if (++i == argc) error("missing argument");
outputFileName = argv[i];
alwaysWrite = true;
}
else if (arg == "--debug") { else if (arg == "--debug") {
debugMode = true; debugMode = true;
} }
@@ -1751,6 +1765,9 @@ int mainWrapped(int argc, char * * argv)
if (fileNames.empty()) error("missing filename"); if (fileNames.empty()) error("missing filename");
if (!outputFileName.empty() && fileNames.size() != 1)
error("--output option only allowed with single input file");
patchElf(); patchElf();
return 0; return 0;

View File

@@ -21,7 +21,8 @@ no_rpath_arch_TESTS = \
src_TESTS = \ src_TESTS = \
plain-fail.sh plain-run.sh shrink-rpath.sh set-interpreter-short.sh \ 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-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 = \ build_TESTS = \
$(no_rpath_arch_TESTS) $(no_rpath_arch_TESTS)

38
tests/output-flag.sh Executable file
View File

@@ -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