Index: llvm/test/tools/llvm-objcopy/ELF/group.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/group.test +++ llvm/test/tools/llvm-objcopy/ELF/group.test @@ -1,6 +1,6 @@ # RUN: yaml2obj %s -o %t -# RUN: llvm-objcopy --remove-section=.text.bar %t %t2 -# RUN: llvm-readobj --elf-section-groups %t2 | FileCheck %s +# RUN: llvm-objcopy --remove-section=.text.bar %t %t1 +# RUN: llvm-readobj --elf-section-groups %t1 | FileCheck %s # In this test the section .text.bar is getting removed, as a result, # the indices of the sections which go after .text.bar will change, @@ -54,3 +54,17 @@ Section: .text.foo Size: 0x0000000000000000 Binding: STB_WEAK + +# This checks that tool will emit an error when trying to remove the symbol +# table when we have the a group section linked with symtab. +# RUN: not llvm-objcopy -R .symtab %t.o %t2 2>&1 >/dev/null | FileCheck %s --check-prefix=ERR -DINPUT=%t.o +# ERR: error: '[[INPUT]]': section '.symtab' cannot be removed because it is referenced by the group section '.group' +# RUN: llvm-readobj --file-headers --sections %t | FileCheck %s --check-prefix=CHECKEXIST +# CHECKEXIST: SectionHeaderCount: 7 + +# The '.symtab' section could be removed using --allow-broken-links option +# RUN: llvm-objcopy --allow-broken-links -R .symtab %t.o %t3 +# RUN: llvm-readobj --sections %t3 | FileCheck %s --check-prefix=SECTIONS --implicit-check-not=.symtab +# SECTIONS: Name: .group +# RUN: llvm-readobj --file-headers --sections %t3 | FileCheck %s --check-prefix=CHECKREMOVED +# CHECKREMOVED: SectionHeaderCount: 6 Index: llvm/tools/llvm-objcopy/ELF/Object.h =================================================================== --- llvm/tools/llvm-objcopy/ELF/Object.h +++ llvm/tools/llvm-objcopy/ELF/Object.h @@ -475,6 +475,7 @@ class Section : public SectionBase { MAKE_SEC_WRITER_FRIEND +protected: ArrayRef Contents; SectionBase *LinkSection = nullptr; @@ -487,6 +488,8 @@ function_ref ToRemove) override; void initialize(SectionTableRef SecTable) override; void finalize() override; + + ArrayRef getContents() const { return Contents; } }; class OwnedDataSection : public SectionBase { @@ -779,7 +782,7 @@ // TODO: The way stripping and groups interact is complicated // and still needs to be worked on. -class GroupSection : public SectionBase { +class GroupSection : public Section { MAKE_SEC_WRITER_FRIEND const SymbolTableSection *SymTab = nullptr; Symbol *Sym = nullptr; @@ -787,11 +790,7 @@ SmallVector GroupMembers; public: - // TODO: Contents is present in several classes of the hierarchy. - // This needs to be refactored to avoid duplication. - ArrayRef Contents; - - explicit GroupSection(ArrayRef Data) : Contents(Data) {} + explicit GroupSection(ArrayRef Data) : Section(Data) {} void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; } void setSymbol(Symbol *S) { Sym = S; } @@ -800,6 +799,7 @@ void accept(SectionVisitor &) const override; void accept(MutableSectionVisitor &Visitor) override; + void initialize(SectionTableRef SecTable) override; void finalize() override; Error removeSectionReferences( bool AllowBrokenLinks, Index: llvm/tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/Object.cpp +++ llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -965,6 +965,14 @@ return Error::success(); } +void GroupSection::initialize(SectionTableRef SecTable) { + if (Link == ELF::SHN_UNDEF) + return; + LinkSection = SecTable.getSection(Link, "Link field value " + Twine(Link) + + " in group section " + Name + + " is invalid"); +} + void GroupSection::finalize() { this->Info = Sym->Index; this->Link = SymTab->Index; @@ -972,6 +980,14 @@ Error GroupSection::removeSectionReferences( bool AllowBrokenLinks, function_ref ToRemove) { + if (ToRemove(LinkSection)) { + if (!AllowBrokenLinks) + return createStringError(llvm::errc::invalid_argument, + "section '%s' cannot be removed because it is " + "referenced by the group section '%s'", + LinkSection->Name.data(), this->Name.data()); + LinkSection = nullptr; + } llvm::erase_if(GroupMembers, ToRemove); return Error::success(); } @@ -1350,13 +1366,12 @@ GroupSec->Name + "' is not a valid symbol index"); GroupSec->setSymTab(SymTab); GroupSec->setSymbol(Sym); - if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) || - GroupSec->Contents.empty()) + const ArrayRef Contents = GroupSec->getContents(); + if (Contents.size() % sizeof(ELF::Elf32_Word) || Contents.empty()) error("the content of the section " + GroupSec->Name + " is malformed"); const ELF::Elf32_Word *Word = - reinterpret_cast(GroupSec->Contents.data()); - const ELF::Elf32_Word *End = - Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word); + reinterpret_cast(Contents.data()); + const ELF::Elf32_Word *End = Word + Contents.size() / sizeof(ELF::Elf32_Word); GroupSec->setFlagWord(*Word++); for (; Word != End; ++Word) { uint32_t Index = support::endian::read32(Word);