Skip to content

Commit f0a4868

Browse files
committed
fix: make section as null when remobing entire section, use rewriteHeaders rather than rewriteSection
1 parent 7e07d97 commit f0a4868

File tree

1 file changed

+53
-9
lines changed

1 file changed

+53
-9
lines changed

src/patchelf.cc

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2228,7 +2228,7 @@ void ElfFile<ElfFileParamNames>::removeNeededVersion(const std::map<std::string,
22282228
auto & shdrVersionR = shdrs.at(idxVersionR);
22292229
Elf_Shdr & shdrVersionRStrings = shdrs.at(rdi(shdrVersionR.sh_link));
22302230

2231-
auto spanVersyms = tryGetSectionSpan<Elf_Versym>(".gnu.version");
2231+
auto mapOffset = rdi(shdrVersionR.sh_addr) - rdi(shdrVersionR.sh_offset);
22322232

22332233
size_t verNeedNum = rdi(shdrVersionR.sh_info);
22342234
std::set<size_t> removedVersionIds;
@@ -2238,6 +2238,8 @@ void ElfFile<ElfFileParamNames>::removeNeededVersion(const std::map<std::string,
22382238

22392239
debug("found .gnu.version_r with %i entries\n", verNeedNum);
22402240

2241+
bool removeEntireSection = false;
2242+
22412243
auto vn = (Elf_Verneed *)(fileContents->data() + rdi(shdrVersionR.sh_offset));
22422244
Elf_Verneed * prevVn = nullptr;
22432245
for (size_t i = 0; i < verNeedNum; ++i) {
@@ -2296,9 +2298,9 @@ void ElfFile<ElfFileParamNames>::removeNeededVersion(const std::map<std::string,
22962298
if (next) {
22972299
wri(shdrVersionR.sh_offset, rdi(shdrVersionR.sh_offset) + next);
22982300
} else {
2299-
// FIXME: remove entire section?
2300-
wri(shdrVersionR.sh_offset, 0);
23012301
wri(shdrVersionR.sh_size, 0);
2302+
2303+
removeEntireSection = true;
23022304
}
23032305
}
23042306
wri(shdrVersionR.sh_info, rdi(shdrVersionR.sh_info) - 1);
@@ -2313,20 +2315,40 @@ void ElfFile<ElfFileParamNames>::removeNeededVersion(const std::map<std::string,
23132315
vn = follow<Elf_Verneed>(vn, next);
23142316
}
23152317
}
2316-
// virtual address and file offset need to be the same for .gnu.version_r
2317-
shdrVersionR.sh_addr = shdrVersionR.sh_offset;
2318+
2319+
// virtual address and file offset need to be the same
2320+
if (!removeEntireSection) {
2321+
wri(shdrVersionR.sh_addr, mapOffset + rdi(shdrVersionR.sh_offset));
2322+
}
23182323

23192324
if (auto shdrDynamic = tryFindSectionHeader(".dynamic")) {
23202325
auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic->get().sh_offset));
23212326

2322-
// keep DT_VERNEED and DT_VERNEEDNUM in sync, DT_VERNEEDNUM handled by rewriteHeaders
2327+
// keep DT_VERNEED and DT_VERNEEDNUM in sync, DT_VERNEED handled by rewriteHeaders
2328+
Elf_Dyn * last = dyn;
23232329
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
23242330
if (rdi(dyn->d_tag) == DT_VERNEEDNUM) {
2325-
dyn->d_un.d_val = shdrVersionR.sh_info;
2331+
if (!removeEntireSection) {
2332+
dyn->d_un.d_val = shdrVersionR.sh_info;
2333+
*last++ = *dyn;
2334+
}
2335+
} else if (rdi(dyn->d_tag) == DT_VERNEED) {
2336+
if (!removeEntireSection) {
2337+
*last++ = *dyn;
2338+
}
2339+
} else if (rdi(dyn->d_tag) == DT_VERSYM) {
2340+
if (!removeEntireSection) {
2341+
*last++ = *dyn;
2342+
}
2343+
} else {
2344+
*last++ = *dyn;
23262345
}
23272346
}
2347+
memset(last, 0, sizeof(Elf_Dyn) * (dyn - last));
23282348
}
23292349

2350+
auto spanVersyms = tryGetSectionSpan<Elf_Versym>(".gnu.version");
2351+
23302352
if (spanVersyms) {
23312353
for (auto & versym : spanVersyms) {
23322354
if (removedVersionIds.count(versym)) {
@@ -2335,8 +2357,30 @@ void ElfFile<ElfFileParamNames>::removeNeededVersion(const std::map<std::string,
23352357
}
23362358
}
23372359

2338-
debug("remaining entries in .gnu.version_r: %i\n", rdi(shdrVersionR.sh_info));
2339-
this->rewriteSections(true);
2360+
if (removeEntireSection) {
2361+
debug("removing .gnu.version_r and .gnu.version section\n");
2362+
wri(shdrVersionR.sh_type, SHT_NULL);
2363+
auto idxVersion = getSectionIndex(".gnu.version");
2364+
if (idxVersion) {
2365+
auto & shdrVersion = shdrs.at(idxVersion);
2366+
wri(shdrVersion.sh_type, SHT_NULL);
2367+
memset(fileContents->data() + rdi(shdrVersion.sh_offset), 0, rdi(shdrVersion.sh_size));
2368+
wri(shdrVersion.sh_size, 0);
2369+
}
2370+
} else {
2371+
debug("remaining entries in .gnu.version_r: %i\n", rdi(shdrVersionR.sh_info));
2372+
}
2373+
2374+
// we did not change phdrAddress, rewrite it in place
2375+
Elf_Addr phdrAddress;
2376+
for (auto & phdr : phdrs) {
2377+
if (rdi(phdr.p_type) == PT_PHDR) {
2378+
phdrAddress = rdi(phdr.p_vaddr);
2379+
break;
2380+
}
2381+
}
2382+
2383+
rewriteHeaders(phdrAddress);
23402384
}
23412385

23422386
template<ElfFileParams>

0 commit comments

Comments
 (0)