[lld] r274342 - [ELF] Fix first PT_LOAD segment VA calculation, when linker script is used

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 1 03:27:36 PDT 2016


Author: evgeny777
Date: Fri Jul  1 05:27:36 2016
New Revision: 274342

URL: http://llvm.org/viewvc/llvm-project?rev=274342&view=rev
Log:
[ELF] Fix first PT_LOAD segment VA calculation, when linker script is used

Added:
    lld/trunk/test/ELF/linkerscript-phdr-check.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=274342&r1=274341&r2=274342&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Jul  1 05:27:36 2016
@@ -21,6 +21,7 @@
 #include "ScriptParser.h"
 #include "Strings.h"
 #include "SymbolTable.h"
+#include "Target.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ELF.h"
 #include "llvm/Support/FileSystem.h"
@@ -220,7 +221,8 @@ void LinkerScript<ELFT>::assignAddresses
   }
 
   // Assign addresses as instructed by linker script SECTIONS sub-commands.
-  Dot = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
+  Dot = Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();  
+  uintX_t MinVA = std::numeric_limits<uintX_t>::max();
   uintX_t ThreadBssOffset = 0;
 
   for (SectionsCommand &Cmd : Opt.Commands) {
@@ -247,11 +249,20 @@ void LinkerScript<ELFT>::assignAddresses
       if (Sec->getFlags() & SHF_ALLOC) {
         Dot = alignTo(Dot, Sec->getAlignment());
         Sec->setVA(Dot);
+        MinVA = std::min(MinVA, Dot);        
         Dot += Sec->getSize();
         continue;
       }
     }
   }
+  
+  // ELF and Program headers need to be right before the first section in memory.
+  // Set their addresses accordingly.
+  MinVA = alignDown(MinVA - Out<ELFT>::ElfHeader->getSize() -
+                        Out<ELFT>::ProgramHeaders->getSize(),
+                    Target->PageSize);
+  Out<ELFT>::ElfHeader->setVA(MinVA);
+  Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA);
 }
 
 template <class ELFT>

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=274342&r1=274341&r2=274342&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Jul  1 05:27:36 2016
@@ -1131,11 +1131,9 @@ template <class ELFT> void Writer<ELFT>:
 // list, but have them to simplify the code.
 template <class ELFT> void Writer<ELFT>::fixHeaders() {
   uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Target->getVAStart();
-  Out<ELFT>::ElfHeader->setVA(BaseVA);
-  Out<ELFT>::ElfHeader->setFileOffset(0);
+  Out<ELFT>::ElfHeader->setVA(BaseVA);  
   uintX_t Off = Out<ELFT>::ElfHeader->getSize();
-  Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
-  Out<ELFT>::ProgramHeaders->setFileOffset(Off);
+  Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);  
 }
 
 // Assign VAs (addresses at run-time) to output sections.
@@ -1183,19 +1181,24 @@ static uintX_t getFileAlignment(uintX_t
 
 // Assign file offsets to output sections.
 template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
-  uintX_t Off =
-      Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
+  uintX_t Off = 0;
 
-  for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+  auto Set = [&](OutputSectionBase<ELFT> *Sec) {
     if (Sec->getType() == SHT_NOBITS) {
       Sec->setFileOffset(Off);
-      continue;
+      return;
     }
 
     Off = getFileAlignment<ELFT>(Off, Sec);
     Sec->setFileOffset(Off);
     Off += Sec->getSize();
-  }
+  };
+
+  Set(Out<ELFT>::ElfHeader);
+  Set(Out<ELFT>::ProgramHeaders);
+  for (OutputSectionBase<ELFT> *Sec : OutputSections)
+    Set(Sec);
+
   SectionHeaderOff = alignTo(Off, sizeof(uintX_t));
   FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
 }

Added: lld/trunk/test/ELF/linkerscript-phdr-check.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-phdr-check.s?rev=274342&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript-phdr-check.s (added)
+++ lld/trunk/test/ELF/linkerscript-phdr-check.s Fri Jul  1 05:27:36 2016
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# RUN: echo "SECTIONS { . = 0x10000000; .text : {*(.text.*)} }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-readobj -program-headers %t1 | FileCheck %s
+# CHECK:      ProgramHeaders [
+# CHECK-NEXT:  ProgramHeader {
+# CHECK-NEXT:    Type: PT_PHDR (0x6)
+# CHECK-NEXT:    Offset: 0x40
+# CHECK-NEXT:    VirtualAddress: 0xFFFF040
+
+.global _start
+_start:
+ nop




More information about the llvm-commits mailing list