Skip to content

Commit 7c89b20

Browse files
committed
[ELF] OVERLAY: support optional start address and LMA
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 Pull Request: #77272
1 parent 6958986 commit 7c89b20

File tree

2 files changed

+29
-17
lines changed

2 files changed

+29
-17
lines changed

lld/ELF/ScriptParser.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -531,13 +531,17 @@ void ScriptParser::readSearchDir() {
531531
// linker's sections sanity check failures.
532532
// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
533533
SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
534-
// VA and LMA expressions are optional, though for simplicity of
535-
// implementation we assume they are not. That is what OVERLAY was designed
536-
// for first of all: to allow sections with overlapping VAs at different LMAs.
537-
Expr addrExpr = readExpr();
538-
expect(":");
539-
expect("AT");
540-
Expr lmaExpr = readParenExpr();
534+
Expr addrExpr;
535+
if (consume(":")) {
536+
addrExpr = [] { return script->getDot(); };
537+
} else {
538+
addrExpr = readExpr();
539+
expect(":");
540+
}
541+
// When AT is omitted, LMA should equal VMA. script->getDot() when evaluating
542+
// lmaExpr will ensure this, even if the start address is specified.
543+
Expr lmaExpr =
544+
consume("AT") ? readParenExpr() : [] { return script->getDot(); };
541545
expect("{");
542546

543547
SmallVector<SectionCommand *, 0> v;
@@ -547,10 +551,15 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
547551
// starting from the base load address specified.
548552
OutputDesc *osd = readOverlaySectionDescription();
549553
osd->osec.addrExpr = addrExpr;
550-
if (prev)
554+
if (prev) {
551555
osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
552-
else
556+
} else {
553557
osd->osec.lmaExpr = lmaExpr;
558+
// Use first section address for subsequent sections as initial addrExpr
559+
// can be DOT. Ensure the first section, even if empty, is not discarded.
560+
osd->osec.usedInExpression = true;
561+
addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; };
562+
}
554563
v.push_back(osd);
555564
prev = &osd->osec;
556565
}

lld/test/ELF/linkerscript/overlay.test

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@
1616
# CHECK-NEXT: .small1 PROGBITS 0000000000001000 002000 000004
1717
# CHECK-NEXT: .small2 PROGBITS 0000000000001008 002008 000004
1818
# CHECK-NEXT: .big2 PROGBITS 0000000000001008 003008 000008
19+
# CHECK-NEXT: .empty3 PROGBITS 0000000000001010 003010 000000
1920
# CHECK-NEXT: .small3 PROGBITS 0000000000001010 003010 000004
20-
# CHECK-NEXT: .big3 PROGBITS 0000000000001014 003014 000008
21-
# CHECK-NEXT: .text PROGBITS 0000000000001024 003024 000001
21+
# CHECK-NEXT: .big3 PROGBITS 0000000000001010 004010 000008
22+
# CHECK-NEXT: .text PROGBITS 0000000000001018 004018 000001
2223

2324
# CHECK: Program Headers:
2425
# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
2526
# CHECK-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000008 0x000008 R 0x1000
2627
# CHECK-NEXT: LOAD 0x002000 0x0000000000001000 0x0000000000001008 0x000004 0x000004 R 0x1000
2728
# CHECK-NEXT: LOAD 0x002008 0x0000000000001008 0x0000000000002008 0x000004 0x000004 R 0x1000
2829
# CHECK-NEXT: LOAD 0x003008 0x0000000000001008 0x000000000000200c 0x000008 0x000008 R 0x1000
29-
## FIXME Fix p_paddr when the first section in an overlay is empty and discarded.
30-
# CHECK-NEXT: LOAD 0x003010 0x0000000000001010 0x0000000000000000 0x000004 0x000004 R 0x1000
31-
# CHECK-NEXT: LOAD 0x003014 0x0000000000001014 0x0000000000000004 0x000008 0x000008 R 0x1000
32-
# CHECK-NEXT: LOAD 0x003024 0x0000000000001024 0x0000000000000014 0x000001 0x000001 R E 0x1000
30+
# CHECK-NEXT: LOAD 0x003010 0x0000000000001010 0x0000000000002014 0x000004 0x000004 R 0x1000
31+
# CHECK-NEXT: LOAD 0x004010 0x0000000000001010 0x0000000000002018 0x000008 0x000008 R 0x1000
32+
# CHECK-NEXT: LOAD 0x004018 0x0000000000001018 0x0000000000002020 0x000001 0x000001 R E 0x1000
3333

3434
# RUN: not ld.lld a.o -T err1.t 2>&1 | FileCheck %s --check-prefix=ERR1 --match-full-lines --strict-whitespace
3535
# ERR1:{{.*}}error: err1.t:3: { expected, but got 0x3000
@@ -57,14 +57,17 @@ _start:
5757

5858
#--- a.t
5959
SECTIONS {
60-
OVERLAY 0x1000 : AT( 0x1000 ) {
60+
## LMA defaults to VMA
61+
OVERLAY 0x1000 : {
6162
.big1 { *(.big1) }
6263
.small1 { *(.small1) }
6364
}
64-
OVERLAY 0x1008 : AT (0x2008) {
65+
## .big2 starts at ADDR(.small2)
66+
OVERLAY : AT (0x2008) {
6567
.small2 { *(.small2) }
6668
.big2 { *(.big2) }
6769
}
70+
## .empty3 is not discarded. .small3 and .big3 share its address.
6871
OVERLAY . : AT (0x2014) {
6972
.empty3 { *(.empty3) }
7073
.small3 { *(.small3) }

0 commit comments

Comments
 (0)