diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/patchelf.cc | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc index 592799d..965686a 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -46,6 +46,8 @@ static bool debugMode = false; static bool forceRPath = false; static std::vector<std::string> fileNames; +static std::string outputFileName; +static bool alwaysWrite = false; static int pageSize = PAGESIZE; 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) { - 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"); @@ -742,14 +746,13 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary() since DYN executables tend to start at virtual address 0, so rewriteSectionsExecutable() won't work because it doesn't have any virtual address space to grow downwards into. */ - if (isExecutable) { - if (startOffset >= startPage) { - debug("shifting new PT_LOAD segment by %d bytes to work around a Linux kernel bug\n", startOffset - startPage); - } + if (isExecutable && startOffset > startPage) { + debug("shifting new PT_LOAD segment by %d bytes to work around a Linux kernel bug\n", startOffset - startPage); startPage = startOffset; } /* Add a segment that maps the replaced sections into memory. */ + wri(hdr->e_phoff, sizeof(Elf_Ehdr)); phdrs.resize(rdi(hdr->e_phnum) + 1); wri(hdr->e_phnum, rdi(hdr->e_phnum) + 1); Elf_Phdr & phdr = phdrs[rdi(hdr->e_phnum) - 1]; @@ -1248,7 +1251,17 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, } - if (std::string(rpath ? rpath : "") == newRPath) return; + if (!forceRPath && dynRPath && !dynRunPath) { /* convert DT_RPATH to DT_RUNPATH */ + dynRPath->d_tag = DT_RUNPATH; + dynRunPath = dynRPath; + dynRPath = 0; + } else if (forceRPath && dynRunPath) { /* convert DT_RUNPATH to DT_RPATH */ + dynRunPath->d_tag = DT_RPATH; + dynRPath = dynRunPath; + dynRunPath = 0; + } else if (std::string(rpath ? rpath : "") == newRPath) { + return; + } changed = true; @@ -1262,15 +1275,6 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, debug("new rpath is '%s'\n", newRPath.c_str()); - if (!forceRPath && dynRPath && !dynRunPath) { /* convert DT_RPATH to DT_RUNPATH */ - dynRPath->d_tag = DT_RUNPATH; - dynRunPath = dynRPath; - dynRPath = 0; - } - - if (forceRPath && dynRPath && dynRunPath) { /* convert DT_RUNPATH to DT_RPATH */ - dynRunPath->d_tag = DT_IGNORE; - } if (newRPath.size() <= rpathSize) { strcpy(rpath, newRPath.c_str()); @@ -1560,7 +1564,7 @@ static bool printNeeded = false; static bool noDefaultLib = false; template<class ElfFile> -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()); @@ -1596,6 +1600,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); } } @@ -1609,11 +1616,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<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 - 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); } } @@ -1637,9 +1645,10 @@ 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()); + FILENAME...\n", progName.c_str()); } @@ -1723,6 +1732,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; } @@ -1744,6 +1758,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; |