diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-01-16 22:41:19 (GMT) |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-01-16 22:42:21 (GMT) |
commit | 118897f0303fac8e9dc14c3600444ff9abcaa683 (patch) | |
tree | 37b8df543971ca86f35d6ab8de5c2e7ac2a5f4f4 /src/patchelf.cc | |
parent | 8dba0ae9d705d13c47114120660f706357e78cf4 (diff) | |
download | patchelf-118897f0303fac8e9dc14c3600444ff9abcaa683.zip patchelf-118897f0303fac8e9dc14c3600444ff9abcaa683.tar.gz patchelf-118897f0303fac8e9dc14c3600444ff9abcaa683.tar.bz2 |
Add ‘--remove-needed’ option
This allows removing the specified DT_NEEDED entries from the dynamic
section.
Closes #4.
Diffstat (limited to 'src/patchelf.cc')
-rw-r--r-- | src/patchelf.cc | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc index 694b2f8..82a4bf1 100644 --- a/src/patchelf.cc +++ b/src/patchelf.cc @@ -1,5 +1,6 @@ #include <string> #include <vector> +#include <set> #include <map> #include <algorithm> @@ -149,6 +150,8 @@ public: void modifyRPath(RPathOp op, string newRPath); + void removeNeeded(set<string> libs); + private: /* Convert an integer in big or little endian representation (as @@ -924,7 +927,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string newRPath) rpath = strTab + rdi(dyn->d_un.d_val); } else if (rdi(dyn->d_tag) == DT_NEEDED) - neededLibs.push_back(string(strTab + rdi(dyn->d_un.d_val))); + neededLibs.push_back(string(strTab + rdi(dyn->d_un.d_val))); } if (op == rpPrint) { @@ -1048,6 +1051,37 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string newRPath) } +template<ElfFileParams> +void ElfFile<ElfFileParamNames>::removeNeeded(set<string> libs) +{ + if (libs.empty()) return; + + Elf_Shdr & shdrDynamic = findSection(".dynamic"); + Elf_Shdr & shdrDynStr = findSection(".dynstr"); + char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset); + + Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset)); + Elf_Dyn * last = dyn; + for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) { + if (rdi(dyn->d_tag) == DT_NEEDED) { + char * name = strTab + rdi(dyn->d_un.d_val); + if (libs.find(name) != libs.end()) { + debug("removing DT_NEEDED entry `%s'\n", name); + changed = true; + } else { + debug("keeping DT_NEEDED entry `%s'\n", name); + *last++ = *dyn; + } + } else + *last++ = *dyn; + } + + memset(last, 0, sizeof(Elf_Dyn) * (dyn - last)); + + debug("%d", dyn - last); +} + + static bool printInterpreter = false; static string newInterpreter; @@ -1055,6 +1089,7 @@ static bool shrinkRPath = false; static bool setRPath = false; static bool printRPath = false; static string newRPath; +static set<string> neededLibsToRemove; template<class ElfFile> @@ -1062,7 +1097,6 @@ static void patchElf2(ElfFile & elfFile, mode_t fileMode) { elfFile.parse(); - if (printInterpreter) printf("%s\n", elfFile.getInterpreter().c_str()); @@ -1077,6 +1111,7 @@ static void patchElf2(ElfFile & elfFile, mode_t fileMode) else if (setRPath) elfFile.modifyRPath(elfFile.rpSet, newRPath); + elfFile.removeNeeded(neededLibsToRemove); if (elfFile.isChanged()){ elfFile.rewriteSections(); @@ -1128,6 +1163,7 @@ void showHelp(const string & progName) [--shrink-rpath]\n\ [--print-rpath]\n\ [--force-rpath]\n\ + [--remove-needed LIBRARY]\n\ [--debug]\n\ [--version]\n\ FILENAME\n", progName.c_str()); @@ -1178,6 +1214,10 @@ int main(int argc, char * * argv) added. */ forceRPath = true; } + else if (arg == "--remove-needed") { + if (++i == argc) error("missing argument"); + neededLibsToRemove.insert(argv[i]); + } else if (arg == "--debug") { debugMode = true; } |