From 118897f0303fac8e9dc14c3600444ff9abcaa683 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 16 Jan 2013 23:41:19 +0100 Subject: =?UTF-8?q?Add=20=E2=80=98--remove-needed=E2=80=99=20option?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows removing the specified DT_NEEDED entries from the dynamic section. Closes #4. --- README | 11 ++++++++++- src/patchelf.cc | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/README b/README index e2ec1e2..fbdbcf5 100644 --- a/README +++ b/README @@ -19,10 +19,17 @@ libraries. In particular, it can do the following: 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". +* Remove declared dependencies on dynamic libraries (DT_NEEDED + entries): + + $ patchelf --remove-needed libfoo.so.1 my-program + + This option can be given multiple times. + AUTHOR -Copyright 2004-2009 Eelco Dolstra . +Copyright 2004-2013 Eelco Dolstra . LICENSE @@ -62,6 +69,8 @@ RELEASE HISTORY * Rewrite section indices in symbol tables. This for instance allows gdb to show proper backtraces. +* Added `--remove-needed' option. + 0.6 (November 7, 2011): * Hacky support for executables created by the Gold linker. 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 #include +#include #include #include @@ -149,6 +150,8 @@ public: void modifyRPath(RPathOp op, string newRPath); + void removeNeeded(set libs); + private: /* Convert an integer in big or little endian representation (as @@ -924,7 +927,7 @@ void ElfFile::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::modifyRPath(RPathOp op, string newRPath) } +template +void ElfFile::removeNeeded(set 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 neededLibsToRemove; template @@ -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; } -- cgit v0.12