Skip to content

Commit 501ad1d

Browse files
committed
Merging r369828:
------------------------------------------------------------------------ r369828 | maskray | 2019-08-24 02:41:15 +0200 (Sat, 24 Aug 2019) | 18 lines [ELF] Align the first section of a PT_LOAD even if its type is SHT_NOBITS Reported at https://reviews.llvm.org/D64930#1642223 If the only section of a PT_LOAD is a SHT_NOBITS section (e.g. .bss), we may not align its sh_offset. p_offset of the PT_LOAD will be set to sh_offset, and we will get p_offset!=p_vaddr (mod p_align). If such executable is mapped by the Linux kernel, it will segfault. After D64906, this may happen the non-linker script case. The linker script case has had this issue for a long time. This was fixed by rL321657 (but the test linkerscript/nobits-offset.s failed to test a SHT_NOBITS section), but broken by rL345154. Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D66658 ------------------------------------------------------------------------ llvm-svn: 371196
1 parent 5fc0367 commit 501ad1d

File tree

5 files changed

+56
-27
lines changed

5 files changed

+56
-27
lines changed

lld/ELF/Writer.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,25 +2230,26 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
22302230
// same with its virtual address modulo the page size, so that the loader can
22312231
// load executables without any address adjustment.
22322232
static uint64_t computeFileOffset(OutputSection *os, uint64_t off) {
2233-
// File offsets are not significant for .bss sections. By convention, we keep
2234-
// section offsets monotonically increasing rather than setting to zero.
2235-
if (os->type == SHT_NOBITS)
2236-
return off;
2237-
2238-
// If the section is not in a PT_LOAD, we just have to align it.
2239-
if (!os->ptLoad)
2240-
return alignTo(off, os->alignment);
2241-
22422233
// The first section in a PT_LOAD has to have congruent offset and address
22432234
// module the page size.
2244-
OutputSection *first = os->ptLoad->firstSec;
2245-
if (os == first) {
2235+
if (os->ptLoad && os->ptLoad->firstSec == os) {
22462236
uint64_t alignment = std::max<uint64_t>(os->alignment, config->maxPageSize);
22472237
return alignTo(off, alignment, os->addr);
22482238
}
22492239

2240+
// File offsets are not significant for .bss sections other than the first one
2241+
// in a PT_LOAD. By convention, we keep section offsets monotonically
2242+
// increasing rather than setting to zero.
2243+
if (os->type == SHT_NOBITS)
2244+
return off;
2245+
2246+
// If the section is not in a PT_LOAD, we just have to align it.
2247+
if (!os->ptLoad)
2248+
return alignTo(off, os->alignment);
2249+
22502250
// If two sections share the same PT_LOAD the file offset is calculated
22512251
// using this formula: Off2 = Off1 + (VA2 - VA1).
2252+
OutputSection *first = os->ptLoad->firstSec;
22522253
return first->offset + os->addr - first->addr;
22532254
}
22542255

lld/test/ELF/basic-ppc64.s

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
// CHECK-NEXT: Version: 1
3636
// CHECK-NEXT: Entry: 0x10000
3737
// CHECK-NEXT: ProgramHeaderOffset: 0x40
38-
// CHECK-NEXT: SectionHeaderOffset: 0x200F8
38+
// CHECK-NEXT: SectionHeaderOffset: 0x30098
3939
// CHECK-NEXT: Flags [ (0x2)
4040
// CHECK-NEXT: 0x2
4141
// CHECK-NEXT: ]
@@ -178,7 +178,7 @@
178178
// CHECK-NEXT: SHF_WRITE (0x1)
179179
// CHECK-NEXT: ]
180180
// CHECK-NEXT: Address: 0x30000
181-
// CHECK-NEXT: Offset: 0x20060
181+
// CHECK-NEXT: Offset: 0x30000
182182
// CHECK-NEXT: Size: 0
183183
// CHECK-NEXT: Link: 0
184184
// CHECK-NEXT: Info: 0
@@ -194,7 +194,7 @@
194194
// CHECK-NEXT: SHF_STRINGS (0x20)
195195
// CHECK-NEXT: ]
196196
// CHECK-NEXT: Address: 0x0
197-
// CHECK-NEXT: Offset: 0x20060
197+
// CHECK-NEXT: Offset: 0x30000
198198
// CHECK-NEXT: Size: 8
199199
// CHECK-NEXT: Link: 0
200200
// CHECK-NEXT: Info: 0
@@ -211,7 +211,7 @@
211211
// CHECK-NEXT: Flags [ (0x0)
212212
// CHECK-NEXT: ]
213213
// CHECK-NEXT: Address: 0x0
214-
// CHECK-NEXT: Offset: 0x20068
214+
// CHECK-NEXT: Offset: 0x30008
215215
// CHECK-NEXT: Size: 48
216216
// CHECK-NEXT: Link: 10
217217
// CHECK-NEXT: Info: 2
@@ -233,7 +233,7 @@
233233
// CHECK-NEXT: Flags [ (0x0)
234234
// CHECK-NEXT: ]
235235
// CHECK-NEXT: Address: 0x0
236-
// CHECK-NEXT: Offset: 0x20098
236+
// CHECK-NEXT: Offset: 0x30038
237237
// CHECK-NEXT: Size: 84
238238
// CHECK-NEXT: Link: 0
239239
// CHECK-NEXT: Info: 0
@@ -255,7 +255,7 @@
255255
// CHECK-NEXT: Flags [ (0x0)
256256
// CHECK-NEXT: ]
257257
// CHECK-NEXT: Address: 0x0
258-
// CHECK-NEXT: Offset: 0x200EC
258+
// CHECK-NEXT: Offset: 0x3008C
259259
// CHECK-NEXT: Size: 10
260260
// CHECK-NEXT: Link: 0
261261
// CHECK-NEXT: Info: 0

lld/test/ELF/linkerscript/nobits-offset.s

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,24 @@
22
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
33
# RUN: echo "SECTIONS { \
44
# RUN: .sec1 (NOLOAD) : { . += 1; } \
5-
# RUN: .text : { *(.text) } \
5+
# RUN: .bss : { *(.bss) } \
66
# RUN: };" > %t.script
77
# RUN: ld.lld %t.o -T %t.script -o %t
8-
# RUN: llvm-readelf --sections %t | FileCheck %s
8+
# RUN: llvm-readelf -S -l %t | FileCheck %s
99

10-
# We used to misalign section offsets if the first section in a
11-
# PT_LOAD was SHT_NOBITS.
10+
## If a SHT_NOBITS section is the only section of a PT_LOAD segment,
11+
## p_offset will be set to the sh_offset field of the section. Check we align
12+
## sh_offset to sh_addr modulo max-page-size, so that p_vaddr=p_offset (mod
13+
## p_align).
1214

13-
# CHECK: [ 2] .text PROGBITS 0000000000000010 001010 000010 00 AX 0 0 16
15+
# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
16+
# CHECK: .bss NOBITS 0000000000000400 001400 000001 00 WA 0 0 1024
1417

15-
.global _start
16-
_start:
17-
nop
18-
.p2align 4
18+
# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
19+
# CHECK: LOAD 0x001400 0x0000000000000400 0x0000000000000400 0x000000 0x000001 RW 0x1000
20+
21+
# CHECK: 00 .bss
22+
23+
.bss
24+
.p2align 10
25+
.byte 0

lld/test/ELF/nobits-offset.s

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# REQUIRES: aarch64
2+
# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
3+
# RUN: ld.lld %t.o -o %t
4+
# RUN: llvm-readelf -S -l %t | FileCheck %s
5+
6+
## If a SHT_NOBITS section is the only section of a PT_LOAD segment,
7+
## p_offset will be set to the sh_offset field of the section. Check we align
8+
## sh_offset to sh_addr modulo max-page-size, so that p_vaddr=p_offset (mod
9+
## p_align).
10+
11+
# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
12+
# CHECK: .bss NOBITS 0000000000210000 010000 000001 00 WA 0 0 4096
13+
14+
# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
15+
# CHECK: LOAD 0x010000 0x0000000000210000 0x0000000000210000 0x000000 0x000001 RW 0x10000
16+
17+
# CHECK: 02 .bss
18+
19+
.bss
20+
.p2align 12
21+
.byte 0

lld/test/ELF/relocation-copy-align-common.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# CHECK-NEXT: SHF_WRITE
1616
# CHECK-NEXT: ]
1717
# CHECK-NEXT: Address: 0x203000
18-
# CHECK-NEXT: Offset: 0x20B0
18+
# CHECK-NEXT: Offset: 0x3000
1919
# CHECK-NEXT: Size: 16
2020
# CHECK-NEXT: Link: 0
2121
# CHECK-NEXT: Info: 0

0 commit comments

Comments
 (0)