llvm.org GIT mirror llvm / b9ccf78
[llvm-objcopy] - Check dynamic relocation sections for broken references. 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 George Rimar 1 year, 5 months ago
4 changed file(s) with 100 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
0 # RUN: yaml2obj %s > %t
1 # RUN: llvm-objcopy -R .got.plt %t %t2
2
3 ## .rela.plt is a dynamic relocation section that has a connection
4 ## via sh_info field with its target section .got.plt.
5 ## Here we check that if the target section is removed then dynamic
6 ## relocation section is also removed and we do not end up with a broken
7 ## sh_info value, for example.
8
9 # RUN: llvm-readelf --sections %t2 \
10 # RUN: | FileCheck %s --implicit-check-not=".got.plt" --implicit-check-not=".rela.plt"
11
12 --- !ELF
13 FileHeader:
14 Class: ELFCLASS64
15 Data: ELFDATA2LSB
16 Type: ET_DYN
17 Machine: EM_X86_64
18 Sections:
19 - Name: .rela.plt
20 Type: SHT_RELA
21 Flags: [ SHF_ALLOC ]
22 Link: .dynsym
23 Info: .got.plt
24 - Name: .got.plt
25 Type: SHT_PROGBITS
26 Flags: [ SHF_WRITE, SHF_ALLOC ]
27 DynamicSymbols:
28 - Name: bar
29 Binding: STB_GLOBAL
0 # RUN: yaml2obj %s > %t
1
2 ## Check we cannot remove the .dynsym symbol table because dynamic
3 ## relocation section .rela.dyn still references it via sh_link field.
4 # RUN: not llvm-objcopy -R .dynsym %t %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
5 # ERR: error: Symbol table .dynsym cannot be removed because it is referenced by the relocation section .rela.dyn.
6
7 ## Check we can remove .dynsym after removing the reference.
8 # RUN: llvm-objcopy -R .dynsym -R .rela.dyn %t %t2
9 # RUN: llvm-readelf --sections %t2 | FileCheck %s --implicit-check-not=".dynsym"
10
11 ## Check we zero out sh_link field and allow producing output with the --allow-broken-links switch.
12 # RUN: llvm-objcopy -R .dynsym --allow-broken-links %t %t2
13 # RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=DROP-LINK
14 # DROP-LINK: [Nr] Name Type Address Off Size ES Flg L
15 # DROP-LINK: [ 1] .rela.dyn RELA 0000000000000270 000040 000000 18 A 0
16 # DROP-LINK-NOT: .dynsym
17
18 !ELF
19 FileHeader:
20 Class: ELFCLASS64
21 Data: ELFDATA2LSB
22 Type: ET_DYN
23 Machine: EM_X86_64
24 Sections:
25 - Name: .rela.dyn
26 Type: SHT_RELA
27 Flags: [ SHF_ALLOC ]
28 Address: 0x0000000000000270
29 Link: .dynsym
30 EntSize: 0x0000000000000018
31 DynamicSymbols:
32 - Name: bar
33 Binding: STB_GLOBAL
679679 }
680680
681681 void DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
682 Visitor.visit(*this);
683 }
684
685 Error Section::removeSectionReferences(bool AllowBrokenDependency,
686 function_ref ToRemove) {
687 if (ToRemove(LinkSection)) {
682 Visitor.visit(*this);
683 }
684
685 Error DynamicRelocationSection::removeSectionReferences(
686 bool AllowBrokenLinks, function_ref ToRemove) {
687 if (ToRemove(Symbols)) {
688 if (!AllowBrokenLinks)
689 return createStringError(
690 llvm::errc::invalid_argument,
691 "Symbol table %s cannot be removed because it is "
692 "referenced by the relocation section %s.",
693 Symbols->Name.data(), this->Name.data());
694 Symbols = nullptr;
695 }
696
697 // SecToApplyRel contains a section referenced by sh_info field. It keeps
698 // a section to which the relocation section applies. When we remove any
699 // sections we also remove their relocation sections. Since we do that much
700 // earlier, this assert should never be triggered.
701 assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
702
703 return Error::success();
704 }
705
706 Error Section::removeSectionReferences(bool AllowBrokenDependency,
707 function_ref ToRemove) {
708 if (ToRemove(LinkSection)) {
688709 if (!AllowBrokenDependency)
689710 return createStringError(llvm::errc::invalid_argument,
690711 "Section %s cannot be removed because it is "
681681
682682 public:
683683 explicit DynamicRelocationSection(ArrayRef Data) : Contents(Data) {}
684
685 void accept(SectionVisitor &) const override;
686 void accept(MutableSectionVisitor &Visitor) override;
687
688 static bool classof(const SectionBase *S) {
689 if (!(S->Flags & ELF::SHF_ALLOC))
684
685 void accept(SectionVisitor &) const override;
686 void accept(MutableSectionVisitor &Visitor) override;
687 Error removeSectionReferences(
688 bool AllowBrokenLinks,
689 function_ref ToRemove) override;
690
691 static bool classof(const SectionBase *S) {
692 if (!(S->Flags & ELF::SHF_ALLOC))
690693 return false;
691694 return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
692695 }