[lld] r221571 - [ELF] Support --no-align-segments.

Shankar Easwaran shankare at codeaurora.org
Fri Nov 7 19:44:50 PST 2014


Author: shankare
Date: Fri Nov  7 21:44:49 2014
New Revision: 221571

URL: http://llvm.org/viewvc/llvm-project?rev=221571&view=rev
Log:
[ELF] Support --no-align-segments.

lld generates an ELF by adhering to the ELF spec by aligning vma/fileoffset to a
page boundary, but this becomes an issue when dealing with large pages. This
adds support so that lld generated executables adheres to the ELF spec with the
rule vma % p_align = offset % p_align.

This is supported by the flag --no-align-segments.

This could be the default in few targets like X86_64 to save space on disk.

Added:
    lld/trunk/test/elf/X86_64/noalignsegments.test
Modified:
    lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
    lld/trunk/lib/Driver/GnuLdDriver.cpp
    lld/trunk/lib/Driver/GnuLdOptions.td
    lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
    lld/trunk/test/elf/phdr.test

Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=221571&r1=221570&r2=221571&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Fri Nov  7 21:44:49 2014
@@ -278,6 +278,10 @@ public:
   bool demangleSymbols() const { return _demangle; }
   void setDemangleSymbols(bool d) { _demangle = d; }
 
+  /// \brief Align segments.
+  bool alignSegments() const { return _alignSegments; }
+  void setAlignSegments(bool align) { _alignSegments = align; }
+
 private:
   ELFLinkingContext() LLVM_DELETED_FUNCTION;
 
@@ -303,6 +307,7 @@ protected:
   bool _noAllowDynamicLibraries;
   bool _mergeRODataToTextSegment;
   bool _demangle;
+  bool _alignSegments;
   OutputMagic _outputMagic;
   StringRefVector _inputSearchPaths;
   std::unique_ptr<Writer> _writer;

Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=221571&r1=221570&r2=221571&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Fri Nov  7 21:44:49 2014
@@ -555,6 +555,10 @@ bool GnuLdDriver::parse(int argc, const
       ctx->setCreateSeparateROSegment();
       break;
 
+    case OPT_no_align_segments:
+      ctx->setAlignSegments(false);
+      break;
+
     default:
       break;
     } // end switch on option ID

Modified: lld/trunk/lib/Driver/GnuLdOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdOptions.td?rev=221571&r1=221570&r2=221571&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdOptions.td (original)
+++ lld/trunk/lib/Driver/GnuLdOptions.td Fri Nov  7 21:44:49 2014
@@ -221,6 +221,9 @@ def rosegment: Flag<["--"], "rosegment">
 def z : Separate<["-"], "z">,
      HelpText<"Linker Option extensions">,
      Group<grp_customopts>;
+def no_align_segments: Flag<["--"], "no-align-segments">,
+     HelpText<"Don't align ELF segments(virtualaddress/fileoffset) to page boundaries">,
+     Group<grp_customopts>;
 
 //===----------------------------------------------------------------------===//
 /// Symbol options

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=221571&r1=221570&r2=221571&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Fri Nov  7 21:44:49 2014
@@ -62,7 +62,8 @@ ELFLinkingContext::ELFLinkingContext(
       _mergeCommonStrings(false), _runLayoutPass(true),
       _useShlibUndefines(true), _dynamicLinkerArg(false),
       _noAllowDynamicLibraries(false), _mergeRODataToTextSegment(true),
-      _demangle(true), _outputMagic(OutputMagic::DEFAULT), _sysrootPath("") {}
+      _demangle(true), _alignSegments(true), _outputMagic(OutputMagic::DEFAULT),
+      _sysrootPath("") {}
 
 void ELFLinkingContext::addPasses(PassManager &pm) {
   if (_runLayoutPass)

Modified: lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h?rev=221571&r1=221570&r2=221571&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/SegmentChunks.h Fri Nov  7 21:44:49 2014
@@ -399,14 +399,12 @@ void Segment<ELFT>::assignFileOffsets(ui
   uint64_t fileOffset = startOffset;
   uint64_t curSliceFileOffset = fileOffset;
   bool isDataPageAlignedForNMagic = false;
+  bool alignSegments = this->_context.alignSegments();
+  uint64_t p_align = this->_context.getPageSize();
 
   this->setFileOffset(startOffset);
   for (auto &slice : slices()) {
-    // Align to the slice alignment
-    fileOffset = llvm::RoundUpToAlignment(fileOffset, slice->align2());
-
     bool isFirstSection = true;
-
     for (auto section : slice->sections()) {
       // If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
       // to a page boundary
@@ -415,16 +413,25 @@ void Segment<ELFT>::assignFileOffsets(ui
           _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC) {
         // Align to a page only if the output is not
         // OutputMagic::NMAGIC/OutputMagic::OMAGIC
-        fileOffset =
-            llvm::RoundUpToAlignment(fileOffset, this->_context.getPageSize());
-      }
-      if (!isDataPageAlignedForNMagic && needAlign(section)) {
+        if (alignSegments)
+          fileOffset = llvm::RoundUpToAlignment(fileOffset, p_align);
+        else {
+          // Align according to ELF spec.
+          // in p75, http://www.sco.com/developers/devspecs/gabi41.pdf
+          uint64_t padding = 0;
+          uint64_t virtualAddress = slice->virtualAddr();
+          Section<ELFT> *sect = dyn_cast<Section<ELFT>>(section);
+          if (sect && sect->isLoadableSection() &&
+              ((virtualAddress & (p_align - 1)) !=
+               (fileOffset & (p_align - 1))))
+            fileOffset = llvm::RoundUpToAlignment(fileOffset, p_align);
+        }
+      } else if (!isDataPageAlignedForNMagic && needAlign(section)) {
         fileOffset =
             llvm::RoundUpToAlignment(fileOffset, this->_context.getPageSize());
         isDataPageAlignedForNMagic = true;
-      }
-      // Align the section address
-      fileOffset = llvm::RoundUpToAlignment(fileOffset, section->align2());
+      } else
+        fileOffset = llvm::RoundUpToAlignment(fileOffset, section->align2());
 
       if (isFirstSection) {
         slice->setFileOffset(fileOffset);
@@ -460,6 +467,7 @@ template <class ELFT> void Segment<ELFT>
   uint64_t startAddr = addr;
   SegmentSlice<ELFT> *slice = nullptr;
   uint64_t tlsStartAddr = 0;
+  bool alignSegments = this->_context.alignSegments();
 
   for (auto si = _sections.begin(); si != _sections.end(); ++si) {
     // If this is first section in the segment, page align the section start
@@ -467,7 +475,8 @@ template <class ELFT> void Segment<ELFT>
     // only if NMAGIC is set.
     if (isFirstSection) {
       isFirstSection = false;
-      if (_outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
+      if (alignSegments &&
+          _outputMagic != ELFLinkingContext::OutputMagic::NMAGIC &&
           _outputMagic != ELFLinkingContext::OutputMagic::OMAGIC)
         // Align to a page only if the output is not
         // OutputMagic::NMAGIC/OutputMagic::OMAGIC

Added: lld/trunk/test/elf/X86_64/noalignsegments.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/noalignsegments.test?rev=221571&view=auto
==============================================================================
--- lld/trunk/test/elf/X86_64/noalignsegments.test (added)
+++ lld/trunk/test/elf/X86_64/noalignsegments.test Fri Nov  7 21:44:49 2014
@@ -0,0 +1,95 @@
+# Checks that segments are aligned as per ELF spec than aligning each
+# segment fileoffset / virtual address to a page.
+
+# Build executable
+# RUN: yaml2obj -format=elf -docnum 1 %s -o %t.o
+# RUN: lld -flavor gnu -target x86_64 %t.o -o %t.exe -static \
+# RUN: --no-align-segments --noinhibit-exec
+# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s
+#
+#CHECK:    VirtualAddress: 0x400000
+#CHECK:    PhysicalAddress: 0x400000
+#CHECK:    VirtualAddress: 0x400178
+#CHECK:    PhysicalAddress: 0x400178
+
+# object
+---
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  OSABI:           ELFOSABI_GNU
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000010
+    Content:         554889E5B864000000C745FC000000005DC366666666662E0F1F840000000000554889E531C05DC3
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         '64000000'
+  - Name:            .rodata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    AddressAlign:    0x0000000000000004
+    Content:         '64000000'
+  - Name:            .eh_frame
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    AddressAlign:    0x0000000000000008
+    Content:         1400000000000000037A5200017810011B0C070890010000180000001C000000000000001200000000410E108602430D060000001800000038000000000000000800000000410E108602430D06000000
+  - Name:            .rela.eh_frame
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .eh_frame
+    Relocations:
+      - Offset:          0x0000000000000020
+        Symbol:          .text
+        Type:            R_X86_64_PC32
+        Addend:          0
+      - Offset:          0x000000000000003C
+        Symbol:          .text
+        Type:            R_X86_64_PC32
+        Addend:          32
+Symbols:
+  Local:
+    - Name:            .text
+      Type:            STT_SECTION
+      Section:         .text
+    - Name:            .data
+      Type:            STT_SECTION
+      Section:         .data
+    - Name:            .bss
+      Type:            STT_SECTION
+      Section:         .bss
+    - Name:            .eh_frame
+      Type:            STT_SECTION
+      Section:         .eh_frame
+  Global:
+    - Name:            foo
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000020
+      Size:            0x0000000000000008
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Size:            0x0000000000000012
+    - Name:            myval
+      Type:            STT_OBJECT
+      Section:         .bss
+      Size:            0x0000000000000004
+    - Name:            val
+      Type:            STT_OBJECT
+      Section:         .rodata
+      Size:            0x0000000000000004
+...

Modified: lld/trunk/test/elf/phdr.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/phdr.test?rev=221571&r1=221570&r2=221571&view=diff
==============================================================================
--- lld/trunk/test/elf/phdr.test (original)
+++ lld/trunk/test/elf/phdr.test Fri Nov  7 21:44:49 2014
@@ -59,7 +59,7 @@ I386-NEXT:     Alignment: 4096
 I386-NEXT:   }
 I386-NEXT:   ProgramHeader {
 I386-NEXT:     Type: PT_LOAD (0x1)
-I386-NEXT:     Offset: 0x4000
+I386-NEXT:     Offset: 0x2000
 I386-NEXT:     VirtualAddress: 0x4000
 I386-NEXT:     PhysicalAddress: 0x4000
 I386-NEXT:     FileSize: 4





More information about the llvm-commits mailing list