Skip to content

Commit 5daa357

Browse files
Rodger Combsrcombs
Rodger Combs
authored andcommitted
modifyRPath: when possible, avoid growing the dynamic section
Growing the section can require changing its position, which results in crashes if the code relies on a symbol within it (e.g. _DYNAMIC). Instead, we can usually find an entry that isn't actually required and replace it.
1 parent c3ffe62 commit 5daa357

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

src/patchelf.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
11421142
string. */
11431143
std::vector<std::string> neededLibs;
11441144
Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
1145-
Elf_Dyn * dynRPath = 0, * dynRunPath = 0;
1145+
Elf_Dyn * dynRPath = 0, * dynRunPath = 0, * dynReplaceable = 0;
11461146
char * rpath = 0;
11471147
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
11481148
if (rdi(dyn->d_tag) == DT_RPATH) {
@@ -1157,6 +1157,12 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
11571157
}
11581158
else if (rdi(dyn->d_tag) == DT_NEEDED)
11591159
neededLibs.push_back(std::string(strTab + rdi(dyn->d_un.d_val)));
1160+
/* Try to replace an IGNORE rather than growing and moving the section, if possible */
1161+
else if (rdi(dyn->d_tag) == DT_IGNORE)
1162+
dynReplaceable = dyn;
1163+
/* If we don't find an IGNORE, RELCOUNT/RELACOUNT are redundant and optional, so we can replace those */
1164+
else if (!dynReplaceable && (rdi(dyn->d_tag) == DT_RELCOUNT || rdi(dyn->d_tag) == DT_RELACOUNT))
1165+
dynReplaceable = dyn;
11601166
}
11611167

11621168
if (op == rpPrint) {
@@ -1283,7 +1289,11 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
12831289
if (dynRunPath) dynRunPath->d_un.d_val = shdrDynStr.sh_size;
12841290
if (dynRPath) dynRPath->d_un.d_val = shdrDynStr.sh_size;
12851291
}
1286-
1292+
/* Convert an unused or redundant entry to a DT_RPATH or DT_RUNPATH */
1293+
else if (dynReplaceable) {
1294+
dynReplaceable->d_un.d_val = shdrDynStr.sh_size;
1295+
dynReplaceable->d_tag = forceRPath ? DT_RPATH : DT_RUNPATH;
1296+
}
12871297
else {
12881298
/* There is no DT_RUNPATH entry in the .dynamic section, so we
12891299
have to grow the .dynamic section. */

0 commit comments

Comments
 (0)