Index: test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shinfo-reference.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shinfo-reference.test @@ -0,0 +1,30 @@ +# RUN: yaml2obj %s > %t +# RUN: llvm-objcopy -R .got.plt %t %t2 + +## .rela.plt is a dynamic relocation section that has a connection +## via sh_info field with its target section .got.plt. +## Here we check that if the target section is removed then dynamic +## relocation section is also removed and we do not end up with a broken +## sh_info value, for example. + +# RUN: llvm-readelf --sections %t2 | \ +# RUN: FileCheck %s --implicit-check-not=".got.plt" --implicit-check-not=".rela.plt" + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela.plt + Type: SHT_RELA + Flags: [ SHF_ALLOC ] + Link: .dynsym + Info: .got.plt + - Name: .got.plt + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] +DynamicSymbols: + - Name: bar + Binding: STB_GLOBAL Index: test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shlink-reference.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shlink-reference.test @@ -0,0 +1,29 @@ +# RUN: yaml2obj %s > %t + +## Check we cannot remove the .dynsym symbol table because dynamic +## relocation section .rela.dyn still references it via sh_link field. +# RUN: not llvm-objcopy -R .dynsym %t %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR +# ERR: error: Symbol table .dynsym cannot be removed because it is referenced by the relocation section .rela.dyn. + +## Check we can remove .dynsym after removing the reference. +# RUN: llvm-objcopy -R .dynsym -R .rela.dyn %t %t2 +# RUN: llvm-readelf --sections %t2 | FileCheck %s --implicit-check-not=".dynsym" + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .rela.dyn + Type: SHT_RELA + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000270 + Link: .dynsym +## TODO: zero Info field should not be needed. + Info: 0 + EntSize: 0x0000000000000018 +DynamicSymbols: + - Name: bar + Binding: STB_GLOBAL Index: tools/llvm-objcopy/ELF/Object.h =================================================================== --- tools/llvm-objcopy/ELF/Object.h +++ tools/llvm-objcopy/ELF/Object.h @@ -684,6 +684,8 @@ void accept(SectionVisitor &) const override; void accept(MutableSectionVisitor &Visitor) override; + Error removeSectionReferences( + function_ref ToRemove) override; static bool classof(const SectionBase *S) { if (!(S->Flags & ELF::SHF_ALLOC)) Index: tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- tools/llvm-objcopy/ELF/Object.cpp +++ tools/llvm-objcopy/ELF/Object.cpp @@ -667,6 +667,23 @@ Visitor.visit(*this); } +Error DynamicRelocationSection::removeSectionReferences( + function_ref ToRemove) { + if (ToRemove(Symbols)) + return createStringError(llvm::errc::invalid_argument, + "Symbol table %s cannot be removed because it is " + "referenced by the relocation section %s.", + Symbols->Name.data(), this->Name.data()); + + // SecToApplyRel contains a section referenced by sh_info field. It keeps + // a section to which the relocation section applies. When we remove any + // sections we also remove their relocation sections. Since we do that much + // earlier, this assert should never be triggered. + assert(!SecToApplyRel || !ToRemove(SecToApplyRel)); + + return Error::success(); +} + Error Section::removeSectionReferences( function_ref ToRemove) { if (ToRemove(LinkSection))