mirror of
https://github.com/NixOS/patchelf.git
synced 2025-10-19 19:53:19 +08:00
Merge pull request #311 from NixOS/refactoring
make modify rpath function smaller
This commit is contained in:
178
src/patchelf.cc
178
src/patchelf.cc
@@ -203,6 +203,8 @@ public:
|
|||||||
typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove } RPathOp;
|
typedef enum { rpPrint, rpShrink, rpSet, rpAdd, rpRemove } RPathOp;
|
||||||
|
|
||||||
void modifyRPath(RPathOp op, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath);
|
void modifyRPath(RPathOp op, const std::vector<std::string> & allowedRpathPrefixes, std::string newRPath);
|
||||||
|
std::string shrinkRPath(char* rpath, std::vector<std::string> &neededLibs, const std::vector<std::string> & allowedRpathPrefixes);
|
||||||
|
void removeRPath(Elf_Shdr & shdrDynamic);
|
||||||
|
|
||||||
void addNeeded(const std::set<std::string> & libs);
|
void addNeeded(const std::set<std::string> & libs);
|
||||||
|
|
||||||
@@ -1317,12 +1319,80 @@ void ElfFile<ElfFileParamNames>::setInterpreter(const std::string & newInterpret
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void concatToRPath(std::string & rpath, const std::string & path)
|
static void appendRPath(std::string & rpath, const std::string & path)
|
||||||
{
|
{
|
||||||
if (!rpath.empty()) rpath += ":";
|
if (!rpath.empty()) rpath += ":";
|
||||||
rpath += path;
|
rpath += path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For each directory in the RPATH, check if it contains any
|
||||||
|
needed library. */
|
||||||
|
template<ElfFileParams>
|
||||||
|
std::string ElfFile<ElfFileParamNames>::shrinkRPath(char* rpath, std::vector<std::string> &neededLibs, const std::vector<std::string> & allowedRpathPrefixes) {
|
||||||
|
std::vector<bool> neededLibFound(neededLibs.size(), false);
|
||||||
|
|
||||||
|
std::string newRPath = "";
|
||||||
|
|
||||||
|
for (auto & dirName : splitColonDelimitedString(rpath)) {
|
||||||
|
|
||||||
|
/* Non-absolute entries are allowed (e.g., the special
|
||||||
|
"$ORIGIN" hack). */
|
||||||
|
if (dirName[0] != '/') {
|
||||||
|
appendRPath(newRPath, dirName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If --allowed-rpath-prefixes was given, reject directories
|
||||||
|
not starting with any of the (colon-delimited) prefixes. */
|
||||||
|
if (!allowedRpathPrefixes.empty() && !hasAllowedPrefix(dirName, allowedRpathPrefixes)) {
|
||||||
|
debug("removing directory '%s' from RPATH because of non-allowed prefix\n", dirName.c_str());
|
||||||
|
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)
|
||||||
|
debug("removing directory '%s' from RPATH\n", dirName.c_str());
|
||||||
|
else
|
||||||
|
appendRPath(newRPath, dirName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<ElfFileParams>
|
||||||
|
void ElfFile<ElfFileParamNames>::removeRPath(Elf_Shdr & shdrDynamic) {
|
||||||
|
auto 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_RPATH) {
|
||||||
|
debug("removing DT_RPATH entry\n");
|
||||||
|
changed = true;
|
||||||
|
} else if (rdi(dyn->d_tag) == DT_RUNPATH) {
|
||||||
|
debug("removing DT_RUNPATH entry\n");
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
*last++ = *dyn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(last, 0, sizeof(Elf_Dyn) * (dyn - last));
|
||||||
|
}
|
||||||
|
|
||||||
template<ElfFileParams>
|
template<ElfFileParams>
|
||||||
void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
|
void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
|
||||||
@@ -1372,89 +1442,36 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
|
|||||||
neededLibs.push_back(std::string(strTab + rdi(dyn->d_un.d_val)));
|
neededLibs.push_back(std::string(strTab + rdi(dyn->d_un.d_val)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == rpPrint) {
|
switch (op) {
|
||||||
printf("%s\n", rpath ? rpath : "");
|
case rpPrint: {
|
||||||
return;
|
printf("%s\n", rpath ? rpath : "");
|
||||||
}
|
return;
|
||||||
|
};
|
||||||
if (op == rpShrink && !rpath) {
|
case rpRemove: {
|
||||||
debug("no RPATH to shrink\n");
|
if (!rpath) {
|
||||||
return;
|
debug("no RPATH to delete\n");
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
|
||||||
/* For each directory in the RPATH, check if it contains any
|
|
||||||
needed library. */
|
|
||||||
if (op == rpShrink) {
|
|
||||||
std::vector<bool> neededLibFound(neededLibs.size(), false);
|
|
||||||
|
|
||||||
newRPath = "";
|
|
||||||
|
|
||||||
for (auto & dirName : splitColonDelimitedString(rpath)) {
|
|
||||||
|
|
||||||
/* Non-absolute entries are allowed (e.g., the special
|
|
||||||
"$ORIGIN" hack). */
|
|
||||||
if (dirName[0] != '/') {
|
|
||||||
concatToRPath(newRPath, dirName);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
removeRPath(shdrDynamic);
|
||||||
/* If --allowed-rpath-prefixes was given, reject directories
|
|
||||||
not starting with any of the (colon-delimited) prefixes. */
|
|
||||||
if (!allowedRpathPrefixes.empty() && !hasAllowedPrefix(dirName, allowedRpathPrefixes)) {
|
|
||||||
debug("removing directory '%s' from RPATH because of non-allowed prefix\n", dirName.c_str());
|
|
||||||
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)
|
|
||||||
debug("removing directory '%s' from RPATH\n", dirName.c_str());
|
|
||||||
else
|
|
||||||
concatToRPath(newRPath, dirName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (op == rpRemove) {
|
|
||||||
if (!rpath) {
|
|
||||||
debug("no RPATH to delete\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case rpShrink: {
|
||||||
dyn = (Elf_Dyn *)(contents + rdi(shdrDynamic.sh_offset));
|
if (!rpath) {
|
||||||
Elf_Dyn * last = dyn;
|
debug("no RPATH to shrink\n");
|
||||||
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
|
return;
|
||||||
if (rdi(dyn->d_tag) == DT_RPATH) {
|
;}
|
||||||
debug("removing DT_RPATH entry\n");
|
newRPath = shrinkRPath(rpath, neededLibs, allowedRpathPrefixes);
|
||||||
changed = true;
|
break;
|
||||||
} else if (rdi(dyn->d_tag) == DT_RUNPATH) {
|
|
||||||
debug("removing DT_RUNPATH entry\n");
|
|
||||||
changed = true;
|
|
||||||
} else {
|
|
||||||
*last++ = *dyn;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
memset(last, 0, sizeof(Elf_Dyn) * (dyn - last));
|
case rpAdd: {
|
||||||
return;
|
auto temp = std::string(rpath ? rpath : "");
|
||||||
|
appendRPath(temp, newRPath);
|
||||||
|
newRPath = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rpSet: { break; } /* new rpath was provied as input to this function */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!forceRPath && dynRPath && !dynRunPath) { /* convert DT_RPATH to DT_RUNPATH */
|
if (!forceRPath && dynRPath && !dynRunPath) { /* convert DT_RPATH to DT_RUNPATH */
|
||||||
wri(dynRPath->d_tag, DT_RUNPATH);
|
wri(dynRPath->d_tag, DT_RUNPATH);
|
||||||
dynRunPath = dynRPath;
|
dynRunPath = dynRPath;
|
||||||
@@ -1470,11 +1487,6 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
|
|||||||
if (rpath && rpath == newRPath) {
|
if (rpath && rpath == newRPath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == rpAdd) {
|
|
||||||
newRPath = std::string(rpath ? rpath : "") + ":" + newRPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
/* Zero out the previous rpath to prevent retained dependencies in
|
/* Zero out the previous rpath to prevent retained dependencies in
|
||||||
|
Reference in New Issue
Block a user