Index: test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shinfo-reference.test =================================================================== --- test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shinfo-reference.test +++ 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 =================================================================== --- test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shlink-reference.test +++ test/tools/llvm-objcopy/ELF/dynrelocsec-remove-shlink-reference.test @@ -0,0 +1,34 @@ +# 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" + +## Check we zero out sh_link field and allow producing output with the --allow-broken-links. +# RUN: llvm-objcopy -R .dynsym --allow-broken-links %t %t2 +# RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=DROP-LINK +# DROP-LINK: [Nr] Name Type Address Off Size ES Flg L +# DROP-LINK: [ 1] .rela.dyn RELA 0000000000000270 000040 000000 18 A 0 +# DROP-LINK-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 + 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 @@ -685,6 +685,9 @@ void accept(SectionVisitor &) const override; void accept(MutableSectionVisitor &Visitor) override; + Error removeSectionReferences( + bool AllowBrokenLinks, + 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 @@ -683,6 +683,27 @@ Visitor.visit(*this); } +Error DynamicRelocationSection::removeSectionReferences( + bool AllowBrokenLinks, function_ref ToRemove) { + if (ToRemove(Symbols)) { + if (!AllowBrokenLinks) + 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()); + Symbols = nullptr; + } + + // 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(bool AllowBrokenDependency, function_ref ToRemove) { if (ToRemove(LinkSection)) {