Skip to content

Commit 67f590e

Browse files
author
George Rimar
committedApr 30, 2019
[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 llvm-svn: 359552
1 parent 648a8cf commit 67f590e

File tree

4 files changed

+100
-12
lines changed

4 files changed

+100
-12
lines changed
 
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# RUN: yaml2obj %s > %t
2+
# RUN: llvm-objcopy -R .got.plt %t %t2
3+
4+
## .rela.plt is a dynamic relocation section that has a connection
5+
## via sh_info field with its target section .got.plt.
6+
## Here we check that if the target section is removed then dynamic
7+
## relocation section is also removed and we do not end up with a broken
8+
## sh_info value, for example.
9+
10+
# RUN: llvm-readelf --sections %t2 \
11+
# RUN: | FileCheck %s --implicit-check-not=".got.plt" --implicit-check-not=".rela.plt"
12+
13+
--- !ELF
14+
FileHeader:
15+
Class: ELFCLASS64
16+
Data: ELFDATA2LSB
17+
Type: ET_DYN
18+
Machine: EM_X86_64
19+
Sections:
20+
- Name: .rela.plt
21+
Type: SHT_RELA
22+
Flags: [ SHF_ALLOC ]
23+
Link: .dynsym
24+
Info: .got.plt
25+
- Name: .got.plt
26+
Type: SHT_PROGBITS
27+
Flags: [ SHF_WRITE, SHF_ALLOC ]
28+
DynamicSymbols:
29+
- Name: bar
30+
Binding: STB_GLOBAL
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# RUN: yaml2obj %s > %t
2+
3+
## Check we cannot remove the .dynsym symbol table because dynamic
4+
## relocation section .rela.dyn still references it via sh_link field.
5+
# RUN: not llvm-objcopy -R .dynsym %t %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR
6+
# ERR: error: Symbol table .dynsym cannot be removed because it is referenced by the relocation section .rela.dyn.
7+
8+
## Check we can remove .dynsym after removing the reference.
9+
# RUN: llvm-objcopy -R .dynsym -R .rela.dyn %t %t2
10+
# RUN: llvm-readelf --sections %t2 | FileCheck %s --implicit-check-not=".dynsym"
11+
12+
## Check we zero out sh_link field and allow producing output with the --allow-broken-links switch.
13+
# RUN: llvm-objcopy -R .dynsym --allow-broken-links %t %t2
14+
# RUN: llvm-readelf --sections %t2 | FileCheck %s --check-prefix=DROP-LINK
15+
# DROP-LINK: [Nr] Name Type Address Off Size ES Flg L
16+
# DROP-LINK: [ 1] .rela.dyn RELA 0000000000000270 000040 000000 18 A 0
17+
# DROP-LINK-NOT: .dynsym
18+
19+
!ELF
20+
FileHeader:
21+
Class: ELFCLASS64
22+
Data: ELFDATA2LSB
23+
Type: ET_DYN
24+
Machine: EM_X86_64
25+
Sections:
26+
- Name: .rela.dyn
27+
Type: SHT_RELA
28+
Flags: [ SHF_ALLOC ]
29+
Address: 0x0000000000000270
30+
Link: .dynsym
31+
EntSize: 0x0000000000000018
32+
DynamicSymbols:
33+
- Name: bar
34+
Binding: STB_GLOBAL

‎llvm/tools/llvm-objcopy/ELF/Object.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -680,12 +680,33 @@ void DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
680680
}
681681

682682
void DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
683-
Visitor.visit(*this);
684-
}
685-
686-
Error Section::removeSectionReferences(bool AllowBrokenDependency,
687-
function_ref<bool(const SectionBase *)> ToRemove) {
688-
if (ToRemove(LinkSection)) {
683+
Visitor.visit(*this);
684+
}
685+
686+
Error DynamicRelocationSection::removeSectionReferences(
687+
bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
688+
if (ToRemove(Symbols)) {
689+
if (!AllowBrokenLinks)
690+
return createStringError(
691+
llvm::errc::invalid_argument,
692+
"Symbol table %s cannot be removed because it is "
693+
"referenced by the relocation section %s.",
694+
Symbols->Name.data(), this->Name.data());
695+
Symbols = nullptr;
696+
}
697+
698+
// SecToApplyRel contains a section referenced by sh_info field. It keeps
699+
// a section to which the relocation section applies. When we remove any
700+
// sections we also remove their relocation sections. Since we do that much
701+
// earlier, this assert should never be triggered.
702+
assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
703+
704+
return Error::success();
705+
}
706+
707+
Error Section::removeSectionReferences(bool AllowBrokenDependency,
708+
function_ref<bool(const SectionBase *)> ToRemove) {
709+
if (ToRemove(LinkSection)) {
689710
if (!AllowBrokenDependency)
690711
return createStringError(llvm::errc::invalid_argument,
691712
"Section %s cannot be removed because it is "

‎llvm/tools/llvm-objcopy/ELF/Object.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -682,12 +682,15 @@ class DynamicRelocationSection
682682

683683
public:
684684
explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
685-
686-
void accept(SectionVisitor &) const override;
687-
void accept(MutableSectionVisitor &Visitor) override;
688-
689-
static bool classof(const SectionBase *S) {
690-
if (!(S->Flags & ELF::SHF_ALLOC))
685+
686+
void accept(SectionVisitor &) const override;
687+
void accept(MutableSectionVisitor &Visitor) override;
688+
Error removeSectionReferences(
689+
bool AllowBrokenLinks,
690+
function_ref<bool(const SectionBase *)> ToRemove) override;
691+
692+
static bool classof(const SectionBase *S) {
693+
if (!(S->Flags & ELF::SHF_ALLOC))
691694
return false;
692695
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
693696
}

0 commit comments

Comments
 (0)
Please sign in to comment.