From 276b4e642845c3edd379a2a671f8314e38a864cb Mon Sep 17 00:00:00 2001 From: George Rimar Date: Tue, 26 Jul 2016 17:58:44 +0000 Subject: [PATCH] [ELF] Linkerscript: implement DATA_SEGMENT_RELRO_END. In compare with what GNU linkers do (https://sourceware.org/binutils/docs/ld/Builtin-Functions.html), this implementation simple: Do not touch DATA_SEGMENT_ALIGN, it do what it do now - just aligns to the page boundary. Parameters of DATA_SEGMENT_RELRO_END is ignored. That should be correct as it is usually just a 24 bytes shift that allows to protect first 3 entries of got.plt with relro. (https://svnweb.freebsd.org/base/head/sys/conf/ldscript.amd64?revision=284870&view=markup#l146). DATA_SEGMENT_RELRO_END just aligns to the page boundary. That is what expected because all sections that are not affected by relro should be on another memory page. So at fact the difference with documented behavior is that we do not pad DATA_SEGMENT_ALIGN. 3 entries of got.plt are uncovered by relro, but functionality is simple and equal to lld behavior for case when script is not given. Differential revision: https://reviews.llvm.org/D22813 llvm-svn: 276778 --- lld/ELF/LinkerScript.cpp | 11 +++ lld/test/ELF/linkerscript/Inputs/shared.s | 10 +++ .../linkerscript-data-segment-relro.s | 69 +++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 lld/test/ELF/linkerscript/Inputs/shared.s create mode 100644 lld/test/ELF/linkerscript/linkerscript-data-segment-relro.s diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 9e4ec943bdd51..a9ca646b1ea1d 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -819,6 +819,17 @@ Expr ScriptParser::readPrimary() { expect(")"); return [](uint64_t Dot) { return Dot; }; } + // GNU linkers implements more complicated logic to handle + // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and just align to + // the next page boundary for simplicity. + if (Tok == "DATA_SEGMENT_RELRO_END") { + expect("("); + next(); + expect(","); + readExpr(); + expect(")"); + return [](uint64_t Dot) { return alignTo(Dot, Target->PageSize); }; + } // Parse a number literal uint64_t V = 0; diff --git a/lld/test/ELF/linkerscript/Inputs/shared.s b/lld/test/ELF/linkerscript/Inputs/shared.s new file mode 100644 index 0000000000000..c3c22fe4b4fbc --- /dev/null +++ b/lld/test/ELF/linkerscript/Inputs/shared.s @@ -0,0 +1,10 @@ +.global bar +.type bar, @function +bar: + +.global bar2 +.type bar2, @function +bar2: + +.global zed +zed: diff --git a/lld/test/ELF/linkerscript/linkerscript-data-segment-relro.s b/lld/test/ELF/linkerscript/linkerscript-data-segment-relro.s new file mode 100644 index 0000000000000..559113e6706db --- /dev/null +++ b/lld/test/ELF/linkerscript/linkerscript-data-segment-relro.s @@ -0,0 +1,69 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o +# RUN: ld.lld -shared %t2.o -o %t2.so + +# RUN: echo "SECTIONS { \ +# RUN: .plt : { *(.plt) } \ +# RUN: .text : { *(.text) } \ +# RUN: . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); \ +# RUN: .dynamic : { *(.dynamic) } \ +# RUN: .got : { *(.got) } \ +# RUN: . = DATA_SEGMENT_RELRO_END (24, .); \ +# RUN: .got.plt : { *(.got.plt) } \ +# RUN: .data : { *(.data) } \ +# RUN: .bss : { *(.bss) } \ +# RUN: . = DATA_SEGMENT_END (.); \ +# RUN: }" > %t.script + +## With relro or without DATA_SEGMENT_RELRO_END just aligns to +## page boundary. +# RUN: ld.lld -z norelro %t1.o %t2.so --script %t.script -o %t +# RUN: llvm-readobj -s %t | FileCheck %s +# RUN: ld.lld -z relro %t1.o %t2.so --script %t.script -o %t2 +# RUN: llvm-readobj -s %t2 | FileCheck %s + +# CHECK: Section { +# CHECK: Index: 4 +# CHECK-NEXT: Name: .got +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x10F0 +# CHECK-NEXT: Offset: 0x10F0 +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 5 +# CHECK-NEXT: Name: .got.plt +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x2000 +# CHECK-NEXT: Offset: 0x2000 +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: } + +.global _start +_start: + .long bar + jmp *bar2@GOTPCREL(%rip) + +.section .data,"aw" +.quad 0 + +.zero 4 +.section .foo,"aw" +.section .bss,"",@nobits