[lld] r337363 - [ELF] - Do not produce broken output when amount of sections is > ~65k

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 18 01:44:38 PDT 2018


Author: grimar
Date: Wed Jul 18 01:44:38 2018
New Revision: 337363

URL: http://llvm.org/viewvc/llvm-project?rev=337363&view=rev
Log:
[ELF] - Do not produce broken output when amount of sections is > ~65k

This is a part of ttps://bugs.llvm.org//show_bug.cgi?id=38119

We produce broken ELF header now when the number of output sections is >= SHN_LORESERVE (0xff00).

ELF spec says (http://www.sco.com/developers/gabi/2003-12-17/ch4.eheader.html):

e_shnum:
If the number of sections is greater than or equal to SHN_LORESERVE (0xff00), this member has the value zero
and the actual number of section header table entries is contained in the sh_size field of the section header at index 0.
(Otherwise, the sh_size member of the initial entry contains 0.)

e_shstrndx
If the section name string table section index is greater than or equal to SHN_LORESERVE (0xff00), this member has the
value SHN_XINDEX (0xffff) and the actual index of the section name string table section is contained in the sh_link field of
the section header at index 0. (Otherwise, the sh_link member of the initial entry contains 0.)

We did not set these fields correctly earlier. The patch fixes the issue.

Differential revision: https://reviews.llvm.org/D49371

Added:
    lld/trunk/test/ELF/relocatable-many-sections.s
Modified:
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=337363&r1=337362&r2=337363&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Jul 18 01:44:38 2018
@@ -2242,8 +2242,6 @@ template <class ELFT> void Writer<ELFT>:
   EHdr->e_ehsize = sizeof(Elf_Ehdr);
   EHdr->e_phnum = Phdrs.size();
   EHdr->e_shentsize = sizeof(Elf_Shdr);
-  EHdr->e_shnum = OutputSections.size() + 1;
-  EHdr->e_shstrndx = InX::ShStrTab->getParent()->SectionIndex;
 
   if (!Config->Relocatable) {
     EHdr->e_phoff = sizeof(Elf_Ehdr);
@@ -2264,8 +2262,30 @@ template <class ELFT> void Writer<ELFT>:
     ++HBuf;
   }
 
-  // Write the section header table. Note that the first table entry is null.
+  // Write the section header table.
+  //
+  // The ELF header can only store numbers up to SHN_LORESERVE in the e_shnum
+  // and e_shstrndx fields. When the value of one of these fields exceeds
+  // SHN_LORESERVE ELF requires us to put sentinel values in the ELF header and
+  // use fields in the section header at index 0 to store
+  // the value. The sentinel values and fields are:
+  // e_shnum = 0, SHdrs[0].sh_size = number of sections.
+  // e_shstrndx = SHN_XINDEX, SHdrs[0].sh_link = .shstrtab section index.
   auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
+  size_t Num = OutputSections.size() + 1;
+  if (Num >= SHN_LORESERVE)
+    SHdrs->sh_size = Num;
+  else
+    EHdr->e_shnum = Num;
+
+  uint32_t StrTabIndex = InX::ShStrTab->getParent()->SectionIndex;
+  if (StrTabIndex >= SHN_LORESERVE) {
+    SHdrs->sh_link = StrTabIndex;
+    EHdr->e_shstrndx = SHN_XINDEX;
+  } else {
+    EHdr->e_shstrndx = StrTabIndex;
+  }
+
   for (OutputSection *Sec : OutputSections)
     Sec->writeHeaderTo<ELFT>(++SHdrs);
 }

Added: lld/trunk/test/ELF/relocatable-many-sections.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/relocatable-many-sections.s?rev=337363&view=auto
==============================================================================
--- lld/trunk/test/ELF/relocatable-many-sections.s (added)
+++ lld/trunk/test/ELF/relocatable-many-sections.s Wed Jul 18 01:44:38 2018
@@ -0,0 +1,85 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o
+# RUN: ld.lld -r %t.o -o %t
+# RUN: llvm-readobj -file-headers %t | FileCheck %s
+
+## Check we are able to emit a valid ELF header when
+## sections amount is greater than SHN_LORESERVE.
+# CHECK:      ElfHeader {
+# CHECK:        SectionHeaderCount: 0 (65541)
+# CHECK-NEXT:   StringTableSectionIndex: 65535 (65539)
+
+.macro gen_sections4 x
+  .section a\x
+  .section b\x
+  .section c\x
+  .section d\x
+.endm
+
+.macro gen_sections8 x
+  gen_sections4 a\x
+  gen_sections4 b\x
+.endm
+
+.macro gen_sections16 x
+  gen_sections8 a\x
+  gen_sections8 b\x
+.endm
+
+.macro gen_sections32 x
+  gen_sections16 a\x
+  gen_sections16 b\x
+.endm
+
+.macro gen_sections64 x
+  gen_sections32 a\x
+  gen_sections32 b\x
+.endm
+
+.macro gen_sections128 x
+  gen_sections64 a\x
+  gen_sections64 b\x
+.endm
+
+.macro gen_sections256 x
+  gen_sections128 a\x
+  gen_sections128 b\x
+.endm
+
+.macro gen_sections512 x
+  gen_sections256 a\x
+  gen_sections256 b\x
+.endm
+
+.macro gen_sections1024 x
+  gen_sections512 a\x
+  gen_sections512 b\x
+.endm
+
+.macro gen_sections2048 x
+  gen_sections1024 a\x
+  gen_sections1024 b\x
+.endm
+
+.macro gen_sections4096 x
+  gen_sections2048 a\x
+  gen_sections2048 b\x
+.endm
+
+.macro gen_sections8192 x
+  gen_sections4096 a\x
+  gen_sections4096 b\x
+.endm
+
+.macro gen_sections16384 x
+  gen_sections8192 a\x
+  gen_sections8192 b\x
+.endm
+
+gen_sections16384 a
+gen_sections16384 b
+gen_sections16384 c
+gen_sections16384 d
+
+.global _start
+_start:




More information about the llvm-commits mailing list