diff --git a/llvm/test/tools/llvm-objcopy/ELF/group.test b/llvm/test/tools/llvm-objcopy/ELF/group.test --- a/llvm/test/tools/llvm-objcopy/ELF/group.test +++ b/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,27 @@ 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 a group section linked with symtab. +# RUN: not llvm-objcopy -R .symtab %t %t2 2>&1 | FileCheck %s --check-prefix=ERR -DINPUT=%t + +# ERR: error: '[[INPUT]]': section '.symtab' cannot be removed because it is referenced by the group section '.group' + +## The '.symtab' section could be removed using --allow-broken-links option. +# RUN: llvm-objcopy --allow-broken-links -R .symtab %t %t3 +# RUN: llvm-readelf --sections %t3 | FileCheck %s --check-prefix=SECTIONS + +# SECTIONS: There are 6 section headers +# SECTIONS: Name Type Address Off Size ES Flg Lk Inf +# SECTIONS-NEXT: NULL +# SECTIONS-NEXT: .group {{.+}} {{.+}} {{.+}} {{.+}} {{.+}} 0 0 +# SECTIONS-NEXT: .text.bar +# SECTIONS-NEXT: .text.foo +# SECTIONS-NEXT: .strtab +# SECTIONS-NEXT: .shstrtab + +## Show that llvm-objcopy can handle a group section with a zero sh_link and +## sh_info fields. +# RUN: llvm-objcopy --allow-broken-links -R .symtab %t3 %t4 +# RUN: cmp %t3 %t4 diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -967,12 +967,22 @@ } void GroupSection::finalize() { - this->Info = Sym->Index; - this->Link = SymTab->Index; + this->Info = Sym ? Sym->Index : 0; + this->Link = SymTab ? SymTab->Index : 0; } Error GroupSection::removeSectionReferences( bool AllowBrokenLinks, function_ref ToRemove) { + if (ToRemove(SymTab)) { + if (!AllowBrokenLinks) + return createStringError( + llvm::errc::invalid_argument, + "section '.symtab' cannot be removed because it is " + "referenced by the group section '%s'", + this->Name.data()); + SymTab = nullptr; + Sym = nullptr; + } llvm::erase_if(GroupMembers, ToRemove); return Error::success(); } @@ -1339,18 +1349,20 @@ error("invalid alignment " + Twine(GroupSec->Align) + " of group section '" + GroupSec->Name + "'"); SectionTableRef SecTable = Obj.sections(); - auto SymTab = SecTable.template getSectionOfType( - GroupSec->Link, - "link field value '" + Twine(GroupSec->Link) + "' in section '" + - GroupSec->Name + "' is invalid", - "link field value '" + Twine(GroupSec->Link) + "' in section '" + - GroupSec->Name + "' is not a symbol table"); - Symbol *Sym = SymTab->getSymbolByIndex(GroupSec->Info); - if (!Sym) - error("info field value '" + Twine(GroupSec->Info) + "' in section '" + - GroupSec->Name + "' is not a valid symbol index"); - GroupSec->setSymTab(SymTab); - GroupSec->setSymbol(Sym); + if (GroupSec->Link != SHN_UNDEF) { + auto SymTab = SecTable.template getSectionOfType( + GroupSec->Link, + "link field value '" + Twine(GroupSec->Link) + "' in section '" + + GroupSec->Name + "' is invalid", + "link field value '" + Twine(GroupSec->Link) + "' in section '" + + GroupSec->Name + "' is not a symbol table"); + Symbol *Sym = SymTab->getSymbolByIndex(GroupSec->Info); + if (!Sym) + error("info field value '" + Twine(GroupSec->Info) + "' in section '" + + 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()) error("the content of the section " + GroupSec->Name + " is malformed");