Skip to content
Permalink
Browse files

[ELF] Split RW PT_LOAD on the PT_GNU_RELRO boundary

Summary:
Based on Peter Collingbourne's suggestion in D56828.

Before D56828: PT_LOAD(.data PT_GNU_RELRO(.data.rel.ro .bss.rel.ro) .bss)
Old:           PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro) .data .bss)
New:           PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro)) PT_LOAD(.data. .bss)

The new layout reflects the runtime memory mappings.
By having two PT_LOAD segments, we can utilize the NOBITS part of the
first PT_LOAD and save bytes for .bss.rel.ro.

.bss.rel.ro is currently small and only used by copy relocations of
symbols in read-only segments, but it can be used for other purposes in
the future, e.g. if a relro section's statically relocated data is all
zeros, we can move it to .bss.rel.ro.

Reviewers: espindola, ruiu, pcc

Reviewed By: ruiu

Subscribers: nemanjai, jvesely, nhaehnle, javed.absar, kbarton, emaste, arichardson, llvm-commits

Tags: #llvm

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

llvm-svn: 356226
  • Loading branch information
MaskRay committed Mar 15, 2019
1 parent 71560b5 commit e8710ef1fbe8109eaa36143654f325dd345f8a01
@@ -1945,6 +1945,29 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
Load->add(Out::ElfHeader);
Load->add(Out::ProgramHeaders);

// PT_GNU_RELRO includes all sections that should be marked as
// read-only by dynamic linker after proccessing relocations.
// Current dynamic loaders only support one PT_GNU_RELRO PHDR, give
// an error message if more than one PT_GNU_RELRO PHDR is required.
PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
bool InRelroPhdr = false;
OutputSection *RelroEnd = nullptr;
for (OutputSection *Sec : OutputSections) {
if (!needsPtLoad(Sec))
continue;
if (isRelroSection(Sec)) {
InRelroPhdr = true;
if (!RelroEnd)
RelRo->add(Sec);
else
error("section: " + Sec->Name + " is not contiguous with other relro" +
" sections");
} else if (InRelroPhdr) {
InRelroPhdr = false;
RelroEnd = Sec;
}
}

for (OutputSection *Sec : OutputSections) {
if (!(Sec->Flags & SHF_ALLOC))
break;
@@ -1962,8 +1985,8 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
if (((Sec->LMAExpr ||
(Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) &&
Load->LastSec != Out::ProgramHeaders) ||
Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) {

Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags ||
Sec == RelroEnd) {
Load = AddHdr(PT_LOAD, NewFlags);
Flags = NewFlags;
}
@@ -1983,28 +2006,6 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
if (OutputSection *Sec = In.Dynamic->getParent())
AddHdr(PT_DYNAMIC, Sec->getPhdrFlags())->add(Sec);

// PT_GNU_RELRO includes all sections that should be marked as
// read-only by dynamic linker after proccessing relocations.
// Current dynamic loaders only support one PT_GNU_RELRO PHDR, give
// an error message if more than one PT_GNU_RELRO PHDR is required.
PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
bool InRelroPhdr = false;
bool IsRelroFinished = false;
for (OutputSection *Sec : OutputSections) {
if (!needsPtLoad(Sec))
continue;
if (isRelroSection(Sec)) {
InRelroPhdr = true;
if (!IsRelroFinished)
RelRo->add(Sec);
else
error("section: " + Sec->Name + " is not contiguous with other relro" +
" sections");
} else if (InRelroPhdr) {
InRelroPhdr = false;
IsRelroFinished = true;
}
}
if (RelRo->FirstSec)
Ret.push_back(RelRo);

@@ -90,4 +90,4 @@ _start:

// RODATA: Contents of section .rodata:
// S(z) = 0x230014
// RODATA-NEXT: 2002e0 14002300
// RODATA-NEXT: 200318 14002300
@@ -110,7 +110,7 @@ foo:
# CHECK-NEXT: ]

# OBJDUMP: Contents of section .rodata:
# OBJDUMP: d0f8ffff ffffffff
# OBJDUMP: 98f8ffff ffffffff

# OBJDUMP: Contents of section nonalloc:
# OBJDUMP-NEXT: 0000 00000000 14380000 00000000 18340000
@@ -78,4 +78,4 @@ _start:

// RODATA: Contents of section .rodata:
// S(z) = 0x13004
// RODATA-NEXT: 10190 04300100
// RODATA-NEXT: 101b0 04300100
@@ -42,4 +42,4 @@ __aeabi_unwind_cpp_pr0:

// CHECK-EXTAB: Contents of section .ARM.extab:
// 0x0210 + 0x0e20 = 0x1030 = __gxx_personality_v0(PLT)
// CHECK-EXTAB-NEXT: 0210 200e0000 b0b0b000 00000000
// CHECK-EXTAB-NEXT: 0230 000e0000 b0b0b000 00000000
@@ -63,8 +63,8 @@
// CHECK-NEXT: Flags [ (0x2)
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x1C8
// CHECK-NEXT: Offset: 0x1C8
// CHECK-NEXT: Address: 0x200
// CHECK-NEXT: Offset: 0x200
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Link: 3
// CHECK-NEXT: Info: 1
@@ -82,8 +82,8 @@
// CHECK-NEXT: Flags [ (0x2)
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x1E0
// CHECK-NEXT: Offset: 0x1E0
// CHECK-NEXT: Address: 0x218
// CHECK-NEXT: Offset: 0x218
// CHECK-NEXT: Size: 16
// CHECK-NEXT: Link: 1
// CHECK-NEXT: Info: 0
@@ -100,8 +100,8 @@
// CHECK-NEXT: Flags [ (0x2)
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x1F0
// CHECK-NEXT: Offset: 0x1F0
// CHECK-NEXT: Address: 0x228
// CHECK-NEXT: Offset: 0x228
// CHECK-NEXT: Size: 1
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
@@ -146,12 +146,12 @@
// CHECK-NEXT: AddressAlignment: 8
// CHECK-NEXT: EntrySize: 16
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 06000000 00000000 C8010000 00000000 |................|
// CHECK-NEXT: 0010: 0B000000 00000000 18000000 00000000 |................|
// CHECK-NEXT: 0020: 05000000 00000000 F0010000 00000000 |................|
// CHECK-NEXT: 0030: 0A000000 00000000 01000000 00000000 |................|
// CHECK-NEXT: 0040: 04000000 00000000 E0010000 00000000 |................|
// CHECK-NEXT: 0050: 00000000 00000000 00000000 00000000 |................|
// CHECK-NEXT: 0000: 06000000 00000000 00020000 00000000 |
// CHECK-NEXT: 0010: 0B000000 00000000 18000000 00000000 |
// CHECK-NEXT: 0020: 05000000 00000000 28020000 00000000 |
// CHECK-NEXT: 0030: 0A000000 00000000 01000000 00000000 |
// CHECK-NEXT: 0040: 04000000 00000000 18020000 00000000 |
// CHECK-NEXT: 0050: 00000000 00000000 00000000 00000000 |
// CHECK-NEXT: )
// CHECK-NEXT: }
// CHECK-NEXT: Section {
@@ -254,8 +254,8 @@
// CHECK-NEXT: Offset: 0x40
// CHECK-NEXT: VirtualAddress: 0x40
// CHECK-NEXT: PhysicalAddress: 0x40
// CHECK-NEXT: FileSize: 392
// CHECK-NEXT: MemSize: 392
// CHECK-NEXT: FileSize: 448
// CHECK-NEXT: MemSize: 448
// CHECK-NEXT: Flags [ (0x4)
// CHECK-NEXT: PF_R (0x4)
// CHECK-NEXT: ]
@@ -266,8 +266,8 @@
// CHECK-NEXT: Offset: 0x0
// CHECK-NEXT: VirtualAddress: 0x0
// CHECK-NEXT: PhysicalAddress: 0x0
// CHECK-NEXT: FileSize: 497
// CHECK-NEXT: MemSize: 497
// CHECK-NEXT: FileSize: 553
// CHECK-NEXT: MemSize: 553
// CHECK-NEXT: Flags [ (0x4)
// CHECK-NEXT: PF_R (0x4)
// CHECK-NEXT: ]
@@ -292,7 +292,7 @@
// CHECK-NEXT: VirtualAddress: 0x20000
// CHECK-NEXT: PhysicalAddress: 0x20000
// CHECK-NEXT: FileSize: 96
// CHECK-NEXT: MemSize: 65536
// CHECK-NEXT: MemSize: 96
// CHECK-NEXT: Flags [ (0x6)
// CHECK-NEXT: PF_R (0x4)
// CHECK-NEXT: PF_W (0x2)
@@ -8,7 +8,7 @@
## when there are no other relocations except R_*_IRELATIVE.

# CHECK: Name Size VMA
# CHECK: .rela.plt 00000030 0000000000000210
# CHECK: .rela.plt 00000030 0000000000000248
# CHECK: .got.plt 00000010 0000000000003000

# TAGS: Relocations [
@@ -19,7 +19,7 @@
# TAGS-NEXT: ]

# TAGS: Tag Type Name/Value
# TAGS: 0x0000000000000017 JMPREL 0x210
# TAGS: 0x0000000000000017 JMPREL 0x248
# TAGS: 0x0000000000000002 PLTRELSZ 48
# TAGS: 0x0000000000000003 PLTGOT 0x3000
# TAGS: 0x0000000000000014 PLTREL RELA
@@ -9,7 +9,7 @@
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_MERGE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x158
// CHECK-NEXT: Address: 0x178
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size:
// CHECK-NEXT: Link:
@@ -35,7 +35,7 @@
// CHECK-NEXT: AddressAlignment: 1
// CHECK-NEXT: EntrySize: 0
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 58010000 |
// CHECK-NEXT: 0000: 78010000 |
// CHECK-NEXT: )

// The content of .data should be the address of .mysec.
@@ -8,5 +8,5 @@ SECTIONS {
.foo : ALIGN(2M) { *(.foo) }
}

# CHECK: .foo PROGBITS 0000000000200000 201000 000008 00 WA 0 0 2097152
# CHECK: LOAD 0x001048 0x0000000000000048 0x0000000000000048 {{.*}} RW 0x200000
# CHECK: .foo PROGBITS 0000000000200000 200000 000008 00 WA 0 0 2097152
# CHECK: LOAD 0x200000 0x0000000000200000 0x0000000000200000 {{.*}} RW 0x200000
@@ -66,8 +66,8 @@
# RUN: not ld.lld -o %t.so --script %t-both-overlap.script %t.o -shared 2>&1 | FileCheck %s -check-prefix BOTH-OVERLAP-ERR

# BOTH-OVERLAP-ERR: error: section .sec1 file range overlaps with .sec2
# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x9000, 0x90FF]
# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x9040, 0x913F]
# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x2000, 0x20FF]
# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x2040, 0x213F]
# BOTH-OVERLAP-ERR: error: section .sec1 virtual address range overlaps with .sec2
# BOTH-OVERLAP-ERR-NEXT: >>> .sec1 range is [0x8000, 0x80FF]
# BOTH-OVERLAP-ERR-NEXT: >>> .sec2 range is [0x8040, 0x813F]
@@ -93,14 +93,14 @@

# RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t.so | FileCheck %s -check-prefix BAD-BOTH
# BAD-BOTH-LABEL: Section Headers:
# BAD-BOTH: .sec1 PROGBITS 0000000000008000 009000 000100 00 WA 0 0 1
# BAD-BOTH: .sec2 PROGBITS 0000000000008040 009040 000100 00 WA 0 0 1
# BAD-BOTH: .sec1 PROGBITS 0000000000008000 002000 000100 00 WA 0 0 1
# BAD-BOTH: .sec2 PROGBITS 0000000000008040 002040 000100 00 WA 0 0 1
# BAD-BOTH-LABEL: Program Headers:
# BAD-BOTH-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# BAD-BOTH-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000100 0x000100 R E 0x1000
# BAD-BOTH-NEXT: LOAD 0x001100 0x0000000000000100 0x0000000000000100 0x008040 0x008040 RW 0x1000
# BAD-BOTH-NEXT: LOAD 0x001100 0x0000000000000100 0x0000000000000100 0x000070 0x000070 RW 0x1000
# BAD-BOTH-LABEL: Section to Segment mapping:
# BAD-BOTH: 01 .text .dynamic .sec1 .sec2
# BAD-BOTH: 01 .text .dynamic

.section .first_sec,"aw",@progbits
.rept 0x100
@@ -10,13 +10,13 @@
# RUN: llvm-readobj -t %t1 | FileCheck %s

# CHECK: Name: foo1
# CHECK-NEXT: Value: 0x288
# CHECK-NEXT: Value: 0x2C0

# CHECK: Name: foo2
# CHECK-NEXT: Value: 0x290
# CHECK-NEXT: Value: 0x2C8

# CHECK: Name: foo3
# CHECK-NEXT: Value: 0x294
# CHECK-NEXT: Value: 0x2CC

.section .foo.1,"a"
.long 1
@@ -41,22 +41,22 @@ abs = 0xAB5
labs = 0x1AB5

// CHECK: VMA LMA Size Align Out In Symbol
// CHECK-NEXT: 2001c8 2001c8 78 8 .dynsym
// CHECK-NEXT: 2001c8 2001c8 78 8 <internal>:(.dynsym)
// CHECK-NEXT: 200240 200240 2c 8 .gnu.hash
// CHECK-NEXT: 200240 200240 2c 8 <internal>:(.gnu.hash)
// CHECK-NEXT: 20026c 20026c 30 4 .hash
// CHECK-NEXT: 20026c 20026c 30 4 <internal>:(.hash)
// CHECK-NEXT: 20029c 20029c 31 1 .dynstr
// CHECK-NEXT: 20029c 20029c 31 1 <internal>:(.dynstr)
// CHECK-NEXT: 2002d0 2002d0 30 8 .rela.dyn
// CHECK-NEXT: 2002d0 2002d0 30 8 <internal>:(.rela.dyn)
// CHECK-NEXT: 200300 200300 30 8 .rela.plt
// CHECK-NEXT: 200300 200300 30 8 <internal>:(.rela.plt)
// CHECK-NEXT: 200330 200330 64 8 .eh_frame
// CHECK-NEXT: 200330 200330 2c 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x0)
// CHECK-NEXT: 200360 200360 14 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x2c)
// CHECK-NEXT: 200378 200378 18 1 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.eh_frame+0x18)
// CHECK-NEXT: 200200 200200 78 8 .dynsym
// CHECK-NEXT: 200200 200200 78 8 <internal>:(.dynsym)
// CHECK-NEXT: 200278 200278 2c 8 .gnu.hash
// CHECK-NEXT: 200278 200278 2c 8 <internal>:(.gnu.hash)
// CHECK-NEXT: 2002a4 2002a4 30 4 .hash
// CHECK-NEXT: 2002a4 2002a4 30 4 <internal>:(.hash)
// CHECK-NEXT: 2002d4 2002d4 31 1 .dynstr
// CHECK-NEXT: 2002d4 2002d4 31 1 <internal>:(.dynstr)
// CHECK-NEXT: 200308 200308 30 8 .rela.dyn
// CHECK-NEXT: 200308 200308 30 8 <internal>:(.rela.dyn)
// CHECK-NEXT: 200338 200338 30 8 .rela.plt
// CHECK-NEXT: 200338 200338 30 8 <internal>:(.rela.plt)
// CHECK-NEXT: 200368 200368 64 8 .eh_frame
// CHECK-NEXT: 200368 200368 2c 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x0)
// CHECK-NEXT: 200398 200398 14 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x2c)
// CHECK-NEXT: 2003b0 2003b0 18 1 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.eh_frame+0x18)
// CHECK-NEXT: 201000 201000 2d 4 .text
// CHECK-NEXT: 201000 201000 28 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.text)
// CHECK-NEXT: 201000 201000 0 1 _start
@@ -19,10 +19,10 @@
// CHECK-NEXT: SHF_MERGE
// CHECK-NEXT: SHF_STRINGS
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x228
// CHECK-NEXT: Address: 0x260

// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x229
// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x261
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -17,10 +17,10 @@
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_MERGE
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x228
// CHECK-NEXT: Address: 0x260

// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x22A
// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x262
// CHECK-NEXT: }
// CHECK-NEXT: ]
@@ -16,26 +16,26 @@
// CHECK-NEXT: Flags [ (0x2)
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x210
// CHECK-NEXT: Offset: 0x210
// CHECK-NEXT: Address: 0x248
// CHECK-NEXT: Offset: 0x248
// CHECK-NEXT: Size: 22

// CHECK: Name: x (43)
// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
// CHECK-NEXT: Flags [ (0x2)
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x226
// CHECK-NEXT: Offset: 0x226
// CHECK-NEXT: Address: 0x25E
// CHECK-NEXT: Offset: 0x25E
// CHECK-NEXT: Size: 64980

// CHECK: Name: barr (45)
// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
// CHECK-NEXT: Flags [ (0x2)
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0xFFFA
// CHECK-NEXT: Offset: 0xFFFA
// CHECK-NEXT: Address: 0x10032
// CHECK-NEXT: Offset: 0x10032
// CHECK-NEXT: Size: 0

// CHECK: Name: foo (71)
@@ -44,8 +44,8 @@
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: SHF_WRITE (0x1)
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x20004
// CHECK-NEXT: Offset: 0x20004
// CHECK-NEXT: Address: 0x30004
// CHECK-NEXT: Offset: 0x30004
// CHECK-NEXT: Size: 12


0 comments on commit e8710ef

Please sign in to comment.
You can’t perform that action at this time.