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

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


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

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


>From 54a4e2b2c1f65693c7e41abfb456bddfe65e12bd Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 7 Jan 2024 21:37:19 -0800
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.4
---
 lld/ELF/ScriptParser.cpp               | 25 ++++++++++++++++---------
 lld/test/ELF/linkerscript/overlay.test | 19 +++++++++++--------
 2 files changed, 27 insertions(+), 17 deletions(-)

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) }



More information about the llvm-commits mailing list