[lld] r323733 - Merging r323395, r323396, r323399, r323440, r323449, r323456, and r323625:

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 30 01:20:28 PST 2018


Author: hans
Date: Tue Jan 30 01:20:27 2018
New Revision: 323733

URL: http://llvm.org/viewvc/llvm-project?rev=323733&view=rev
Log:
Merging r323395, r323396, r323399, r323440, r323449, r323456, and r323625:

------------------------------------------------------------------------
r323395 | rafael | 2018-01-25 02:29:15 +0100 (Thu, 25 Jan 2018) | 1 line

Use lookup instead of find. NFC, just simpler.
------------------------------------------------------------------------

------------------------------------------------------------------------
r323396 | rafael | 2018-01-25 02:36:36 +0100 (Thu, 25 Jan 2018) | 3 lines

Only lookup LMARegion once. NFC.

This is similar to how we handle MemRegion.
------------------------------------------------------------------------

------------------------------------------------------------------------
r323399 | rafael | 2018-01-25 03:18:00 +0100 (Thu, 25 Jan 2018) | 3 lines

Remove MemRegionOffset. NFC.

We can just use a member variable in MemoryRegion.
------------------------------------------------------------------------

------------------------------------------------------------------------
r323440 | rafael | 2018-01-25 17:43:49 +0100 (Thu, 25 Jan 2018) | 1 line

Simplify. NFC.
------------------------------------------------------------------------

------------------------------------------------------------------------
r323449 | rafael | 2018-01-25 18:42:03 +0100 (Thu, 25 Jan 2018) | 9 lines

Improve LMARegion handling.

This fixes the crash reported at PR36083.

The issue is that we were trying to put all the sections in the same
PT_LOAD and crashing trying to write past the end of the file.

This also adds accounting for used space in LMARegion, without it all
3 PT_LOADs would have the same physical address.
------------------------------------------------------------------------

------------------------------------------------------------------------
r323456 | rafael | 2018-01-25 20:02:08 +0100 (Thu, 25 Jan 2018) | 19 lines

Move LMAOffset from the OutputSection to the PhdrEntry. NFC.

If two sections are in the same PT_LOAD, their relatives offsets,
virtual address and physical addresses are all the same.

I initially wanted to have a single global LMAOffset, on the
assumption that every ELF file was in practiced loaded contiguously in
both physical and virtual memory.

Unfortunately that is not the case. The linux kernel has:

  LOAD           0x200000 0xffffffff81000000 0x0000000001000000 0xced000 0xced000 R E 0x200000
  LOAD           0x1000000 0xffffffff81e00000 0x0000000001e00000 0x15f000 0x15f000 RW  0x200000
  LOAD           0x1200000 0x0000000000000000 0x0000000001f5f000 0x01b198 0x01b198 RW  0x200000
  LOAD           0x137b000 0xffffffff81f7b000 0x0000000001f7b000 0x116000 0x1ec000 RWE 0x200000

The delta for all but the third PT_LOAD is the same:
0xffffffff80000000. I think the 3rd one is a hack for implementing per
cpu data, but we can't break that.
------------------------------------------------------------------------

------------------------------------------------------------------------
r323625 | rafael | 2018-01-29 04:44:44 +0100 (Mon, 29 Jan 2018) | 10 lines

Put the header in the first PT_LOAD even if that PT_LOAD has a LMAExpr.

This should fix PR36017.

The root problem is that we were creating a PT_LOAD just for the
header. That was technically valid, but inconvenient: we should not be
making the ELF discontinuous.

The solution is to allow a section with LMAExpr to be added to a
PT_LOAD if that PT_LOAD doesn't already have a LMAExpr.
------------------------------------------------------------------------

Added:
    lld/branches/release_60/test/ELF/linkerscript/at3.s
      - copied unchanged from r323449, lld/trunk/test/ELF/linkerscript/at3.s
    lld/branches/release_60/test/ELF/linkerscript/merge-header-load.s
      - copied unchanged from r323625, lld/trunk/test/ELF/linkerscript/merge-header-load.s
Modified:
    lld/branches/release_60/   (props changed)
    lld/branches/release_60/ELF/LinkerScript.cpp
    lld/branches/release_60/ELF/LinkerScript.h
    lld/branches/release_60/ELF/OutputSections.h
    lld/branches/release_60/ELF/ScriptParser.cpp
    lld/branches/release_60/ELF/Writer.cpp
    lld/branches/release_60/ELF/Writer.h

Propchange: lld/branches/release_60/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jan 30 01:20:27 2018
@@ -1 +1 @@
-/lld/trunk:321983,321986,322041,322259,322264,322359,322421,322801,323221
+/lld/trunk:321983,321986,322041,322259,322264,322359,322421,322801,323221,323395-323396,323399,323440,323449,323456,323625

Modified: lld/branches/release_60/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_60/ELF/LinkerScript.cpp?rev=323733&r1=323732&r2=323733&view=diff
==============================================================================
--- lld/branches/release_60/ELF/LinkerScript.cpp (original)
+++ lld/branches/release_60/ELF/LinkerScript.cpp Tue Jan 30 01:20:27 2018
@@ -589,8 +589,12 @@ void LinkerScript::output(InputSection *
 
   // If there is a memory region associated with this input section, then
   // place the section in that region and update the region index.
+  if (Ctx->LMARegion)
+    Ctx->LMARegion->CurPos += Pos - Before;
+  // FIXME: should we also produce overflow errors for LMARegion?
+
   if (Ctx->MemRegion) {
-    uint64_t &CurOffset = Ctx->MemRegionOffset[Ctx->MemRegion];
+    uint64_t &CurOffset = Ctx->MemRegion->CurPos;
     CurOffset += Pos - Before;
     uint64_t CurSize = CurOffset - Ctx->MemRegion->Origin;
     if (CurSize > Ctx->MemRegion->Length) {
@@ -617,9 +621,8 @@ MemoryRegion *LinkerScript::findMemoryRe
   // If a memory region name was specified in the output section command,
   // then try to find that region first.
   if (!Sec->MemoryRegionName.empty()) {
-    auto It = MemoryRegions.find(Sec->MemoryRegionName);
-    if (It != MemoryRegions.end())
-      return It->second;
+    if (MemoryRegion *M = MemoryRegions.lookup(Sec->MemoryRegionName))
+      return M;
     error("memory region '" + Sec->MemoryRegionName + "' not declared");
     return nullptr;
   }
@@ -652,31 +655,24 @@ void LinkerScript::assignOffsets(OutputS
     setDot(Sec->AddrExpr, Sec->Location, false);
 
   Ctx->MemRegion = Sec->MemRegion;
+  Ctx->LMARegion = Sec->LMARegion;
   if (Ctx->MemRegion)
-    Dot = Ctx->MemRegionOffset[Ctx->MemRegion];
+    Dot = Ctx->MemRegion->CurPos;
 
   switchTo(Sec);
 
-  if (Sec->LMAExpr) {
-    uint64_t D = Dot;
-    Ctx->LMAOffset = [=] { return Sec->LMAExpr().getValue() - D; };
-  }
+  if (Sec->LMAExpr)
+    Ctx->LMAOffset = Sec->LMAExpr().getValue() - Dot;
 
-  if (!Sec->LMARegionName.empty()) {
-    if (MemoryRegion *MR = MemoryRegions.lookup(Sec->LMARegionName)) {
-      uint64_t Offset = MR->Origin - Dot;
-      Ctx->LMAOffset = [=] { return Offset; };
-    } else {
-      error("memory region '" + Sec->LMARegionName + "' not declared");
-    }
-  }
+  if (MemoryRegion *MR = Sec->LMARegion)
+    Ctx->LMAOffset = MR->CurPos - Dot;
 
   // If neither AT nor AT> is specified for an allocatable section, the linker
   // will set the LMA such that the difference between VMA and LMA for the
   // section is the same as the preceding output section in the same region
   // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
-  if (Ctx->LMAOffset)
-    Ctx->OutSec->LMAOffset = Ctx->LMAOffset();
+  if (PhdrEntry *L = Ctx->OutSec->PtLoad)
+    L->LMAOffset = Ctx->LMAOffset;
 
   // The Size previously denoted how many InputSections had been added to this
   // section, and was used for sorting SHF_LINK_ORDER sections. Reset it to
@@ -698,7 +694,9 @@ void LinkerScript::assignOffsets(OutputS
       Cmd->Offset = Dot - Ctx->OutSec->Addr;
       Dot += Cmd->Size;
       if (Ctx->MemRegion)
-        Ctx->MemRegionOffset[Ctx->MemRegion] += Cmd->Size;
+        Ctx->MemRegion->CurPos += Cmd->Size;
+      if (Ctx->LMARegion)
+        Ctx->LMARegion->CurPos += Cmd->Size;
       Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr;
       continue;
     }
@@ -797,6 +795,12 @@ void LinkerScript::adjustSectionsAfterSo
     if (auto *Sec = dyn_cast<OutputSection>(Base)) {
       if (!Sec->Live)
         continue;
+      if (!Sec->LMARegionName.empty()) {
+        if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName))
+          Sec->LMARegion = M;
+        else
+          error("memory region '" + Sec->LMARegionName + "' not declared");
+      }
       Sec->MemRegion = findMemoryRegion(Sec);
       // Handle align (e.g. ".foo : ALIGN(16) { ... }").
       if (Sec->AlignExpr)
@@ -887,8 +891,8 @@ void LinkerScript::allocateHeaders(std::
 
 LinkerScript::AddressState::AddressState() {
   for (auto &MRI : Script->MemoryRegions) {
-    const MemoryRegion *MR = MRI.second;
-    MemRegionOffset[MR] = MR->Origin;
+    MemoryRegion *MR = MRI.second;
+    MR->CurPos = MR->Origin;
   }
 }
 

Modified: lld/branches/release_60/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_60/ELF/LinkerScript.h?rev=323733&r1=323732&r2=323733&view=diff
==============================================================================
--- lld/branches/release_60/ELF/LinkerScript.h (original)
+++ lld/branches/release_60/ELF/LinkerScript.h Tue Jan 30 01:20:27 2018
@@ -118,11 +118,17 @@ enum class ConstraintKind { NoConstraint
 // target memory. Instances of the struct are created by parsing the
 // MEMORY command.
 struct MemoryRegion {
+  MemoryRegion(StringRef Name, uint64_t Origin, uint64_t Length, uint32_t Flags,
+               uint32_t NegFlags)
+      : Name(Name), Origin(Origin), Length(Length), Flags(Flags),
+        NegFlags(NegFlags) {}
+
   std::string Name;
   uint64_t Origin;
   uint64_t Length;
   uint32_t Flags;
   uint32_t NegFlags;
+  uint64_t CurPos = 0;
 };
 
 // This struct represents one section match pattern in SECTIONS() command.
@@ -200,8 +206,8 @@ class LinkerScript final {
     uint64_t ThreadBssOffset = 0;
     OutputSection *OutSec = nullptr;
     MemoryRegion *MemRegion = nullptr;
-    llvm::DenseMap<const MemoryRegion *, uint64_t> MemRegionOffset;
-    std::function<uint64_t()> LMAOffset;
+    MemoryRegion *LMARegion = nullptr;
+    uint64_t LMAOffset = 0;
   };
 
   llvm::DenseMap<StringRef, OutputSection *> NameToOutputSection;

Modified: lld/branches/release_60/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_60/ELF/OutputSections.h?rev=323733&r1=323732&r2=323733&view=diff
==============================================================================
--- lld/branches/release_60/ELF/OutputSections.h (original)
+++ lld/branches/release_60/ELF/OutputSections.h Tue Jan 30 01:20:27 2018
@@ -49,7 +49,7 @@ public:
 
   static bool classof(const BaseCommand *C);
 
-  uint64_t getLMA() const { return Addr + LMAOffset; }
+  uint64_t getLMA() const { return PtLoad ? Addr + PtLoad->LMAOffset : Addr; }
   template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
 
   unsigned SectionIndex;
@@ -78,7 +78,6 @@ public:
 
   // The following fields correspond to Elf_Shdr members.
   uint64_t Offset = 0;
-  uint64_t LMAOffset = 0;
   uint64_t Addr = 0;
   uint32_t ShName = 0;
 
@@ -89,6 +88,7 @@ public:
 
   // The following members are normally only used in linker scripts.
   MemoryRegion *MemRegion = nullptr;
+  MemoryRegion *LMARegion = nullptr;
   Expr AddrExpr;
   Expr AlignExpr;
   Expr LMAExpr;

Modified: lld/branches/release_60/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_60/ELF/ScriptParser.cpp?rev=323733&r1=323732&r2=323733&view=diff
==============================================================================
--- lld/branches/release_60/ELF/ScriptParser.cpp (original)
+++ lld/branches/release_60/ELF/ScriptParser.cpp Tue Jan 30 01:20:27 2018
@@ -1293,8 +1293,8 @@ void ScriptParser::readMemory() {
     // Add the memory region to the region map.
     if (Script->MemoryRegions.count(Name))
       setError("region '" + Name + "' already defined");
-    MemoryRegion *MR = make<MemoryRegion>();
-    *MR = {Name, Origin, Length, Flags, NegFlags};
+    MemoryRegion *MR =
+        make<MemoryRegion>(Name, Origin, Length, Flags, NegFlags);
     Script->MemoryRegions[Name] = MR;
   }
 }

Modified: lld/branches/release_60/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_60/ELF/Writer.cpp?rev=323733&r1=323732&r2=323733&view=diff
==============================================================================
--- lld/branches/release_60/ELF/Writer.cpp (original)
+++ lld/branches/release_60/ELF/Writer.cpp Tue Jan 30 01:20:27 2018
@@ -822,6 +822,8 @@ void PhdrEntry::add(OutputSection *Sec)
   p_align = std::max(p_align, Sec->Alignment);
   if (p_type == PT_LOAD)
     Sec->PtLoad = this;
+  if (Sec->LMAExpr)
+    ASectionHasLMA = true;
 }
 
 // The beginning and the ending of .rel[a].plt section are marked
@@ -1626,7 +1628,9 @@ template <class ELFT> std::vector<PhdrEn
     // different flags or is loaded at a discontiguous address using AT linker
     // script command.
     uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
-    if (Sec->LMAExpr || Flags != NewFlags) {
+    if ((Sec->LMAExpr && Load->ASectionHasLMA) ||
+        Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) {
+
       Load = AddHdr(PT_LOAD, NewFlags);
       Flags = NewFlags;
     }

Modified: lld/branches/release_60/ELF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/branches/release_60/ELF/Writer.h?rev=323733&r1=323732&r2=323733&view=diff
==============================================================================
--- lld/branches/release_60/ELF/Writer.h (original)
+++ lld/branches/release_60/ELF/Writer.h Tue Jan 30 01:20:27 2018
@@ -44,6 +44,13 @@ struct PhdrEntry {
   OutputSection *FirstSec = nullptr;
   OutputSection *LastSec = nullptr;
   bool HasLMA = false;
+
+  // True if one of the sections in this program header has a LMA specified via
+  // linker script: AT(addr). We never allow 2 or more sections with LMA in the
+  // same program header.
+  bool ASectionHasLMA = false;
+
+  uint64_t LMAOffset = 0;
 };
 
 void addReservedSymbols();




More information about the llvm-commits mailing list