|
@@ -41,6 +41,8 @@ pending.
|
|
|
[2] https://github.com/NixOS/patchelf/pull/118
|
|
|
|
|
|
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
|
|
|
+[Fabrice: update for 0.13]
|
|
|
+Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
|
|
|
---
|
|
|
src/patchelf.cc | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
|
1 file changed, 175 insertions(+), 21 deletions(-)
|
|
@@ -57,14 +59,14 @@ index 1d9a772..35b4a33 100644
|
|
|
+
|
|
|
+static bool relativeToFile = false;
|
|
|
+
|
|
|
- static string fileName;
|
|
|
- static int pageSize = PAGESIZE;
|
|
|
-
|
|
|
+ static std::vector<std::string> fileNames;
|
|
|
+ static std::string outputFileName;
|
|
|
+ static bool alwaysWrite = false;
|
|
|
@@ -77,6 +81,49 @@ static unsigned int getPageSize(){
|
|
|
return pageSize;
|
|
|
}
|
|
|
|
|
|
-+static bool absolutePathExists(const string & path, string & canonicalPath)
|
|
|
++static bool absolutePathExists(const std::string & path, std::string & canonicalPath)
|
|
|
+{
|
|
|
+ char *cpath = realpath(path.c_str(), NULL);
|
|
|
+ if (cpath) {
|
|
@@ -76,11 +78,11 @@ index 1d9a772..35b4a33 100644
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
-+static string makePathRelative(const string & path,
|
|
|
-+ const string & refPath)
|
|
|
++static std::string makePathRelative(const std::string & path,
|
|
|
++ const std::string & refPath)
|
|
|
+{
|
|
|
-+ string relPath = "$ORIGIN";
|
|
|
-+ string p = path, refP = refPath;
|
|
|
++ std::string relPath = "$ORIGIN";
|
|
|
++ std::string p = path, refP = refPath;
|
|
|
+ size_t pos;
|
|
|
+
|
|
|
+ /* Strip the common part of path and refPath */
|
|
@@ -90,7 +92,7 @@ index 1d9a772..35b4a33 100644
|
|
|
+ break;
|
|
|
+ if (p.substr(0, pos) != refP.substr(0, pos))
|
|
|
+ break;
|
|
|
-+ if (pos == string::npos)
|
|
|
++ if (pos == std::string::npos)
|
|
|
+ break;
|
|
|
+ p = p.substr(pos);
|
|
|
+ refP = refP.substr(pos);
|
|
@@ -98,7 +100,7 @@ index 1d9a772..35b4a33 100644
|
|
|
+ /* Check if both pathes are equal */
|
|
|
+ if (p != refP) {
|
|
|
+ pos = 0;
|
|
|
-+ while (pos != string::npos) {
|
|
|
++ while (pos != std::string::npos) {
|
|
|
+ pos =refP.find_first_of('/', pos + 1);
|
|
|
+ relPath.append("/..");
|
|
|
+ }
|
|
@@ -114,32 +116,33 @@ index 1d9a772..35b4a33 100644
|
|
|
|
|
|
void setInterpreter(const string & newInterpreter);
|
|
|
|
|
|
-- typedef enum { rpPrint, rpShrink, rpSet, rpRemove } RPathOp;
|
|
|
-+ typedef enum { rpPrint, rpShrink, rpMakeRelative, rpSet, rpRemove} RPathOp;
|
|
|
+- typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove } RPathOp;
|
|
|
++ typedef enum { rpPrint, rpShrink, rpMakeRelative, rpSet, rpAdd, rpRemove} RPathOp;
|
|
|
+
|
|
|
-+ bool libFoundInRPath(const string & dirName,
|
|
|
-+ const vector<string> neededLibs,
|
|
|
-+ vector<bool> & neededLibFound);
|
|
|
++ bool libFoundInRPath(const std::string & dirName,
|
|
|
++ const std::vector<std::string> neededLibs,
|
|
|
++ std::vector<bool> & neededLibFound);
|
|
|
|
|
|
-- void modifyRPath(RPathOp op, string newRPath);
|
|
|
-+ void modifyRPath(RPathOp op, string rootDir, string newRPath);
|
|
|
+- void modifyRPath(RPathOp op, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath);
|
|
|
++ void modifyRPath(RPathOp op, std::string rootDir, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath, const std::string & fileName);
|
|
|
|
|
|
void addNeeded(set<string> libs);
|
|
|
|
|
|
-@@ -1041,7 +1092,27 @@ static void concatToRPath(string & rpath, const string & path)
|
|
|
+@@ -1041,8 +1092,28 @@ static void concatToRPath(string & rpath, const string & path)
|
|
|
|
|
|
|
|
|
template<ElfFileParams>
|
|
|
--void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string newRPath)
|
|
|
-+bool ElfFile<ElfFileParamNames>::libFoundInRPath(const string & dirName,
|
|
|
-+ const vector<string> neededLibs, vector<bool> & neededLibFound)
|
|
|
+-void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
|
|
|
+- const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath)
|
|
|
++bool ElfFile<ElfFileParamNames>::libFoundInRPath(const std::string & dirName,
|
|
|
++ const std::vector<std::string> neededLibs, std::vector<bool> & neededLibFound)
|
|
|
+{
|
|
|
+ /* For each library that we haven't found yet, see if it
|
|
|
+ exists in this directory. */
|
|
|
+ bool libFound = false;
|
|
|
+ for (unsigned int j = 0; j < neededLibs.size(); ++j)
|
|
|
+ if (!neededLibFound[j]) {
|
|
|
-+ string libName = dirName + "/" + neededLibs[j];
|
|
|
++ std::string libName = dirName + "/" + neededLibs[j];
|
|
|
+ struct stat st;
|
|
|
+ if (stat(libName.c_str(), &st) == 0) {
|
|
|
+ neededLibFound[j] = true;
|
|
@@ -151,7 +154,8 @@ index 1d9a772..35b4a33 100644
|
|
|
+
|
|
|
+
|
|
|
+template<ElfFileParams>
|
|
|
-+void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string rootDir, string newRPath)
|
|
|
++void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, std::string rootDir,
|
|
|
++ const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath, const std::string & fileName)
|
|
|
{
|
|
|
Elf_Shdr & shdrDynamic = findSection(".dynamic");
|
|
|
|
|
@@ -167,7 +171,7 @@ index 1d9a772..35b4a33 100644
|
|
|
if (op == rpShrink && !rpath) {
|
|
|
debug("no RPATH to shrink\n");
|
|
|
return;
|
|
|
-@@ -1120,26 +1196,80 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string newRPath)
|
|
|
+@@ -1120,31 +1196,80 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string newRPath)
|
|
|
continue;
|
|
|
}
|
|
|
|
|
@@ -176,17 +180,22 @@ index 1d9a772..35b4a33 100644
|
|
|
- bool libFound = false;
|
|
|
- for (unsigned int j = 0; j < neededLibs.size(); ++j)
|
|
|
- if (!neededLibFound[j]) {
|
|
|
-- string libName = dirName + "/" + neededLibs[j];
|
|
|
-- struct stat st;
|
|
|
-- if (stat(libName.c_str(), &st) == 0) {
|
|
|
-- neededLibFound[j] = true;
|
|
|
-- libFound = true;
|
|
|
+- std::string libName = dirName + "/" + neededLibs[j];
|
|
|
+- try {
|
|
|
+- Elf32_Half library_e_machine = getElfType(readFile(libName, sizeof(Elf32_Ehdr))).machine;
|
|
|
+- if (rdi(library_e_machine) == rdi(hdr->e_machine)) {
|
|
|
+- neededLibFound[j] = true;
|
|
|
+- libFound = true;
|
|
|
+- } else
|
|
|
+- debug("ignoring library '%s' because its machine type differs\n", libName.c_str());
|
|
|
+- } catch (SysError & e) {
|
|
|
+- if (e.errNo != ENOENT) throw;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!libFound)
|
|
|
+ if (!libFoundInRPath(dirName, neededLibs, neededLibFound))
|
|
|
- debug("removing directory `%s' from RPATH\n", dirName.c_str());
|
|
|
+ debug("removing directory '%s' from RPATH\n", dirName.c_str());
|
|
|
else
|
|
|
concatToRPath(newRPath, dirName);
|
|
|
}
|
|
@@ -194,16 +203,16 @@ index 1d9a772..35b4a33 100644
|
|
|
|
|
|
+ /* Make the the RPATH relative to the specified path */
|
|
|
+ if (op == rpMakeRelative) {
|
|
|
-+ vector<bool> neededLibFound(neededLibs.size(), false);
|
|
|
-+ string fileDir = fileName.substr(0, fileName.find_last_of("/"));
|
|
|
++ std::vector<bool> neededLibFound(neededLibs.size(), false);
|
|
|
++ std::string fileDir = fileName.substr(0, fileName.find_last_of("/"));
|
|
|
+
|
|
|
+ newRPath = "";
|
|
|
+
|
|
|
-+ vector<string> rpathDirs = splitColonDelimitedString(rpath);
|
|
|
-+ for (vector<string>::iterator it = rpathDirs.begin(); it != rpathDirs.end(); ++it) {
|
|
|
-+ const string & dirName = *it;
|
|
|
++ std::vector<std::string> rpathDirs = splitColonDelimitedString(rpath);
|
|
|
++ for (std::vector<std::string>::iterator it = rpathDirs.begin(); it != rpathDirs.end(); ++it) {
|
|
|
++ const std::string & dirName = *it;
|
|
|
+
|
|
|
-+ string canonicalPath;
|
|
|
++ std::string canonicalPath;
|
|
|
+
|
|
|
+ /* Figure out if we should keep or discard the path. There are several
|
|
|
+ cases to be handled:
|
|
@@ -221,7 +230,7 @@ index 1d9a772..35b4a33 100644
|
|
|
+ (can be anywhere: build trees, staging tree, host location,
|
|
|
+ non-existing location, etc.). Just discard such a path. */
|
|
|
+ if (!dirName.compare(0, 7, "$ORIGIN")) {
|
|
|
-+ string path = fileDir + dirName.substr(7);
|
|
|
++ std::string path = fileDir + dirName.substr(7);
|
|
|
+ if (!absolutePathExists(path, canonicalPath)) {
|
|
|
+ debug("removing directory '%s' from RPATH because '%s' doesn't exist\n",
|
|
|
+ dirName.c_str(), path.c_str());
|
|
@@ -233,7 +242,7 @@ index 1d9a772..35b4a33 100644
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
-+ string path = rootDir + dirName;
|
|
|
++ std::string path = rootDir + dirName;
|
|
|
+ if (!absolutePathExists(path, canonicalPath)) {
|
|
|
+ debug("removing directory '%s' from RPATH because it's not in rootdir\n",
|
|
|
+ dirName.c_str());
|
|
@@ -263,40 +272,43 @@ index 1d9a772..35b4a33 100644
|
|
|
if (!rpath) {
|
|
|
debug("no RPATH to delete\n");
|
|
|
@@ -1413,7 +1543,9 @@ static bool shrinkRPath = false;
|
|
|
- static bool removeRPath = false;
|
|
|
static bool setRPath = false;
|
|
|
+ static bool addRPath = false;
|
|
|
static bool printRPath = false;
|
|
|
+static bool makeRPathRelative = false;
|
|
|
- static string newRPath;
|
|
|
-+static string rootDir;
|
|
|
- static set<string> neededLibsToRemove;
|
|
|
- static map<string, string> neededLibsToReplace;
|
|
|
- static set<string> neededLibsToAdd;
|
|
|
-@@ -1438,14 +1570,16 @@ static void patchElf2(ElfFile & elfFile)
|
|
|
+ static std::string newRPath;
|
|
|
++static std::string rootDir;
|
|
|
+ static std::set<std::string> neededLibsToRemove;
|
|
|
+ static std::map<std::string, std::string> neededLibsToReplace;
|
|
|
+ static std::set<std::string> neededLibsToAdd;
|
|
|
+@@ -1438,16 +1570,18 @@ static void patchElf2(ElfFile & elfFile)
|
|
|
elfFile.setInterpreter(newInterpreter);
|
|
|
|
|
|
if (printRPath)
|
|
|
-- elfFile.modifyRPath(elfFile.rpPrint, "");
|
|
|
-+ elfFile.modifyRPath(elfFile.rpPrint, "", "");
|
|
|
+- elfFile.modifyRPath(elfFile.rpPrint, {}, "");
|
|
|
++ elfFile.modifyRPath(elfFile.rpPrint, "", {}, "", fileName);
|
|
|
|
|
|
if (shrinkRPath)
|
|
|
-- elfFile.modifyRPath(elfFile.rpShrink, "");
|
|
|
-+ elfFile.modifyRPath(elfFile.rpShrink, "", "");
|
|
|
+- elfFile.modifyRPath(elfFile.rpShrink, allowedRpathPrefixes, "");
|
|
|
++ elfFile.modifyRPath(elfFile.rpShrink, "", allowedRpathPrefixes, "", fileName);
|
|
|
else if (removeRPath)
|
|
|
-- elfFile.modifyRPath(elfFile.rpRemove, "");
|
|
|
-+ elfFile.modifyRPath(elfFile.rpRemove, "", "");
|
|
|
+- elfFile.modifyRPath(elfFile.rpRemove, {}, "");
|
|
|
++ elfFile.modifyRPath(elfFile.rpRemove, "", {}, "", fileName);
|
|
|
else if (setRPath)
|
|
|
-- elfFile.modifyRPath(elfFile.rpSet, newRPath);
|
|
|
-+ elfFile.modifyRPath(elfFile.rpSet, "", newRPath);
|
|
|
+- elfFile.modifyRPath(elfFile.rpSet, {}, newRPath);
|
|
|
++ elfFile.modifyRPath(elfFile.rpSet, "", {}, newRPath, fileName);
|
|
|
+ else if (addRPath)
|
|
|
+- elfFile.modifyRPath(elfFile.rpAdd, {}, newRPath);
|
|
|
++ elfFile.modifyRPath(elfFile.rpAdd, "", {}, newRPath, fileName);
|
|
|
+ else if (makeRPathRelative)
|
|
|
-+ elfFile.modifyRPath(elfFile.rpMakeRelative, rootDir, "");
|
|
|
++ elfFile.modifyRPath(elfFile.rpMakeRelative, rootDir, {}, "", fileName);
|
|
|
|
|
|
if (printNeeded) elfFile.printNeededLibs();
|
|
|
|
|
|
@@ -1508,6 +1642,9 @@ void showHelp(const string & progName)
|
|
|
- [--set-rpath RPATH]\n\
|
|
|
[--remove-rpath]\n\
|
|
|
[--shrink-rpath]\n\
|
|
|
+ [--allowed-rpath-prefixes PREFIXES]\t\tWith '--shrink-rpath', reject rpath entries not starting with the allowed prefix\n\
|
|
|
+ [--make-rpath-relative ROOTDIR]\n\
|
|
|
+ [--no-standard-lib-dirs]\n\
|
|
|
+ [--relative-to-file]\n\
|