diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -586,6 +586,8 @@ static OutputSection *createSection(InputSectionBase *isec, StringRef outsecName) { OutputSection *sec = script->createOutputSection(outsecName, ""); + if (!(isec->flags & SHF_ALLOC)) + sec->addrExpr = [] { return 0; }; sec->recordSection(isec); return sec; } @@ -848,9 +850,6 @@ // 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; @@ -858,7 +857,7 @@ 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 diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1234,7 +1234,11 @@ static std::vector::iterator findOrphanPos(std::vector::iterator b, std::vector::iterator e) { + // To make the addresses of orphan sections not affected by non-allocable + // sections in the middle, place orphan non-allocable sections in the end. OutputSection *sec = cast(*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) { @@ -2326,8 +2330,6 @@ } for (OutputSection *sec : outputSections) { - if (!(sec->flags & SHF_ALLOC)) - break; if (!needsPtLoad(sec)) continue; diff --git a/lld/test/ELF/linkerscript/compress-debug-sections-custom.s b/lld/test/ELF/linkerscript/compress-debug-sections-custom.s --- a/lld/test/ELF/linkerscript/compress-debug-sections-custom.s +++ b/lld/test/ELF/linkerscript/compress-debug-sections-custom.s @@ -1,9 +1,10 @@ # REQUIRES: x86, zlib +## NOTE GNU ld makes .debug_str and .debug_info allocable due to `. += 10`. # RUN: echo "SECTIONS { \ # RUN: .text : { . += 0x10; *(.text) } \ -# RUN: .debug_str : { . += 0x10; *(.debug_str) } \ -# RUN: .debug_info : { . += 0x10; *(.debug_info) } \ +# RUN: .debug_str 0 : { . += 0x10; *(.debug_str) } \ +# RUN: .debug_info 0 : { . += 0x10; *(.debug_info) } \ # RUN: }" > %t.script # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o diff --git a/lld/test/ELF/linkerscript/sections.s b/lld/test/ELF/linkerscript/sections.s --- a/lld/test/ELF/linkerscript/sections.s +++ b/lld/test/ELF/linkerscript/sections.s @@ -25,8 +25,10 @@ # 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-allocable section. To +## allow this, place non-allocable orphan sections in the end and advance +## location counters for non-allocable non-orphan sections. # RUN: echo "SECTIONS { \ # RUN: .bss : { *(.bss) } \ # RUN: other : { *(other) } \ @@ -34,20 +36,27 @@ # 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 { \ diff --git a/lld/test/ELF/linkerscript/symbols-non-alloc.test b/lld/test/ELF/linkerscript/symbols-non-alloc.test --- a/lld/test/ELF/linkerscript/symbols-non-alloc.test +++ b/lld/test/ELF/linkerscript/symbols-non-alloc.test @@ -1,14 +1,17 @@ # REQUIRES: x86 +## The address of a symbol assignment after a non-allocable section equals to +## the end address of the section. + # RUN: echo '.section .nonalloc,""; .quad 0' \ # RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t # RUN: ld.lld -o %t2 --script %s %t # RUN: llvm-objdump --section-headers -t %t2 | FileCheck %s # CHECK: Sections: -# CHECK: .nonalloc 00000008 0000000000000000 +# CHECK: .nonalloc 00000008 0000000000000120 # CHECK: SYMBOL TABLE: -# CHECK: 0000000000000008 g .nonalloc 0000000000000000 Sym +# CHECK: 0000000000000128 g .nonalloc 0000000000000000 Sym SECTIONS { . = SIZEOF_HEADERS;