kumquat-buildroot/package/patchelf/0001-Add-option-to-make-the-rpath-relative-under-a-specif.patch
Fabrice Fontaine 257881e6e9 package/patchelf: bump to version 0.13
Update third patch (and renumber it) and drop other ones as they are
upstream:

* 0001-Remove-apparently-incorrect-usage-of-static.patch
  a365bcb7d7025da51b33165ef7ebc7180199a05e

* 0002-Extract-a-function-for-splitting-a-colon-separated-s.patch
  2e3fdc2030c75c19df6fc2924083cfad53856562

* 0004-patchelf-Check-ELF-endianness-before-writing-new-run.patch
  e88d83c8b4e42a3358a90b781a5a98efa279ff15

* 0005-Avoid-inflating-file-sizes-needlessly-and-allow-bina.patch
  c4deb5e9e1ce9c98a48e0d5bb37d87739b8cfee4

* 0006-Fix-shared-library-corruption-when-rerunning-patchel.patch
  ad5f1f078b716802dfb8f7226cb1d5c720348a78

* 0007-fix-adjusting-startPage.patch
  1cc234fea5600190d872329aca60e2365cefc39e

* 0008-Use-sh_offset-instead-of-sh_addr-when-checking-alrea.patch
  83aa89addf8757e2d63aa73222f2fa9bc6d7321a

* 0009-Fix-issue-66-by-ignoring-the-first-section-header-wh.patch
  52ab908394958a2a5d0476e306e2cad4da4fdeae

* 0010-Fix-endianness-issues-for-powerpc-PIE.patch
  884eccc4f061a3dbdbe63a4c73f1cc9bbf77fa7d

Update indentation in hash file (two spaces)

Fixes:
 - https://bugs.buildroot.org/show_bug.cgi?id=14191

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
2022-07-25 10:27:36 +02:00

339 lines
13 KiB
Diff

From 618220bfb55c875d6a4d197cb24fe632ac93ec85 Mon Sep 17 00:00:00 2001
From: Wolfgang Grandegger <wg@grandegger.com>
Date: Mon, 20 Feb 2017 16:29:24 +0100
Subject: [PATCH] Add option to make the rpath relative under a specified root
directory
Running "patchelf" with the option "--make-rpath-relative ROOTDIR" will
modify or delete the RPATHDIRs according the following rules
similar to Martin's patches [1] making the Buildroot toolchaing/SDK
relocatable.
RPATHDIR starts with "$ORIGIN":
The original build-system already took care of setting a relative
RPATH, resolve it and test if it's valid (does exist)
RPATHDIR starts with ROOTDIR:
The original build-system added some absolute RPATH (absolute on
the build machine). Test if it's valid (does exist).
ROOTDIR/RPATHDIR exists:
The original build-system already took care of setting an absolute
RPATH (absolute in the final rootfs), resolve it and test if it's
valid (does exist).
RPATHDIR points somewhere else:
(can be anywhere: build trees, staging tree, host location,
non-existing location, etc.). Just discard such a path.
The option "--no-standard-libs" will discard RPATHDIRs ROOTDIR/lib and
ROOTDIR/usr/lib. Like "--shrink-rpath", RPATHDIRs are also discarded
if the directories do not contain a library referenced by the
DT_NEEDED fields.
If the option "--relative-to-file" is given, the rpath will start
with "$ORIGIN" making it relative to the ELF file, otherwise an
absolute path relative to ROOTDIR will be used.
A pull request for a similar patch [2] for mainline inclusion is
pending.
[1] http://lists.busybox.net/pipermail/buildroot/2016-April/159422.html
[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(-)
diff --git a/src/patchelf.cc b/src/patchelf.cc
index 1d9a772..35b4a33 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -46,6 +46,10 @@ static bool debugMode = false;
static bool forceRPath = false;
+static bool noStandardLibDirs = false;
+
+static bool relativeToFile = false;
+
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 std::string & path, std::string & canonicalPath)
+{
+ char *cpath = realpath(path.c_str(), NULL);
+ if (cpath) {
+ canonicalPath = cpath;
+ free(cpath);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static std::string makePathRelative(const std::string & path,
+ const std::string & refPath)
+{
+ std::string relPath = "$ORIGIN";
+ std::string p = path, refP = refPath;
+ size_t pos;
+
+ /* Strip the common part of path and refPath */
+ while (true) {
+ pos = p.find_first_of('/', 1);
+ if (refP.find_first_of('/', 1) != pos)
+ break;
+ if (p.substr(0, pos) != refP.substr(0, pos))
+ break;
+ if (pos == std::string::npos)
+ break;
+ p = p.substr(pos);
+ refP = refP.substr(pos);
+ }
+ /* Check if both pathes are equal */
+ if (p != refP) {
+ pos = 0;
+ while (pos != std::string::npos) {
+ pos =refP.find_first_of('/', pos + 1);
+ relPath.append("/..");
+ }
+ relPath.append(p);
+ }
+
+ return relPath;
+}
template<ElfFileParams>
class ElfFile
@@ -183,9 +230,13 @@ public:
void setInterpreter(const string & newInterpreter);
- typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove } RPathOp;
+ typedef enum { rpPrint, rpShrink, rpMakeRelative, rpSet, rpAdd, rpRemove} RPathOp;
+
+ bool libFoundInRPath(const std::string & dirName,
+ const std::vector<std::string> neededLibs,
+ std::vector<bool> & neededLibFound);
- 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,8 +1092,28 @@ static void concatToRPath(string & rpath, const string & path)
template<ElfFileParams>
-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]) {
+ std::string libName = dirName + "/" + neededLibs[j];
+ struct stat st;
+ if (stat(libName.c_str(), &st) == 0) {
+ neededLibFound[j] = true;
+ libFound = true;
+ }
+ }
+ return libFound;
+}
+
+
+template<ElfFileParams>
+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");
@@ -1096,6 +1167,11 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string newRPath)
return;
}
+ if (op == rpMakeRelative && !rpath) {
+ debug("no RPATH to make relative\n");
+ return;
+ }
+
if (op == rpShrink && !rpath) {
debug("no RPATH to shrink\n");
return;
@@ -1120,31 +1196,80 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op, string newRPath)
continue;
}
- /* 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]) {
- 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());
else
concatToRPath(newRPath, dirName);
}
}
+ /* Make the the RPATH relative to the specified path */
+ if (op == rpMakeRelative) {
+ std::vector<bool> neededLibFound(neededLibs.size(), false);
+ std::string fileDir = fileName.substr(0, fileName.find_last_of("/"));
+
+ newRPath = "";
+
+ 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;
+
+ std::string canonicalPath;
+
+ /* Figure out if we should keep or discard the path. There are several
+ cases to be handled:
+ "dirName" starts with "$ORIGIN":
+ The original build-system already took care of setting a relative
+ RPATH. Resolve it and test if it's valid (does exist).
+ "dirName" start with "rootDir":
+ The original build-system added some absolute RPATH (absolute on
+ the build machine). Test if it's valid (does exist).
+ "rootDir"/"dirName" exists:
+ The original build-system already took care of setting an absolute
+ RPATH (absolute in the final rootfs). Resolve it and test if it's
+ valid (does exist).
+ "dirName" points somewhere else:
+ (can be anywhere: build trees, staging tree, host location,
+ non-existing location, etc.). Just discard such a path. */
+ if (!dirName.compare(0, 7, "$ORIGIN")) {
+ 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());
+ continue;
+ }
+ } else if (!dirName.compare(0, rootDir.length(), rootDir)) {
+ if (!absolutePathExists(dirName, canonicalPath)) {
+ debug("removing directory '%s' from RPATH because it doesn't exist\n", dirName.c_str());
+ continue;
+ }
+ } else {
+ 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());
+ continue;
+ }
+ }
+
+ if (noStandardLibDirs) {
+ if (!canonicalPath.compare(rootDir + "/lib") ||
+ !canonicalPath.compare(rootDir + "/usr/lib")) {
+ debug("removing directory '%s' from RPATH because it's a standard library directory\n",
+ dirName.c_str());
+ continue;
+ }
+ }
+
+ /* Finally make "canonicalPath" relative to "filedir" in "rootDir" */
+ if (relativeToFile)
+ concatToRPath(newRPath, makePathRelative(canonicalPath, fileDir));
+ else
+ concatToRPath(newRPath, canonicalPath.substr(rootDir.length()));
+ debug("keeping relative path of %s\n", canonicalPath.c_str());
+ }
+ }
+
if (op == rpRemove) {
if (!rpath) {
debug("no RPATH to delete\n");
@@ -1413,7 +1543,9 @@ static bool shrinkRPath = false;
static bool setRPath = false;
static bool addRPath = false;
static bool printRPath = false;
+static bool makeRPathRelative = false;
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, "", {}, "", fileName);
if (shrinkRPath)
- elfFile.modifyRPath(elfFile.rpShrink, allowedRpathPrefixes, "");
+ elfFile.modifyRPath(elfFile.rpShrink, "", allowedRpathPrefixes, "", fileName);
else if (removeRPath)
- elfFile.modifyRPath(elfFile.rpRemove, {}, "");
+ elfFile.modifyRPath(elfFile.rpRemove, "", {}, "", fileName);
else if (setRPath)
- 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, {}, "", fileName);
if (printNeeded) elfFile.printNeededLibs();
@@ -1508,6 +1642,9 @@ void showHelp(const string & progName)
[--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\
[--print-rpath]\n\
[--force-rpath]\n\
[--add-needed LIBRARY]\n\
@@ -1564,6 +1701,17 @@ int main(int argc, char * * argv)
setRPath = true;
newRPath = argv[i];
}
+ else if (arg == "--make-rpath-relative") {
+ if (++i == argc) error("missing argument to --make-rpath-relative");
+ makeRPathRelative = true;
+ rootDir = argv[i];
+ }
+ else if (arg == "--no-standard-lib-dirs") {
+ noStandardLibDirs = true;
+ }
+ else if (arg == "--relative-to-file") {
+ relativeToFile = true;
+ }
else if (arg == "--print-rpath") {
printRPath = true;
}
--
1.9.1