[lld] r299592 - Use uint64_t to keep file size even on 32-bit machines.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 5 14:37:09 PDT 2017


Author: ruiu
Date: Wed Apr  5 16:37:09 2017
New Revision: 299592

URL: http://llvm.org/viewvc/llvm-project?rev=299592&view=rev
Log:
Use uint64_t to keep file size even on 32-bit machines.

If an output file is too large for 32-bit, we should report an error.

Added:
    lld/trunk/test/ELF/linkerscript/output-too-large.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=299592&r1=299591&r2=299592&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Apr  5 16:37:09 2017
@@ -38,7 +38,6 @@ namespace {
 // The writer writes a SymbolTable result to a file.
 template <class ELFT> class Writer {
 public:
-  typedef typename ELFT::uint uintX_t;
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::Ehdr Elf_Ehdr;
   typedef typename ELFT::Phdr Elf_Phdr;
@@ -82,13 +81,13 @@ private:
   void addRelIpltSymbols();
   void addStartEndSymbols();
   void addStartStopSymbols(OutputSection *Sec);
-  uintX_t getEntryAddr();
+  uint64_t getEntryAddr();
   OutputSection *findSection(StringRef Name);
 
   std::vector<PhdrEntry> Phdrs;
 
-  uintX_t FileSize;
-  uintX_t SectionHeaderOff;
+  uint64_t FileSize;
+  uint64_t SectionHeaderOff;
   bool AllocateHeader = true;
 };
 } // anonymous namespace
@@ -143,24 +142,21 @@ template <class ELFT> void Writer<ELFT>:
       return false;
     if (!P.First)
       return true;
-    uintX_t Size = P.Last->Addr + P.Last->Size - P.First->Addr;
+    uint64_t Size = P.Last->Addr + P.Last->Size - P.First->Addr;
     return Size == 0;
   });
   Phdrs.erase(I, Phdrs.end());
 }
 
-template <class ELFT>
-static typename ELFT::uint getOutFlags(InputSectionBase *S) {
-  return S->Flags & ~(typename ELFT::uint)(SHF_GROUP | SHF_COMPRESSED);
+static uint64_t getOutputFlags(InputSectionBase *S) {
+  return S->Flags & ~(uint64_t)(SHF_GROUP | SHF_COMPRESSED);
 }
 
 // This function scans over the input sections and creates mergeable
 // synthetic sections. It removes MergeInputSections from array and
 // adds new synthetic ones. Each synthetic section is added to the
 // location of the first input section it replaces.
-template <class ELFT> static void combineMergableSections() {
-  typedef typename ELFT::uint uintX_t;
-
+static void combineMergableSections() {
   std::vector<MergeSyntheticSection *> MergeSections;
   for (InputSectionBase *&S : InputSections) {
     MergeInputSection *MS = dyn_cast<MergeInputSection>(S);
@@ -173,8 +169,8 @@ template <class ELFT> static void combin
       continue;
 
     StringRef OutsecName = getOutputSectionName(MS->Name);
-    uintX_t Flags = getOutFlags<ELFT>(MS);
-    uint32_t Alignment = std::max<uintX_t>(MS->Alignment, MS->Entsize);
+    uint64_t Flags = getOutputFlags(MS);
+    uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
 
     auto I =
         llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) {
@@ -216,7 +212,7 @@ template <class ELFT> void Writer<ELFT>:
   // Create linker-synthesized sections such as .got or .plt.
   // Such sections are of type input section.
   createSyntheticSections();
-  combineMergableSections<ELFT>();
+  combineMergableSections();
 
   if (!Config->Relocatable)
     combineEhFrameSections<ELFT>();
@@ -334,7 +330,7 @@ template <class ELFT> void Writer<ELFT>:
   Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC);
   Out::ElfHeader->Size = sizeof(Elf_Ehdr);
   Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC);
-  Out::ProgramHeaders->updateAlignment(sizeof(uintX_t));
+  Out::ProgramHeaders->updateAlignment(Config->Wordsize);
 
   if (needsInterpSection<ELFT>()) {
     In<ELFT>::Interp = createInterpSection();
@@ -864,13 +860,13 @@ template <class ELFT> void Writer<ELFT>:
 
 // Sort input sections by section name suffixes for
 // __attribute__((init_priority(N))).
-template <class ELFT> static void sortInitFini(OutputSection *S) {
+static void sortInitFini(OutputSection *S) {
   if (S)
     reinterpret_cast<OutputSection *>(S)->sortInitFini();
 }
 
 // Sort input sections by the special rule for .ctors and .dtors.
-template <class ELFT> static void sortCtorsDtors(OutputSection *S) {
+static void sortCtorsDtors(OutputSection *S) {
   if (S)
     reinterpret_cast<OutputSection *>(S)->sortCtorsDtors();
 }
@@ -935,10 +931,10 @@ template <class ELFT> void Writer<ELFT>:
       Factory.addInputSec(IS, getOutputSectionName(IS->Name));
 
   sortBySymbolsOrder<ELFT>(OutputSections);
-  sortInitFini<ELFT>(findSection(".init_array"));
-  sortInitFini<ELFT>(findSection(".fini_array"));
-  sortCtorsDtors<ELFT>(findSection(".ctors"));
-  sortCtorsDtors<ELFT>(findSection(".dtors"));
+  sortInitFini(findSection(".init_array"));
+  sortInitFini(findSection(".fini_array"));
+  sortCtorsDtors(findSection(".ctors"));
+  sortCtorsDtors(findSection(".dtors"));
 
   for (OutputSection *Sec : OutputSections)
     Sec->assignOffsets();
@@ -1266,13 +1262,12 @@ static bool needsPtLoad(OutputSection *S
 // linker scripts are designed for creating two PT_LOADs only, one RX and one
 // RW. This means that there is no alignment in the RO to RX transition and we
 // cannot create a PT_LOAD there.
-template <class ELFT>
-static typename ELFT::uint computeFlags(typename ELFT::uint F) {
+static uint64_t computeFlags(uint64_t Flags) {
   if (Config->Omagic)
     return PF_R | PF_W | PF_X;
-  if (Config->SingleRoRx && !(F & PF_W))
-    return F | PF_X;
-  return F;
+  if (Config->SingleRoRx && !(Flags & PF_W))
+    return Flags | PF_X;
+  return Flags;
 }
 
 // Decide which program headers to create and which sections to include in each
@@ -1292,7 +1287,7 @@ template <class ELFT> std::vector<PhdrEn
     AddHdr(PT_INTERP, Sec->getPhdrFlags())->add(Sec);
 
   // Add the first PT_LOAD segment for regular output sections.
-  uintX_t Flags = computeFlags<ELFT>(PF_R);
+  uint64_t Flags = computeFlags(PF_R);
   PhdrEntry *Load = AddHdr(PT_LOAD, Flags);
   for (OutputSection *Sec : OutputSections) {
     if (!(Sec->Flags & SHF_ALLOC))
@@ -1305,7 +1300,7 @@ template <class ELFT> std::vector<PhdrEn
     // Therefore, we need to create a new phdr when the next section has
     // different flags or is loaded at a discontiguous address using AT linker
     // script command.
-    uintX_t NewFlags = computeFlags<ELFT>(Sec->getPhdrFlags());
+    uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
     if (Script->hasLMA(Sec->Name) || Flags != NewFlags) {
       Load = AddHdr(PT_LOAD, NewFlags);
       Flags = NewFlags;
@@ -1480,14 +1475,16 @@ template <class ELFT> void Writer<ELFT>:
 
 // Assign VAs (addresses at run-time) to output sections.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
-  uintX_t VA = Config->ImageBase;
+  uint64_t VA = Config->ImageBase;
+  uint64_t ThreadBssOffset = 0;
+
   if (AllocateHeader)
     VA += getHeaderSize();
-  uintX_t ThreadBssOffset = 0;
+
   for (OutputSection *Sec : OutputSections) {
     uint32_t Alignment = Sec->Alignment;
     if (Sec->PageAlign)
-      Alignment = std::max<uintX_t>(Alignment, Config->MaxPageSize);
+      Alignment = std::max<uint32_t>(Alignment, Config->MaxPageSize);
 
     auto I = Config->SectionStartMap.find(Sec->Name);
     if (I != Config->SectionStartMap.end())
@@ -1499,7 +1496,7 @@ template <class ELFT> void Writer<ELFT>:
       Sec->Addr = VA;
       VA += Sec->Size;
     } else if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS) {
-      uintX_t TVA = VA + ThreadBssOffset;
+      uint64_t TVA = VA + ThreadBssOffset;
       TVA = alignTo(TVA, Alignment);
       Sec->Addr = TVA;
       ThreadBssOffset = TVA - VA + Sec->Size;
@@ -1511,8 +1508,7 @@ template <class ELFT> void Writer<ELFT>:
 // its new file offset. The file offset must be the same with its
 // virtual address (modulo the page size) so that the loader can load
 // executables without any address adjustment.
-template <class ELFT, class uintX_t>
-static uintX_t getFileAlignment(uintX_t Off, OutputSection *Sec) {
+static uint64_t getFileAlignment(uint64_t Off, OutputSection *Sec) {
   OutputSection *First = Sec->FirstInPtLoad;
   // If the section is not in a PT_LOAD, we just have to align it.
   if (!First)
@@ -1528,36 +1524,35 @@ static uintX_t getFileAlignment(uintX_t
   return First->Offset + Sec->Addr - First->Addr;
 }
 
-template <class ELFT, class uintX_t>
-static uintX_t setOffset(OutputSection *Sec, uintX_t Off) {
+static uint64_t setOffset(OutputSection *Sec, uint64_t Off) {
   if (Sec->Type == SHT_NOBITS) {
     Sec->Offset = Off;
     return Off;
   }
 
-  Off = getFileAlignment<ELFT>(Off, Sec);
+  Off = getFileAlignment(Off, Sec);
   Sec->Offset = Off;
   return Off + Sec->Size;
 }
 
 template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
-  uintX_t Off = 0;
+  uint64_t Off = 0;
   for (OutputSection *Sec : OutputSections)
     if (Sec->Flags & SHF_ALLOC)
-      Off = setOffset<ELFT>(Sec, Off);
-  FileSize = alignTo(Off, sizeof(uintX_t));
+      Off = setOffset(Sec, Off);
+  FileSize = alignTo(Off, Config->Wordsize);
 }
 
 // Assign file offsets to output sections.
 template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
-  uintX_t Off = 0;
-  Off = setOffset<ELFT>(Out::ElfHeader, Off);
-  Off = setOffset<ELFT>(Out::ProgramHeaders, Off);
+  uint64_t Off = 0;
+  Off = setOffset(Out::ElfHeader, Off);
+  Off = setOffset(Out::ProgramHeaders, Off);
 
   for (OutputSection *Sec : OutputSections)
-    Off = setOffset<ELFT>(Sec, Off);
+    Off = setOffset(Sec, Off);
 
-  SectionHeaderOff = alignTo(Off, sizeof(uintX_t));
+  SectionHeaderOff = alignTo(Off, Config->Wordsize);
   FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
 }
 
@@ -1604,7 +1599,7 @@ template <class ELFT> void Writer<ELFT>:
 // 3. the value of the symbol start, if present;
 // 4. the address of the first byte of the .text section, if present;
 // 5. the address 0.
-template <class ELFT> typename ELFT::uint Writer<ELFT>::getEntryAddr() {
+template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() {
   // Case 1, 2 or 3. As a special case, if the symbol is actually
   // a number, we'll use that number as an address.
   if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Entry))
@@ -1683,11 +1678,11 @@ template <class ELFT> void Writer<ELFT>:
     if (!ElfSym::MipsGp->Value) {
       // Find GP-relative section with the lowest address
       // and use this address to calculate default _gp value.
-      uintX_t Gp = -1;
+      uint64_t Gp = -1;
       for (const OutputSection *OS : OutputSections)
         if ((OS->Flags & SHF_MIPS_GPREL) && OS->Addr < Gp)
           Gp = OS->Addr;
-      if (Gp != (uintX_t)-1)
+      if (Gp != (uint64_t)-1)
         ElfSym::MipsGp->Value = Gp + 0x7ff0;
     }
   }
@@ -1749,6 +1744,11 @@ template <class ELFT> void Writer<ELFT>:
 
 // Open a result file.
 template <class ELFT> void Writer<ELFT>::openFile() {
+  if (!Config->Is64 && FileSize > UINT32_MAX) {
+    error("output file too large: " + Twine(FileSize) + " bytes");
+    return;
+  }
+
   unlinkAsync(Config->OutputFile);
   ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
       FileOutputBuffer::create(Config->OutputFile, FileSize,

Added: lld/trunk/test/ELF/linkerscript/output-too-large.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/output-too-large.s?rev=299592&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/output-too-large.s (added)
+++ lld/trunk/test/ELF/linkerscript/output-too-large.s Wed Apr  5 16:37:09 2017
@@ -0,0 +1,8 @@
+# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+# RUN: echo "SECTIONS { .text : { . = 0xffffffff; *(.text*); } }" > %t.script
+# RUN: not ld.lld --script %t.script %t.o -o %t 2>&1 | FileCheck %s
+# CHECK: error: output file too large
+
+.global _start
+_start:
+  nop




More information about the llvm-commits mailing list