Skip to content

Commit

Permalink
[ELF] Linkerscript: implement DATA_SEGMENT_RELRO_END.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
George Rimar committed Jul 26, 2016
1 parent 6774d61 commit 276b4e6
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
11 changes: 11 additions & 0 deletions lld/ELF/LinkerScript.cpp
Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions 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:
69 changes: 69 additions & 0 deletions 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

0 comments on commit 276b4e6

Please sign in to comment.