[LLD][LinkerScript] Allow non-alloc sections to be assigned to segments.

This patch makes changes to allow sections without the SHF_ALLOC bit to be
assigned to segments in a linker script.

The assignment of output sections to segments is performed in
LinkerScript::createPhdrs. Previously, this function would bail as soon as it
encountered an output section which did not have the SHF_ALLOC bit set, thus
preventing any output section without SHF_ALLOC from being assigned to a
segment.

This restriction has now been removed from LinkerScript::createPhdrs and instead
a check for SHF_ALLOC has been added to LinkerScript::adjustSectionsAfterSorting
to not propagate program headers to sections without SHF_ALLOC which matches the
behaviour of bfd linker scripts.

Differential Revision: https://reviews.llvm.org/D34204

llvm-svn: 307013
This commit is contained in:
Andrew Ng 2017-07-03 10:11:25 +00:00
parent c1a6b128c7
commit a020d3487e
2 changed files with 52 additions and 5 deletions

View File

@ -746,11 +746,16 @@ void LinkerScript::adjustSectionsAfterSorting() {
if (!Cmd) if (!Cmd)
continue; continue;
if (Cmd->Phdrs.empty()) if (Cmd->Phdrs.empty()) {
OutputSection *Sec = Cmd->Sec;
// To match the bfd linker script behaviour, only propagate program
// headers to sections that are allocated.
if (Sec && (Sec->Flags & SHF_ALLOC))
Cmd->Phdrs = DefPhdrs; Cmd->Phdrs = DefPhdrs;
else } else {
DefPhdrs = Cmd->Phdrs; DefPhdrs = Cmd->Phdrs;
} }
}
removeEmptyCommands(); removeEmptyCommands();
} }
@ -880,8 +885,6 @@ std::vector<PhdrEntry> LinkerScript::createPhdrs() {
// Add output sections to program headers. // Add output sections to program headers.
for (OutputSectionCommand *Cmd : OutputSectionCommands) { for (OutputSectionCommand *Cmd : OutputSectionCommands) {
OutputSection *Sec = Cmd->Sec; OutputSection *Sec = Cmd->Sec;
if (!(Sec->Flags & SHF_ALLOC))
break;
// Assign headers specified by linker script // Assign headers specified by linker script
for (size_t Id : getPhdrIndices(Sec)) { for (size_t Id : getPhdrIndices(Sec)) {

View File

@ -0,0 +1,44 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
################################################################################
## Test that non-alloc section .foo can be assigned to a segment. Check that
## the values of the offset and file size of this segment's PHDR are correct.
##
## This functionality allows non-alloc metadata, which is not required at
## run-time, to be added to a custom segment in a file. This metadata may be
## read/edited by tools/loader using the values of the offset and file size from
## the custom segment's PHDR. This is particularly important if section headers
## have been stripped.
# RUN: echo "PHDRS {text PT_LOAD; foo 0x12345678;} \
# RUN: SECTIONS { \
# RUN: .text : {*(.text .text*)} :text \
# RUN: .foo : {*(.foo)} :foo \
# RUN: }" > %t.script
# RUN: ld.lld -o %t --script %t.script %t.o
# RUN: llvm-readobj -elf-output-style=GNU -s -l %t | FileCheck %s
# RUN: llvm-readobj -l %t | FileCheck --check-prefix=PHDR %s
# CHECK: Program Headers:
# CHECK-NEXT: Type
# CHECK-NEXT: LOAD
# CHECK-NEXT: <unknown>: 0x12345678
# CHECK: Section to Segment mapping:
# CHECK-NEXT: Segment Sections...
# CHECK-NEXT: 00 .text
# CHECK-NEXT: 01 .foo
# PHDR: Type: (0x12345678)
# PHDR-NEXT: Offset: 0x1004
# PHDR-NEXT: VirtualAddress
# PHDR-NEXT: PhysicalAddress
# PHDR-NEXT: FileSize: 4
.global _start
_start:
nop
.section .foo
.align 4
.long 0