blob: 31db58b2d0040ae6045150ac9dae71d9c49c680a (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
diff --git a/src/patchelf.cc b/src/patchelf.cc
index ea6c6c0..d2d7d3b 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -1344,6 +1344,8 @@ void ElfFile<ElfFileParamNames>::removeNeeded(const std::set<std::string> & libs
auto shdrDynStr = findSection(".dynstr");
char * strTab = (char *) contents + rdi(shdrDynStr.sh_offset);
+ unsigned int verNeedNum = 0;
+
Elf_Dyn * dyn = (Elf_Dyn *) (contents + rdi(shdrDynamic.sh_offset));
Elf_Dyn * last = dyn;
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
@@ -1358,9 +1360,39 @@ void ElfFile<ElfFileParamNames>::removeNeeded(const std::set<std::string> & libs
}
} else
*last++ = *dyn;
+
+ if (rdi(dyn->d_tag) == DT_VERNEEDNUM)
+ verNeedNum = rdi(dyn->d_un.d_val);
}
memset(last, 0, sizeof(Elf_Dyn) * (dyn - last));
+
+ if (verNeedNum) {
+ auto shdrVersionR = findSection(".gnu.version_r");
+ Elf_Shdr & shdrVersionRStrings = shdrs[rdi(shdrVersionR.sh_link)];
+ char * verStrTab = (char *) contents + rdi(shdrVersionRStrings.sh_offset);
+ std::string versionRStringsSName = getSectionName(shdrVersionRStrings);
+
+ debug("found .gnu.version_r with %i entries, strings in %s\n", verNeedNum, versionRStringsSName.c_str());
+
+ Elf_Verneed * need = (Elf_Verneed *) (contents + rdi(shdrVersionR.sh_offset));
+ Elf_Verneed * last = need;
+
+ while (verNeedNum > 0) {
+ char * file = verStrTab + rdi(need->vn_file);
+
+ if (libs.find(file) != libs.end()) {
+ debug("removing .gnu.version_r entry for '%s'\n", file);
+ // Relative offset, so all we need to do here is punch a hole.
+ last->vn_next += need->vn_next;
+ changed = true;
+ }
+
+ last = need;
+ need = (Elf_Verneed *) (((char *) need) + rdi(need->vn_next));
+ --verNeedNum;
+ }
+ }
}
template<ElfFileParams>
|