summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README11
-rw-r--r--src/patchelf.cc44
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 <e.dolstra@tudelft.nl>.
+Copyright 2004-2013 Eelco Dolstra <eelco.dolstra@logicblox.com>.
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 <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;
}