<div dir="ltr">This breaks platforms with python3 I think. We need python to be in the compatible space between 2.7 and 3.</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jul 16, 2018 at 12:54 PM Jake Ehrlich via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: jakehehrlich<br>
Date: Mon Jul 16 12:48:52 2018<br>
New Revision: 337204<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=337204&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=337204&view=rev</a><br>
Log:<br>
[llvm-objcopy] Add support for large indexes<br>
<br>
This patch is an update of an older patch that never landed<br>
(see here: <a href="https://reviews.llvm.org/D42516" rel="noreferrer" target="_blank">https://reviews.llvm.org/D42516</a>)<br>
<br>
Recently various users have run into this issue and it just 100%<br>
has to be solved at this point. The main difference in this patch<br>
is that I use gunzip instead of unzip which should hopefully allow<br>
tests to pass. Please review this as if it is a new patch however.<br>
I found some issues along the way and made some minor modifications.<br>
<br>
The binary used in this patch for testing (a zip file to make it small)<br>
can be found here:<br>
<a href="https://drive.google.com/file/d/1UjsnTO9edLttZibbr-2T1bJl92KEQFAO/view?usp=sharing" rel="noreferrer" target="_blank">https://drive.google.com/file/d/1UjsnTO9edLttZibbr-2T1bJl92KEQFAO/view?usp=sharing</a><br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D49206" rel="noreferrer" target="_blank">https://reviews.llvm.org/D49206</a><br>
<br>
Added:<br>
llvm/trunk/test/tools/llvm-objcopy/Inputs/many-sections.o.gz (with props)<br>
llvm/trunk/test/tools/llvm-objcopy/Inputs/ungzip.py<br>
llvm/trunk/test/tools/llvm-objcopy/auto-remove-shndx.test<br>
llvm/trunk/test/tools/llvm-objcopy/many-sections.test<br>
llvm/trunk/test/tools/llvm-objcopy/remove-shndx.test<br>
llvm/trunk/test/tools/llvm-objcopy/strict-no-add.test<br>
Modified:<br>
llvm/trunk/tools/llvm-objcopy/Object.cpp<br>
llvm/trunk/tools/llvm-objcopy/Object.h<br>
<br>
Added: llvm/trunk/test/tools/llvm-objcopy/Inputs/many-sections.o.gz<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/Inputs/many-sections.o.gz?rev=337204&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/Inputs/many-sections.o.gz?rev=337204&view=auto</a><br>
==============================================================================<br>
Binary file - no diff available.<br>
<br>
Propchange: llvm/trunk/test/tools/llvm-objcopy/Inputs/many-sections.o.gz<br>
------------------------------------------------------------------------------<br>
svn:mime-type = application/octet-stream<br>
<br>
Added: llvm/trunk/test/tools/llvm-objcopy/Inputs/ungzip.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/Inputs/ungzip.py?rev=337204&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/Inputs/ungzip.py?rev=337204&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-objcopy/Inputs/ungzip.py (added)<br>
+++ llvm/trunk/test/tools/llvm-objcopy/Inputs/ungzip.py Mon Jul 16 12:48:52 2018<br>
@@ -0,0 +1,5 @@<br>
+import gzip<br>
+import sys<br>
+<br>
+with gzip.open(sys.argv[1], 'rb') as f:<br>
+ sys.stdout.write(f.read())<br>
<br>
Added: llvm/trunk/test/tools/llvm-objcopy/auto-remove-shndx.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/auto-remove-shndx.test?rev=337204&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/auto-remove-shndx.test?rev=337204&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-objcopy/auto-remove-shndx.test (added)<br>
+++ llvm/trunk/test/tools/llvm-objcopy/auto-remove-shndx.test Mon Jul 16 12:48:52 2018<br>
@@ -0,0 +1,5 @@<br>
+# RUN: python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t<br>
+# RUN: llvm-objcopy -R .text -R s0 -R s1 -R s2 -R s3 -R s4 -R s5 -R s6 %t %t2<br>
+# RUN: llvm-readobj -sections %t2 | FileCheck --check-prefix=SECS %s<br>
+<br>
+# SECS-NOT: Name: .symtab_shndx<br>
<br>
Added: llvm/trunk/test/tools/llvm-objcopy/many-sections.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/many-sections.test?rev=337204&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/many-sections.test?rev=337204&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-objcopy/many-sections.test (added)<br>
+++ llvm/trunk/test/tools/llvm-objcopy/many-sections.test Mon Jul 16 12:48:52 2018<br>
@@ -0,0 +1,53 @@<br>
+RUN: python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t<br>
+RUN: llvm-objcopy %t %t2<br>
+RUN: llvm-readobj -file-headers %t2 | FileCheck --check-prefix=EHDR %s<br>
+RUN: llvm-readobj -sections %t2 | FileCheck --check-prefix=SECS %s<br>
+RUN: llvm-readobj -symbols %t2 | grep "Symbol {" | wc -l | FileCheck --check-prefix=SYMS %s<br>
+<br>
+EHDR: Format: ELF64-x86-64<br>
+EHDR-NEXT: Arch: x86_64<br>
+EHDR-NEXT: AddressSize: 64bit<br>
+EHDR-NEXT: LoadName:<br>
+EHDR-NEXT: ElfHeader {<br>
+EHDR-NEXT: Ident {<br>
+EHDR-NEXT: Magic: (7F 45 4C 46)<br>
+EHDR-NEXT: Class: 64-bit (0x2)<br>
+EHDR-NEXT: DataEncoding: LittleEndian (0x1)<br>
+EHDR-NEXT: FileVersion: 1<br>
+EHDR-NEXT: OS/ABI: SystemV (0x0)<br>
+EHDR-NEXT: ABIVersion: 0<br>
+EHDR-NEXT: Unused: (00 00 00 00 00 00 00)<br>
+EHDR-NEXT: }<br>
+EHDR-NEXT: Type: Relocatable (0x1)<br>
+EHDR-NEXT: Machine: EM_X86_64 (0x3E)<br>
+EHDR-NEXT: Version: 1<br>
+EHDR-NEXT: Entry: 0x0<br>
+EHDR-NEXT: ProgramHeaderOffset: 0x40<br>
+EHDR-NEXT: SectionHeaderOffset:<br>
+EHDR-NEXT: Flags [ (0x0)<br>
+EHDR-NEXT: ]<br>
+EHDR-NEXT: HeaderSize: 64<br>
+EHDR-NEXT: ProgramHeaderEntrySize: 56<br>
+EHDR-NEXT: ProgramHeaderCount: 0<br>
+EHDR-NEXT: SectionHeaderEntrySize: 64<br>
+EHDR-NEXT: SectionHeaderCount: 0<br>
+EHDR-NEXT: StringTableSectionIndex: 65535<br>
+EHDR-NEXT: }<br>
+<br>
+SECS: Index: 65285<br>
+SECS-NEXT: Name: .symtab<br>
+SECS-NEXT: Type: SHT_SYMTAB<br>
+SECS: Name: .symtab_shndx<br>
+SECS-NEXT: Type: SHT_SYMTAB_SHNDX<br>
+SECS-NEXT: Flags [ (0x0)<br>
+SECS-NEXT: ]<br>
+SECS-NEXT: Address: 0x0<br>
+SECS-NEXT: Offset:<br>
+# There should be #syms * EntrySize bytes.<br>
+SECS-NEXT: Size: 261136<br>
+SECS-NEXT: Link: 65285<br>
+SECS-NEXT: Info:<br>
+SECS-NEXT: AddressAlignment: 4<br>
+SECS-NEXT: EntrySize: 4<br>
+SECS: Index: 65287<br>
+SYMS: 65284<br>
<br>
Added: llvm/trunk/test/tools/llvm-objcopy/remove-shndx.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/remove-shndx.test?rev=337204&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/remove-shndx.test?rev=337204&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-objcopy/remove-shndx.test (added)<br>
+++ llvm/trunk/test/tools/llvm-objcopy/remove-shndx.test Mon Jul 16 12:48:52 2018<br>
@@ -0,0 +1,7 @@<br>
+# This test checks to see that a .symtab_shndx section is added to any binary<br>
+# that needs it, even if the original was removed.<br>
+RUN: python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t<br>
+RUN: llvm-objcopy -R .symtab_shndx %t %t2<br>
+RUN: llvm-readobj -sections %t2 | FileCheck %s<br>
+<br>
+CHECK: Name: .symtab_shndx (<br>
<br>
Added: llvm/trunk/test/tools/llvm-objcopy/strict-no-add.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/strict-no-add.test?rev=337204&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/strict-no-add.test?rev=337204&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-objcopy/strict-no-add.test (added)<br>
+++ llvm/trunk/test/tools/llvm-objcopy/strict-no-add.test Mon Jul 16 12:48:52 2018<br>
@@ -0,0 +1,10 @@<br>
+# This test makes sure that sections added at the end that don't have symbols<br>
+# defined in them don't trigger the creation of a large index table.<br>
+<br>
+RUN: python %p/Inputs/ungzip.py %p/Inputs/many-sections.o.gz > %t.0<br>
+RUN: cat %p/Inputs/alloc-symtab.o > %t<br>
+RUN: llvm-objcopy -R .text -R s0 -R s1 -R s2 -R s3 -R s4 -R s5 -R s6 %t.0 %t2<br>
+RUN: llvm-objcopy -add-section=.s0=%t -add-section=.s1=%t -add-section=.s2=%t %t2 %t2<br>
+RUN: llvm-readobj -sections %t2 | FileCheck --check-prefix=SECS %s<br>
+<br>
+SECS-NOT: Name: .symtab_shndx<br>
<br>
Modified: llvm/trunk/tools/llvm-objcopy/Object.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.cpp?rev=337204&r1=337203&r2=337204&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.cpp?rev=337204&r1=337203&r2=337204&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-objcopy/Object.cpp (original)<br>
+++ llvm/trunk/tools/llvm-objcopy/Object.cpp Mon Jul 16 12:48:52 2018<br>
@@ -101,6 +101,10 @@ template <class ELFT> void ELFWriter<ELF<br>
<br>
SectionVisitor::~SectionVisitor() {}<br>
<br>
+void BinarySectionWriter::visit(const SectionIndexSection &Sec) {<br>
+ error("Cannot write symbol section index table '" + Sec.Name + "' ");<br>
+}<br>
+<br>
void BinarySectionWriter::visit(const SymbolTableSection &Sec) {<br>
error("Cannot write symbol table '" + Sec.Name + "' out to binary");<br>
}<br>
@@ -154,6 +158,29 @@ void StringTableSection::accept(SectionV<br>
Visitor.visit(*this);<br>
}<br>
<br>
+template <class ELFT><br>
+void ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {<br>
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;<br>
+ auto *IndexesBuffer = reinterpret_cast<typename ELFT::Word *>(Buf);<br>
+ std::copy(std::begin(Sec.Indexes), std::end(Sec.Indexes), IndexesBuffer);<br>
+}<br>
+<br>
+void SectionIndexSection::initialize(SectionTableRef SecTable) {<br>
+ Size = 0;<br>
+ setSymTab(SecTable.getSectionOfType<SymbolTableSection>(<br>
+ Link,<br>
+ "Link field value " + Twine(Link) + " in section " + Name + " is invalid",<br>
+ "Link field value " + Twine(Link) + " in section " + Name +<br>
+ " is not a symbol table"));<br>
+ Symbols->setShndxTable(this);<br>
+}<br>
+<br>
+void SectionIndexSection::finalize() { Link = Symbols->Index; }<br>
+<br>
+void SectionIndexSection::accept(SectionVisitor &Visitor) const {<br>
+ Visitor.visit(*this);<br>
+}<br>
+<br>
static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {<br>
switch (Index) {<br>
case SHN_ABS:<br>
@@ -172,8 +199,13 @@ static bool isValidReservedSectionIndex(<br>
return false;<br>
}<br>
<br>
+// Large indexes force us to clarify exactly what this function should do. This<br>
+// function should return the value that will appear in st_shndx when written<br>
+// out.<br>
uint16_t Symbol::getShndx() const {<br>
if (DefinedIn != nullptr) {<br>
+ if (DefinedIn->Index >= SHN_LORESERVE)<br>
+ return SHN_XINDEX;<br>
return DefinedIn->Index;<br>
}<br>
switch (ShndxType) {<br>
@@ -187,6 +219,7 @@ uint16_t Symbol::getShndx() const {<br>
case SYMBOL_HEXAGON_SCOMMON_2:<br>
case SYMBOL_HEXAGON_SCOMMON_4:<br>
case SYMBOL_HEXAGON_SCOMMON_8:<br>
+ case SYMBOL_XINDEX:<br>
return static_cast<uint16_t>(ShndxType);<br>
}<br>
llvm_unreachable("Symbol with invalid ShndxType encountered");<br>
@@ -207,6 +240,8 @@ void SymbolTableSection::addSymbol(Strin<br>
Sym.Binding = Bind;<br>
Sym.Type = Type;<br>
Sym.DefinedIn = DefinedIn;<br>
+ if (DefinedIn != nullptr)<br>
+ DefinedIn->HasSymbol = true;<br>
if (DefinedIn == nullptr) {<br>
if (Shndx >= SHN_LORESERVE)<br>
Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);<br>
@@ -222,6 +257,8 @@ void SymbolTableSection::addSymbol(Strin<br>
}<br>
<br>
void SymbolTableSection::removeSectionReferences(const SectionBase *Sec) {<br>
+ if (SectionIndexTable == Sec)<br>
+ SectionIndexTable = nullptr;<br>
if (SymbolNames == Sec) {<br>
error("String table " + SymbolNames->Name +<br>
" cannot be removed because it is referenced by the symbol table " +<br>
@@ -274,7 +311,17 @@ void SymbolTableSection::finalize() {<br>
Info = MaxLocalIndex + 1;<br>
}<br>
<br>
-void SymbolTableSection::addSymbolNames() {<br>
+void SymbolTableSection::prepareForLayout() {<br>
+ // Add all potential section indexes before file layout so that the section<br>
+ // index section has the approprite size.<br>
+ if (SectionIndexTable != nullptr) {<br>
+ for (const auto &Sym : Symbols) {<br>
+ if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)<br>
+ SectionIndexTable->addIndex(Sym->DefinedIn->Index);<br>
+ else<br>
+ SectionIndexTable->addIndex(SHN_UNDEF);<br>
+ }<br>
+ }<br>
// Add all of our strings to SymbolNames so that SymbolNames has the right<br>
// size before layout is decided.<br>
for (auto &Sym : Symbols)<br>
@@ -654,12 +701,32 @@ template <class ELFT><br>
void ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {<br>
const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index));<br>
StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr));<br>
+ ArrayRef<Elf_Word> ShndxData;<br>
<br>
- for (const auto &Sym : unwrapOrError(ElfFile.symbols(&Shdr))) {<br>
+ auto Symbols = unwrapOrError(ElfFile.symbols(&Shdr));<br>
+ for (const auto &Sym : Symbols) {<br>
SectionBase *DefSection = nullptr;<br>
StringRef Name = unwrapOrError(Sym.getName(StrTabData));<br>
<br>
- if (Sym.st_shndx >= SHN_LORESERVE) {<br>
+ if (Sym.st_shndx == SHN_XINDEX) {<br>
+ if (SymTab->getShndxTable() == nullptr)<br>
+ error("Symbol '" + Name +<br>
+ "' has index SHN_XINDEX but no SHT_SYMTAB_SHNDX section exists.");<br>
+ if (ShndxData.data() == nullptr) {<br>
+ const Elf_Shdr &ShndxSec =<br>
+ *unwrapOrError(ElfFile.getSection(SymTab->getShndxTable()->Index));<br>
+ ShndxData = unwrapOrError(<br>
+ ElfFile.template getSectionContentsAsArray<Elf_Word>(&ShndxSec));<br>
+ if (ShndxData.size() != Symbols.size())<br>
+ error("Symbol section index table does not have the same number of "<br>
+ "entries as the symbol table.");<br>
+ }<br>
+ Elf_Word Index = ShndxData[&Sym - Symbols.begin()];<br>
+ DefSection = Obj.sections().getSection(<br>
+ Index,<br>
+ "Symbol '" + Name + "' has invalid section index " +<br>
+ Twine(Index));<br>
+ } else if (Sym.st_shndx >= SHN_LORESERVE) {<br>
if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {<br>
error(<br>
"Symbol '" + Name +<br>
@@ -669,7 +736,7 @@ void ELFBuilder<ELFT>::initSymbolTable(S<br>
} else if (Sym.st_shndx != SHN_UNDEF) {<br>
DefSection = Obj.sections().getSection(<br>
Sym.st_shndx, "Symbol '" + Name +<br>
- "' is defined in invalid section with index " +<br>
+ "' is defined has invalid section index " +<br>
Twine(Sym.st_shndx));<br>
}<br>
<br>
@@ -699,14 +766,14 @@ void initRelocations(RelocationSection *<br>
}<br>
}<br>
<br>
-SectionBase *SectionTableRef::getSection(uint16_t Index, Twine ErrMsg) {<br>
+SectionBase *SectionTableRef::getSection(uint32_t Index, Twine ErrMsg) {<br>
if (Index == SHN_UNDEF || Index > Sections.size())<br>
error(ErrMsg);<br>
return Sections[Index - 1].get();<br>
}<br>
<br>
template <class T><br>
-T *SectionTableRef::getSectionOfType(uint16_t Index, Twine IndexErrMsg,<br>
+T *SectionTableRef::getSectionOfType(uint32_t Index, Twine IndexErrMsg,<br>
Twine TypeErrMsg) {<br>
if (T *Sec = dyn_cast<T>(getSection(Index, IndexErrMsg)))<br>
return Sec;<br>
@@ -753,6 +820,11 @@ SectionBase &ELFBuilder<ELFT>::makeSecti<br>
Obj.SymbolTable = &SymTab;<br>
return SymTab;<br>
}<br>
+ case SHT_SYMTAB_SHNDX: {<br>
+ auto &ShndxSection = Obj.addSection<SectionIndexSection>();<br>
+ Obj.SectionIndexTable = &ShndxSection;<br>
+ return ShndxSection;<br>
+ }<br>
case SHT_NOBITS:<br>
return Obj.addSection<Section>(Data);<br>
default:<br>
@@ -783,6 +855,12 @@ template <class ELFT> void ELFBuilder<EL<br>
Sec.Index = Index++;<br>
}<br>
<br>
+ // If a section index table exists we'll need to initialize it before we<br>
+ // initialize the symbol table because the symbol table might need to<br>
+ // reference it.<br>
+ if (Obj.SectionIndexTable)<br>
+ Obj.SectionIndexTable->initialize(Obj.sections());<br>
+<br>
// Now that all of the sections have been added we can fill out some extra<br>
// details about symbol tables. We need the symbol table filled out before<br>
// any relocations.<br>
@@ -825,9 +903,13 @@ template <class ELFT> void ELFBuilder<EL<br>
readSectionHeaders();<br>
readProgramHeaders();<br>
<br>
+ uint32_t ShstrIndex = Ehdr.e_shstrndx;<br>
+ if (ShstrIndex == SHN_XINDEX)<br>
+ ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link;<br>
+<br>
Obj.SectionNames =<br>
Obj.sections().template getSectionOfType<StringTableSection>(<br>
- Ehdr.e_shstrndx,<br>
+ ShstrIndex,<br>
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +<br>
" in elf header " + " is invalid",<br>
"e_shstrndx field value " + Twine(Ehdr.e_shstrndx) +<br>
@@ -893,8 +975,27 @@ template <class ELFT> void ELFWriter<ELF<br>
Ehdr.e_shentsize = sizeof(Elf_Shdr);<br>
if (WriteSectionHeaders) {<br>
Ehdr.e_shoff = Obj.SHOffset;<br>
- Ehdr.e_shnum = size(Obj.sections()) + 1;<br>
- Ehdr.e_shstrndx = Obj.SectionNames->Index;<br>
+ // """<br>
+ // If the number of sections is greater than or equal to<br>
+ // SHN_LORESERVE (0xff00), this member has the value zero and the actual<br>
+ // number of section header table entries is contained in the sh_size field<br>
+ // of the section header at index 0.<br>
+ // """<br>
+ auto Shnum = size(Obj.sections()) + 1;<br>
+ if (Shnum >= SHN_LORESERVE)<br>
+ Ehdr.e_shnum = 0;<br>
+ else<br>
+ Ehdr.e_shnum = Shnum;<br>
+ // """<br>
+ // If the section name string table section index is greater than or equal<br>
+ // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)<br>
+ // and the actual index of the section name string table section is<br>
+ // contained in the sh_link field of the section header at index 0.<br>
+ // """<br>
+ if (Obj.SectionNames->Index >= SHN_LORESERVE)<br>
+ Ehdr.e_shstrndx = SHN_XINDEX;<br>
+ else<br>
+ Ehdr.e_shstrndx = Obj.SectionNames->Index;<br>
} else {<br>
Ehdr.e_shoff = 0;<br>
Ehdr.e_shnum = 0;<br>
@@ -917,8 +1018,17 @@ template <class ELFT> void ELFWriter<ELF<br>
Shdr.sh_flags = 0;<br>
Shdr.sh_addr = 0;<br>
Shdr.sh_offset = 0;<br>
- Shdr.sh_size = 0;<br>
- Shdr.sh_link = 0;<br>
+ // See writeEhdr for why we do this.<br>
+ uint64_t Shnum = size(Obj.sections()) + 1;<br>
+ if (Shnum >= SHN_LORESERVE)<br>
+ Shdr.sh_size = Shnum;<br>
+ else<br>
+ Shdr.sh_size = 0;<br>
+ // See writeEhdr for why we do this.<br>
+ if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)<br>
+ Shdr.sh_link = Obj.SectionNames->Index;<br>
+ else<br>
+ Shdr.sh_link = 0;<br>
Shdr.sh_info = 0;<br>
Shdr.sh_addralign = 0;<br>
Shdr.sh_entsize = 0;<br>
@@ -946,9 +1056,10 @@ void Object::removeSections(std::functio<br>
});<br>
if (SymbolTable != nullptr && ToRemove(*SymbolTable))<br>
SymbolTable = nullptr;<br>
- if (SectionNames != nullptr && ToRemove(*SectionNames)) {<br>
+ if (SectionNames != nullptr && ToRemove(*SectionNames))<br>
SectionNames = nullptr;<br>
- }<br>
+ if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))<br>
+ SectionIndexTable = nullptr;<br>
// Now make sure there are no remaining references to the sections that will<br>
// be removed. Sometimes it is impossible to remove a reference so we emit<br>
// an error here instead.<br>
@@ -1109,16 +1220,59 @@ template <class ELFT> void ELFWriter<ELF<br>
error("Cannot write section header table because section header string "<br>
"table was removed.");<br>
<br>
- // Make sure we add the names of all the sections.<br>
+ Obj.sortSections();<br>
+<br>
+ // We need to assign indexes before we perform layout because we need to know<br>
+ // if we need large indexes or not. We can assign indexes first and check as<br>
+ // we go to see if we will actully need large indexes.<br>
+ bool NeedsLargeIndexes = false;<br>
+ if (size(Obj.sections()) >= SHN_LORESERVE) {<br>
+ auto Sections = Obj.sections();<br>
+ NeedsLargeIndexes =<br>
+ std::any_of(Sections.begin() + SHN_LORESERVE, Sections.end(),<br>
+ [](const SectionBase &Sec) { return Sec.HasSymbol; });<br>
+ // TODO: handle case where only one section needs the large index table but<br>
+ // only needs it because the large index table hasn't been removed yet.<br>
+ }<br>
+<br>
+ if (NeedsLargeIndexes) {<br>
+ // This means we definitely need to have a section index table but if we<br>
+ // already have one then we should use it instead of making a new one.<br>
+ if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {<br>
+ // Addition of a section to the end does not invalidate the indexes of<br>
+ // other sections and assigns the correct index to the new section.<br>
+ auto &Shndx = Obj.addSection<SectionIndexSection>();<br>
+ Obj.SymbolTable->setShndxTable(&Shndx);<br>
+ Shndx.setSymTab(Obj.SymbolTable);<br>
+ }<br>
+ } else {<br>
+ // Since we don't need SectionIndexTable we should remove it and all<br>
+ // references to it.<br>
+ if (Obj.SectionIndexTable != nullptr) {<br>
+ Obj.removeSections([this](const SectionBase &Sec) {<br>
+ return &Sec == Obj.SectionIndexTable;<br>
+ });<br>
+ }<br>
+ }<br>
+<br>
+ // Make sure we add the names of all the sections. Importantly this must be<br>
+ // done after we decide to add or remove SectionIndexes.<br>
if (Obj.SectionNames != nullptr)<br>
for (const auto &Section : Obj.sections()) {<br>
Obj.SectionNames->addString(Section.Name);<br>
}<br>
- // Make sure we add the names of all the symbols.<br>
+<br>
+ // Before we can prepare for layout the indexes need to be finalized.<br>
+ uint64_t Index = 0;<br>
+ for (auto &Sec : Obj.sections())<br>
+ Sec.Index = Index++;<br>
+<br>
+ // The symbol table does not update all other sections on update. For<br>
+ // instance, symbol names are not added as new symbols are added. This means<br>
+ // that some sections, like .strtab, don't yet have their final size.<br>
if (Obj.SymbolTable != nullptr)<br>
- Obj.SymbolTable->addSymbolNames();<br>
+ Obj.SymbolTable->prepareForLayout();<br>
<br>
- Obj.sortSections();<br>
assignOffsets();<br>
<br>
// Finalize SectionNames first so that we can assign name indexes.<br>
<br>
Modified: llvm/trunk/tools/llvm-objcopy/Object.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.h?rev=337204&r1=337203&r2=337204&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/Object.h?rev=337204&r1=337203&r2=337204&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-objcopy/Object.h (original)<br>
+++ llvm/trunk/tools/llvm-objcopy/Object.h Mon Jul 16 12:48:52 2018<br>
@@ -37,6 +37,7 @@ class RelocationSection;<br>
class DynamicRelocationSection;<br>
class GnuDebugLinkSection;<br>
class GroupSection;<br>
+class SectionIndexSection;<br>
class Segment;<br>
class Object;<br>
struct Symbol;<br>
@@ -54,10 +55,10 @@ public:<br>
iterator begin() { return iterator(Sections.data()); }<br>
iterator end() { return iterator(Sections.data() + Sections.size()); }<br>
<br>
- SectionBase *getSection(uint16_t Index, Twine ErrMsg);<br>
+ SectionBase *getSection(uint32_t Index, Twine ErrMsg);<br>
<br>
template <class T><br>
- T *getSectionOfType(uint16_t Index, Twine IndexErrMsg, Twine TypeErrMsg);<br>
+ T *getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg);<br>
};<br>
<br>
enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };<br>
@@ -74,6 +75,7 @@ public:<br>
virtual void visit(const DynamicRelocationSection &Sec) = 0;<br>
virtual void visit(const GnuDebugLinkSection &Sec) = 0;<br>
virtual void visit(const GroupSection &Sec) = 0;<br>
+ virtual void visit(const SectionIndexSection &Sec) = 0;<br>
};<br>
<br>
class SectionWriter : public SectionVisitor {<br>
@@ -91,6 +93,7 @@ public:<br>
virtual void visit(const RelocationSection &Sec) override = 0;<br>
virtual void visit(const GnuDebugLinkSection &Sec) override = 0;<br>
virtual void visit(const GroupSection &Sec) override = 0;<br>
+ virtual void visit(const SectionIndexSection &Sec) override = 0;<br>
<br>
explicit SectionWriter(Buffer &Buf) : Out(Buf) {}<br>
};<br>
@@ -107,6 +110,7 @@ public:<br>
void visit(const RelocationSection &Sec) override;<br>
void visit(const GnuDebugLinkSection &Sec) override;<br>
void visit(const GroupSection &Sec) override;<br>
+ void visit(const SectionIndexSection &Sec) override;<br>
<br>
explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {}<br>
};<br>
@@ -123,6 +127,7 @@ public:<br>
void visit(const RelocationSection &Sec) override;<br>
void visit(const GnuDebugLinkSection &Sec) override;<br>
void visit(const GroupSection &Sec) override;<br>
+ void visit(const SectionIndexSection &Sec) override;<br>
<br>
explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {}<br>
};<br>
@@ -230,8 +235,9 @@ public:<br>
StringRef Name;<br>
Segment *ParentSegment = nullptr;<br>
uint64_t HeaderOffset;<br>
- uint64_t OriginalOffset;<br>
+ uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();<br>
uint32_t Index;<br>
+ bool HasSymbol = false;<br>
<br>
uint64_t Addr = 0;<br>
uint64_t Align = 1;<br>
@@ -371,6 +377,7 @@ enum SymbolShndxType {<br>
SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,<br>
SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,<br>
SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,<br>
+ SYMBOL_XINDEX = ELF::SHN_XINDEX,<br>
};<br>
<br>
struct Symbol {<br>
@@ -389,6 +396,32 @@ struct Symbol {<br>
uint16_t getShndx() const;<br>
};<br>
<br>
+class SectionIndexSection : public SectionBase {<br>
+ MAKE_SEC_WRITER_FRIEND<br>
+<br>
+private:<br>
+ std::vector<uint32_t> Indexes;<br>
+ SymbolTableSection *Symbols = nullptr;<br>
+<br>
+public:<br>
+ virtual ~SectionIndexSection() {}<br>
+ void addIndex(uint32_t Index) {<br>
+ Indexes.push_back(Index);<br>
+ Size += 4;<br>
+ }<br>
+ void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }<br>
+ void initialize(SectionTableRef SecTable) override;<br>
+ void finalize() override;<br>
+ void accept(SectionVisitor &Visitor) const override;<br>
+<br>
+ SectionIndexSection() {<br>
+ Name = ".symtab_shndx";<br>
+ Align = 4;<br>
+ EntrySize = 4;<br>
+ Type = ELF::SHT_SYMTAB_SHNDX;<br>
+ }<br>
+};<br>
+<br>
class SymbolTableSection : public SectionBase {<br>
MAKE_SEC_WRITER_FRIEND<br>
<br>
@@ -398,6 +431,7 @@ class SymbolTableSection : public Sectio<br>
protected:<br>
std::vector<std::unique_ptr<Symbol>> Symbols;<br>
StringTableSection *SymbolNames = nullptr;<br>
+ SectionIndexSection *SectionIndexTable = nullptr;<br>
<br>
using SymPtr = std::unique_ptr<Symbol>;<br>
<br>
@@ -405,9 +439,13 @@ public:<br>
void addSymbol(StringRef Name, uint8_t Bind, uint8_t Type,<br>
SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility,<br>
uint16_t Shndx, uint64_t Sz);<br>
- void addSymbolNames();<br>
+ void prepareForLayout();<br>
// An 'empty' symbol table still contains a null symbol.<br>
bool empty() const { return Symbols.size() == 1; }<br>
+ void setShndxTable(SectionIndexSection *ShndxTable) {<br>
+ SectionIndexTable = ShndxTable;<br>
+ }<br>
+ const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }<br>
const SectionBase *getStrTab() const { return SymbolNames; }<br>
const Symbol *getSymbolByIndex(uint32_t Index) const;<br>
Symbol *getSymbolByIndex(uint32_t Index);<br>
@@ -589,6 +627,7 @@ private:<br>
using Elf_Addr = typename ELFT::Addr;<br>
using Elf_Shdr = typename ELFT::Shdr;<br>
using Elf_Ehdr = typename ELFT::Ehdr;<br>
+ using Elf_Word = typename ELFT::Word;<br>
<br>
const ELFFile<ELFT> &ElfFile;<br>
Object &Obj;<br>
@@ -652,6 +691,7 @@ public:<br>
<br>
StringTableSection *SectionNames = nullptr;<br>
SymbolTableSection *SymbolTable = nullptr;<br>
+ SectionIndexSection *SectionIndexTable = nullptr;<br>
<br>
void sortSections();<br>
SectionTableRef sections() { return SectionTableRef(Sections); }<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>