[lld] [ELF] OVERLAY: support optional start address and LMA (PR #77272)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 7 21:37:58 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-elf

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

https://reviews.llvm.org/D44780 implemented rudimentary support for
OVERLAY. The start address and `AT(ldaddr)` in `OVERLAY [start] :
[NOCROSSREFS] [AT ( ldaddr )]` are not optional.

In addition, there are two issues:

* When the start address is `.`, subsequent sections don't share the
  address of the first overlay section.
* When the first overlay section is empty and discardable, `p_paddr` is
  incorrectly zero. This is because a discarded section has a zero
  address, causing `prev->getLMA() + prev->size` where `prev` refers to
  the first section to evaluate to zero.

This patch supports optional start address and LMA and fix the issues.
Close #<!-- -->77265


---
Full diff: https://github.com/llvm/llvm-project/pull/77272.diff


2 Files Affected:

- (modified) lld/ELF/ScriptParser.cpp (+16-9) 
- (modified) lld/test/ELF/linkerscript/overlay.test (+11-8) 


``````````diff
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 55b10f0c59b516..036aa16ad03e97 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -531,13 +531,15 @@ void ScriptParser::readSearchDir() {
 // linker's sections sanity check failures.
 // https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
 SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
-  // VA and LMA expressions are optional, though for simplicity of
-  // implementation we assume they are not. That is what OVERLAY was designed
-  // for first of all: to allow sections with overlapping VAs at different LMAs.
-  Expr addrExpr = readExpr();
-  expect(":");
-  expect("AT");
-  Expr lmaExpr = readParenExpr();
+  Expr addrExpr;
+  if (consume(":")) {
+    addrExpr = [] { return script->getDot(); };
+  } else {
+    addrExpr = readExpr();
+    expect(":");
+  }
+  Expr lmaExpr =
+      consume("AT") ? readParenExpr() : [] { return script->getDot(); };
   expect("{");
 
   SmallVector<SectionCommand *, 0> v;
@@ -547,10 +549,15 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
     // starting from the base load address specified.
     OutputDesc *osd = readOverlaySectionDescription();
     osd->osec.addrExpr = addrExpr;
-    if (prev)
+    if (prev) {
       osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
-    else
+    } else {
       osd->osec.lmaExpr = lmaExpr;
+      // Ensure that the first section, even if empty, is not discarded.
+      // Subsequent sections share its address.
+      osd->osec.usedInExpression = true;
+      addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; };
+    }
     v.push_back(osd);
     prev = &osd->osec;
   }
diff --git a/lld/test/ELF/linkerscript/overlay.test b/lld/test/ELF/linkerscript/overlay.test
index 942e0a2971beca..a40ddb48cf5dba 100644
--- a/lld/test/ELF/linkerscript/overlay.test
+++ b/lld/test/ELF/linkerscript/overlay.test
@@ -16,9 +16,10 @@
 # CHECK-NEXT: .small1    PROGBITS 0000000000001000 002000 000004
 # CHECK-NEXT: .small2    PROGBITS 0000000000001008 002008 000004
 # CHECK-NEXT: .big2      PROGBITS 0000000000001008 003008 000008
+# CHECK-NEXT: .empty3    PROGBITS 0000000000001010 003010 000000
 # CHECK-NEXT: .small3    PROGBITS 0000000000001010 003010 000004
-# CHECK-NEXT: .big3      PROGBITS 0000000000001014 003014 000008
-# CHECK-NEXT: .text      PROGBITS 0000000000001024 003024 000001
+# CHECK-NEXT: .big3      PROGBITS 0000000000001010 004010 000008
+# CHECK-NEXT: .text      PROGBITS 0000000000001018 004018 000001
 
 # CHECK:      Program Headers:
 # CHECK:      Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
@@ -26,10 +27,9 @@
 # CHECK-NEXT: LOAD 0x002000 0x0000000000001000 0x0000000000001008 0x000004 0x000004 R   0x1000
 # CHECK-NEXT: LOAD 0x002008 0x0000000000001008 0x0000000000002008 0x000004 0x000004 R   0x1000
 # CHECK-NEXT: LOAD 0x003008 0x0000000000001008 0x000000000000200c 0x000008 0x000008 R   0x1000
-## FIXME Fix p_paddr when the first section in an overlay is empty and discarded.
-# CHECK-NEXT: LOAD 0x003010 0x0000000000001010 0x0000000000000000 0x000004 0x000004 R   0x1000
-# CHECK-NEXT: LOAD 0x003014 0x0000000000001014 0x0000000000000004 0x000008 0x000008 R   0x1000
-# CHECK-NEXT: LOAD 0x003024 0x0000000000001024 0x0000000000000014 0x000001 0x000001 R E 0x1000
+# CHECK-NEXT: LOAD 0x003010 0x0000000000001010 0x0000000000002014 0x000004 0x000004 R   0x1000
+# CHECK-NEXT: LOAD 0x004010 0x0000000000001010 0x0000000000002018 0x000008 0x000008 R   0x1000
+# CHECK-NEXT: LOAD 0x004018 0x0000000000001018 0x0000000000002020 0x000001 0x000001 R E 0x1000
 
 # RUN: not ld.lld a.o -T err1.t 2>&1 | FileCheck %s --check-prefix=ERR1 --match-full-lines --strict-whitespace
 #      ERR1:{{.*}}error: err1.t:3: { expected, but got 0x3000
@@ -57,14 +57,17 @@ _start:
 
 #--- a.t
 SECTIONS {
-  OVERLAY 0x1000 : AT( 0x1000 ) {
+## LMA defaults to VMA
+  OVERLAY 0x1000 : {
     .big1 { *(.big1) }
     .small1 { *(.small1) }
   }
-  OVERLAY 0x1008 : AT (0x2008) {
+## .big2 starts at ADDR(.small2)
+  OVERLAY : AT (0x2008) {
     .small2 { *(.small2) }
     .big2 { *(.big2) }
   }
+## .big3 starts at .small3
   OVERLAY . : AT (0x2014) {
     .empty3 { *(.empty3) }
     .small3 { *(.small3) }

``````````

</details>


https://github.com/llvm/llvm-project/pull/77272


More information about the llvm-commits mailing list