1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[llvm-objcopy][ELF] Fix removing SHT_GROUP sections.

When a SHT_GROUP section is removed, but other sections of the group are
kept, the SHF_GROUP flag of these sections should be dropped, otherwise
the resulting ELF file will be malformed.

Differential Revision: https://reviews.llvm.org/D80511
This commit is contained in:
Igor Kudrin 2020-05-29 19:27:28 +07:00
parent 6837e69bdf
commit 786d96db56
3 changed files with 45 additions and 0 deletions

View File

@ -0,0 +1,33 @@
## This checks that when the header section of a group is removed, the tool
## drops the flag SHF_GROUP for preserved members of that group.
# RUN: yaml2obj %s -o - \
# RUN: | llvm-objcopy -R .group - - \
# RUN: | llvm-readobj --sections - \
# RUN: | FileCheck %s
# CHECK: Name: .foo
# CHECK-NEXT: Type: SHT_PROGBITS
# CHECK-NEXT: Flags [
# CHECK-NEXT: SHF_ALLOC
# CHECK-NEXT: ]
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Info: foo_grp
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- Name: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_GROUP ]
Symbols:
- Name: foo_grp
Section: .group

View File

@ -65,6 +65,7 @@ void SectionBase::finalize() {}
void SectionBase::markSymbols() {}
void SectionBase::replaceSectionReferences(
const DenseMap<SectionBase *, SectionBase *> &) {}
void SectionBase::onRemove() {}
template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
uint8_t *B = Buf.getBufferStart() + Sec.HeaderOffset;
@ -988,6 +989,13 @@ void GroupSection::replaceSectionReferences(
Sec = To;
}
void GroupSection::onRemove() {
// As the header section of the group is removed, drop the Group flag in its
// former members.
for (SectionBase *Sec : GroupMembers)
Sec->Flags &= ~SHF_GROUP;
}
void Section::initialize(SectionTableRef SecTable) {
if (Link == ELF::SHN_UNDEF)
return;
@ -1838,6 +1846,7 @@ Error Object::removeSections(bool AllowBrokenLinks,
for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
for (auto &Segment : Segments)
Segment->removeSection(RemoveSec.get());
RemoveSec->onRemove();
RemoveSections.insert(RemoveSec.get());
}

View File

@ -424,6 +424,8 @@ public:
virtual void markSymbols();
virtual void
replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
// Notify the section that it is subject to removal.
virtual void onRemove();
};
class Segment {
@ -803,6 +805,7 @@ public:
void markSymbols() override;
void replaceSectionReferences(
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
void onRemove() override;
static bool classof(const SectionBase *S) {
return S->OriginalType == ELF::SHT_GROUP;