@@ -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
23422386template <ElfFileParams>
0 commit comments