static OutputSection *createSection(InputSectionBase *isec,
StringRef outsecName) {
OutputSection *sec = script->createOutputSection(outsecName, "<internal>");
+ if (!(isec->flags & SHF_ALLOC))
+ sec->addrExpr = [] { return 0; };
sec->recordSection(isec);
return sec;
}
// This function assigns offsets to input sections and an output section
// for a single sections command (e.g. ".text { *(.text); }").
void LinkerScript::assignOffsets(OutputSection *sec) {
- if (!(sec->flags & SHF_ALLOC))
- dot = 0;
-
const bool sameMemRegion = ctx->memRegion == sec->memRegion;
const bool prevLMARegionIsDefault = ctx->lmaRegion == nullptr;
ctx->memRegion = sec->memRegion;
if (ctx->memRegion)
dot = ctx->memRegion->curPos;
- if ((sec->flags & SHF_ALLOC) && sec->addrExpr)
+ if (sec->addrExpr)
setDot(sec->addrExpr, sec->location, false);
// If the address of the section has been moved forward by an explicit
static std::vector<BaseCommand *>::iterator
findOrphanPos(std::vector<BaseCommand *>::iterator b,
std::vector<BaseCommand *>::iterator e) {
+ // OutputSections without the SHF_ALLOC flag are not part of the memory image
+ // and their addresses usually don't matter. Place any orphan sections without
+ // the SHF_ALLOC flag at the end so that these do not affect the address
+ // assignment of OutputSections with the SHF_ALLOC flag.
OutputSection *sec = cast<OutputSection>(*e);
+ if (!(sec->flags & SHF_ALLOC))
+ return e;
// Find the first element that has as close a rank as possible.
auto i = std::max_element(b, e, [=](BaseCommand *a, BaseCommand *b) {
}
for (OutputSection *sec : outputSections) {
- if (!(sec->flags & SHF_ALLOC))
- break;
if (!needsPtLoad(sec))
continue;
# SEC-DEFAULT: 7 .shstrtab 0000003b {{[0-9a-f]*}}
# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
-# Sections are put in order specified in linker script, other than alloc
-# sections going first.
+## Sections are placed in the order specified by the linker script. .data has
+## a PT_LOAD segment, even if it is preceded by a non-alloc section. To
+## allow this, place non-alloc orphan sections at the end and advance
+## location counters for non-alloc non-orphan sections.
# RUN: echo "SECTIONS { \
# RUN: .bss : { *(.bss) } \
# RUN: other : { *(other) } \
# RUN: .symtab : { *(.symtab) } \
# RUN: .strtab : { *(.strtab) } \
# RUN: .data : { *(.data) } \
-# RUN: .text : { *(.text) } }" > %t.script
-# RUN: ld.lld -o %t3 --script %t.script %t
-# RUN: llvm-objdump --section-headers %t3 | \
-# RUN: FileCheck -check-prefix=SEC-ORDER %s
+# RUN: .text : { *(.text) } }" > %t3.lds
+# RUN: ld.lld -o %t3a -T %t3.lds %t
+# RUN: llvm-readelf -S -l %t3a | FileCheck --check-prefix=SEC-ORDER %s
+# RUN: ld.lld -o %t3b -T %t3.lds --unique %t
+# RUN: llvm-readelf -S -l %t3b | FileCheck --check-prefix=SEC-ORDER %s
-# Idx Name Size
-# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
-# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
-# SEC-ORDER: 3 .shstrtab 0000003b {{[0-9a-f]*}}
-# SEC-ORDER: 4 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-ORDER: 5 .strtab 00000008 {{[0-9a-f]*}}
-# SEC-ORDER: 6 .comment 00000008 {{[0-9a-f]*}}
-# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
-# SEC-ORDER: 8 .text 0000000e {{[0-9a-f]*}} TEXT
+# SEC-ORDER: [Nr] Name Type Address Off Size ES Flg
+# SEC-ORDER: [ 0] NULL 0000000000000000 000000 000000 00
+# SEC-ORDER-NEXT: [ 1] .bss NOBITS 0000000000000000 001000 000002 00 WA
+# SEC-ORDER-NEXT: [ 2] other PROGBITS 0000000000000002 001002 000003 00 WA
+# SEC-ORDER-NEXT: [ 3] .shstrtab STRTAB 0000000000000005 001005 00003b 00
+# SEC-ORDER-NEXT: [ 4] .symtab SYMTAB 0000000000000040 001040 000030 18
+# SEC-ORDER-NEXT: [ 5] .strtab STRTAB 0000000000000070 001070 000008 00
+# SEC-ORDER-NEXT: [ 6] .data PROGBITS 0000000000000078 001078 000020 00 WA
+# SEC-ORDER-NEXT: [ 7] .text PROGBITS 0000000000000098 001098 00000e 00 AX
+# SEC-ORDER-NEXT: [ 8] .comment PROGBITS 0000000000000000 0010a6 000008 01 MS
+
+# SEC-ORDER: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+# SEC-ORDER-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000098 0x000098 RW 0x1000
+# SEC-ORDER-NEXT: LOAD 0x001098 0x0000000000000098 0x0000000000000098 0x00000e 0x00000e R E 0x1000
+# SEC-ORDER-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0
# .text and .data have swapped names but proper sizes and types.
# RUN: echo "SECTIONS { \
# SEC-MULTI-NEXT: .shstrtab 00000035 {{[0-9a-f]*}}
# SEC-MULTI-NEXT: .strtab 00000008 {{[0-9a-f]*}}
+## other is placed in a PT_LOAD segment even if it is preceded by a non-alloc section.
+## The current implementation places .data, .bss, .comment and other in the same PT_LOAD.
+# RUN: echo 'SECTIONS { \
+# RUN: .text : { *(.text) } \
+# RUN: .data : { *(.data) } \
+# RUN: .comment : { *(.comment) } \
+# RUN: other : { *(other) } }' > %t5.lds
+# RUN: ld.lld -o %t5 -T %t5.lds %t
+# RUN: llvm-readelf -S -l %t5 | FileCheck --check-prefix=SEP-BY-NONALLOC %s
+
+# SEP-BY-NONALLOC: [Nr] Name Type Address Off Size ES Flg
+# SEP-BY-NONALLOC: [ 1] .text PROGBITS 0000000000000000 001000 00000e 00 AX
+# SEP-BY-NONALLOC-NEXT: [ 2] .data PROGBITS 000000000000000e 00100e 000020 00 WA
+# SEP-BY-NONALLOC-NEXT: [ 3] .bss NOBITS 000000000000002e 00102e 000002 00 WA
+# SEP-BY-NONALLOC-NEXT: [ 4] .comment PROGBITS 0000000000000030 00102e 000008 01 MS
+# SEP-BY-NONALLOC-NEXT: [ 5] other PROGBITS 0000000000000038 001038 000003 00 WA
+
+# SEP-BY-NONALLOC: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+# SEP-BY-NONALLOC-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x00000e 0x00000e R E 0x1000
+# SEP-BY-NONALLOC-NEXT: LOAD 0x00100e 0x000000000000000e 0x000000000000000e 0x00002d 0x00002d RW 0x1000
+# SEP-BY-NONALLOC-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0
+
# Input section pattern contains additional semicolon.
# Case found in linux kernel script. Check we are able to parse it.
# RUN: echo "SECTIONS { .text : { ;;*(.text);;S = 0;; } }" > %t.script