This is a fix for https://bugs.llvm.org/show_bug.cgi?id=41371.
Currently, it is possible to break the sh_link field of the dynamic relocation section
by removing the section it refers to. The patch fixes an issue and adds 2 test cases.
One of them shows that it does not seem possible to break the sh_info field.
I added an assert to verify this.
Differential revision: https://reviews.llvm.org/D60825
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359552
91177308-0d34-0410-b5e6-
96231b3b80d8
--- /dev/null
+# RUN: yaml2obj %s > %t\r
+# RUN: llvm-objcopy -R .got.plt %t %t2\r
+\r
+## .rela.plt is a dynamic relocation section that has a connection\r
+## via sh_info field with its target section .got.plt.\r
+## Here we check that if the target section is removed then dynamic\r
+## relocation section is also removed and we do not end up with a broken\r
+## sh_info value, for example.\r
+\r
+# RUN: llvm-readelf --sections %t2 \\r
+# RUN: | FileCheck %s --implicit-check-not=".got.plt" --implicit-check-not=".rela.plt"\r
+\r
+--- !ELF\r
+FileHeader:\r
+ Class: ELFCLASS64\r
+ Data: ELFDATA2LSB\r
+ Type: ET_DYN\r
+ Machine: EM_X86_64\r
+Sections:\r
+ - Name: .rela.plt\r
+ Type: SHT_RELA\r
+ Flags: [ SHF_ALLOC ]\r
+ Link: .dynsym\r
+ Info: .got.plt\r
+ - Name: .got.plt\r
+ Type: SHT_PROGBITS\r
+ Flags: [ SHF_WRITE, SHF_ALLOC ]\r
+DynamicSymbols:\r
+ - Name: bar\r
+ Binding: STB_GLOBAL\r
--- /dev/null
+# RUN: yaml2obj %s > %t\r
+\r
+## Check we cannot remove the .dynsym symbol table because dynamic\r
+## relocation section .rela.dyn still references it via sh_link field.\r
+# RUN: not llvm-objcopy -R .dynsym %t %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR\r
+# ERR: error: Symbol table .dynsym cannot be removed because it is referenced by the relocation section .rela.dyn.\r
+\r
+## Check we can remove .dynsym after removing the reference.\r
+# RUN: llvm-objcopy -R .dynsym -R .rela.dyn %t %t2\r
+# RUN: llvm-readelf --sections %t2 | FileCheck %s --implicit-check-not=".dynsym"\r
+\r
+## Check we zero out sh_link field and allow producing output with the --allow-broken-links switch.\r
+# RUN: llvm-objcopy -R .dynsym --allow-broken-links %t %t2\r
+# RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=DROP-LINK\r
+# DROP-LINK: [Nr] Name Type Address Off Size ES Flg L\r
+# DROP-LINK: [ 1] .rela.dyn RELA 0000000000000270 000040 000000 18 A 0\r
+# DROP-LINK-NOT: .dynsym\r
+\r
+!ELF\r
+FileHeader:\r
+ Class: ELFCLASS64\r
+ Data: ELFDATA2LSB\r
+ Type: ET_DYN\r
+ Machine: EM_X86_64\r
+Sections:\r
+ - Name: .rela.dyn\r
+ Type: SHT_RELA\r
+ Flags: [ SHF_ALLOC ]\r
+ Address: 0x0000000000000270\r
+ Link: .dynsym\r
+ EntSize: 0x0000000000000018\r
+DynamicSymbols:\r
+ - Name: bar\r
+ Binding: STB_GLOBAL\r
}
void DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
- Visitor.visit(*this);
-}
-
-Error Section::removeSectionReferences(bool AllowBrokenDependency,
- function_ref<bool(const SectionBase *)> ToRemove) {
- if (ToRemove(LinkSection)) {
+ Visitor.visit(*this);\r
+}\r
+\r
+Error DynamicRelocationSection::removeSectionReferences(\r
+ bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {\r
+ if (ToRemove(Symbols)) {\r
+ if (!AllowBrokenLinks)\r
+ return createStringError(\r
+ llvm::errc::invalid_argument,\r
+ "Symbol table %s cannot be removed because it is "\r
+ "referenced by the relocation section %s.",\r
+ Symbols->Name.data(), this->Name.data());\r
+ Symbols = nullptr;\r
+ }\r
+\r
+ // SecToApplyRel contains a section referenced by sh_info field. It keeps\r
+ // a section to which the relocation section applies. When we remove any\r
+ // sections we also remove their relocation sections. Since we do that much\r
+ // earlier, this assert should never be triggered.\r
+ assert(!SecToApplyRel || !ToRemove(SecToApplyRel));\r
+\r
+ return Error::success();\r
+}\r
+\r
+Error Section::removeSectionReferences(bool AllowBrokenDependency,\r
+ function_ref<bool(const SectionBase *)> ToRemove) {\r
+ if (ToRemove(LinkSection)) {\r
if (!AllowBrokenDependency)
return createStringError(llvm::errc::invalid_argument,
"Section %s cannot be removed because it is "
public:
explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
-
- void accept(SectionVisitor &) const override;
- void accept(MutableSectionVisitor &Visitor) override;
-
- static bool classof(const SectionBase *S) {
- if (!(S->Flags & ELF::SHF_ALLOC))
+\r
+ void accept(SectionVisitor &) const override;\r
+ void accept(MutableSectionVisitor &Visitor) override;\r
+ Error removeSectionReferences(\r
+ bool AllowBrokenLinks,\r
+ function_ref<bool(const SectionBase *)> ToRemove) override;\r
+\r
+ static bool classof(const SectionBase *S) {\r
+ if (!(S->Flags & ELF::SHF_ALLOC))\r
return false;
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
}