From 5f857327387792928c48d9fbf259127332811be6 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Wed, 27 Apr 2016 09:16:28 +0000 Subject: [PATCH] [ELF] - Align sections file offsets correctly. System V ABI 4.1 specifies that program header's p_vaddr should equal p_offset, modulo p_align. (https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html). It was possible to violate this using the linkerscript. Patch fixes the issue. Differential revision: http://reviews.llvm.org/D19416 llvm-svn: 267684 --- lld/ELF/Writer.cpp | 24 +++++++++++--- lld/test/ELF/phdr-align.s | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 lld/test/ELF/phdr-align.s diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8ca9aa2..8967f2c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1662,6 +1662,24 @@ template void Writer::assignAddresses() { } } +// Adjusts the file alignment for a given output section and returns +// its new file offset. The file offset must be the same with its +// virtual address (modulo the page size) so that the loader can load +// executables without any address adjustment. +template +static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase *Sec) { + uintX_t Align = Sec->getAlign(); + if (Sec->PageAlign) + Align = std::max(Align, Target->PageSize); + Off = alignTo(Off, Align); + + // Relocatable output does not have program headers + // and does not need any other offset adjusting. + if (Config->Relocatable || !(Sec->getFlags() & SHF_ALLOC)) + return Off; + return alignTo(Off, Target->PageSize, Sec->getVA()); +} + // Assign file offsets to output sections. template void Writer::assignFileOffsets() { uintX_t Off = @@ -1672,10 +1690,8 @@ template void Writer::assignFileOffsets() { Sec->setFileOffset(Off); continue; } - uintX_t Align = Sec->getAlign(); - if (Sec->PageAlign) - Align = std::max(Align, Target->PageSize); - Off = alignTo(Off, Align); + + Off = getFileAlignment(Off, Sec); Sec->setFileOffset(Off); Off += Sec->getSize(); } diff --git a/lld/test/ELF/phdr-align.s b/lld/test/ELF/phdr-align.s new file mode 100644 index 0000000..58d537b --- /dev/null +++ b/lld/test/ELF/phdr-align.s @@ -0,0 +1,82 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "SECTIONS { \ +# RUN: .bss : { *(.bss) } \ +# RUN: .data : { *(.data) } \ +# RUN: .text : { *(.text) } }" > %t.script +# RUN: ld.lld %t.o --script %t.script -o %t +# RUN: llvm-readobj -sections -symbols %t | FileCheck %s + +# CHECK: Sections [ +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Name: .bss +# CHECK-NEXT: Type: SHT_NOBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x158 +# CHECK-NEXT: Offset: 0x158 +# CHECK-NEXT: Size: 6 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: Name: .data +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x15E +# CHECK-NEXT: Offset: 0x15E +# CHECK-NEXT: Size: 2 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Name: .text +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_EXECINSTR +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x160 +# CHECK-NEXT: Offset: 0x160 +# CHECK-NEXT: Size: 1 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 4 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } + +.global _start +.text +_start: + nop +.data + .word 1 +.bss + .space 6 -- 2.7.4