forked from OSchip/llvm-project
[ELF] Avoid adding an orphan section to a less suitable segment
If segments are defined in a linker script, placing an orphan section before the found closest-rank section can result in adding it in a previous segment and changing flags of that segment. This happens if the orphan section has a lower sort rank than the found section. To avoid that, the patch forces orphan sections to be moved after the found section if segments are explicitly defined. Differential Revision: https://reviews.llvm.org/D111717
This commit is contained in:
parent
66b650f3da
commit
1302fdc233
|
@ -1255,15 +1255,24 @@ findOrphanPos(std::vector<BaseCommand *>::iterator b,
|
|||
});
|
||||
if (i == e)
|
||||
return e;
|
||||
auto foundSec = dyn_cast<OutputSection>(*i);
|
||||
if (!foundSec)
|
||||
return e;
|
||||
|
||||
// Consider all existing sections with the same proximity.
|
||||
int proximity = getRankProximity(sec, *i);
|
||||
unsigned sortRank = sec->sortRank;
|
||||
if (script->hasPhdrsCommands())
|
||||
// Prevent the orphan section to be placed before the found section because
|
||||
// that can result in adding it to a previous segment and changing flags of
|
||||
// that segment, for example, making a read-only segment writable.
|
||||
sortRank = std::max(sortRank, foundSec->sortRank);
|
||||
for (; i != e; ++i) {
|
||||
auto *curSec = dyn_cast<OutputSection>(*i);
|
||||
if (!curSec || !curSec->hasInputSections)
|
||||
continue;
|
||||
if (getRankProximity(sec, curSec) != proximity ||
|
||||
sec->sortRank < curSec->sortRank)
|
||||
sortRank < curSec->sortRank)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ low_target:
|
|||
bl high_target
|
||||
ret
|
||||
// CHECK: <low_target>:
|
||||
// CHECK-NEXT: d8: bl 0xec <__AArch64ADRPThunk_high_target>
|
||||
// CHECK-NEXT: 0: bl 0x14 <__AArch64ADRPThunk_high_target>
|
||||
// CHECK-NEXT: ret
|
||||
|
||||
.hidden low_target2
|
||||
|
@ -28,23 +28,23 @@ low_target2:
|
|||
bl .text_high+8
|
||||
ret
|
||||
// CHECK: <low_target2>:
|
||||
// CHECK-NEXT: e0: bl 0xf8 <__AArch64ADRPThunk_high_target2>
|
||||
// CHECK-NEXT: e4: bl 0x104 <__AArch64ADRPThunk_>
|
||||
// CHECK-NEXT: 8: bl 0x20 <__AArch64ADRPThunk_high_target2>
|
||||
// CHECK-NEXT: c: bl 0x2c <__AArch64ADRPThunk_>
|
||||
// CHECK-NEXT: ret
|
||||
|
||||
// Expect range extension thunks for .text_low
|
||||
// adrp calculation is (PC + signed immediate) & (!0xfff)
|
||||
// CHECK: <__AArch64ADRPThunk_high_target>:
|
||||
// CHECK-NEXT: ec: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: 14: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: add x16, x16, #0x40
|
||||
// CHECK-NEXT: br x16
|
||||
// CHECK: <__AArch64ADRPThunk_high_target2>:
|
||||
// CHECK-NEXT: f8: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: 20: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: add x16, x16, #0x8
|
||||
// CHECK-NEXT: br x16
|
||||
/// Identical to the previous one, but for the target .text_high+8.
|
||||
// CHECK: <__AArch64ADRPThunk_>:
|
||||
// CHECK-NEXT: 104: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: 2c: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: add x16, x16, #0x8
|
||||
// CHECK-NEXT: br x16
|
||||
|
||||
|
@ -75,7 +75,7 @@ high_target2:
|
|||
|
||||
// CHECK: <__AArch64ADRPThunk_low_target2>:
|
||||
// CHECK-NEXT: 10000010: adrp x16, 0x0
|
||||
// CHECK-NEXT: add x16, x16, #0xe0
|
||||
// CHECK-NEXT: add x16, x16, #0x8
|
||||
// CHECK-NEXT: br x16
|
||||
|
||||
// CHECK: Disassembly of section .plt:
|
||||
|
@ -83,8 +83,8 @@ high_target2:
|
|||
// CHECK-NEXT: <.plt>:
|
||||
// CHECK-NEXT: 10000020: stp x16, x30, [sp, #-0x10]!
|
||||
// CHECK-NEXT: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: ldr x17, [x16, #0x120]
|
||||
// CHECK-NEXT: add x16, x16, #0x120
|
||||
// CHECK-NEXT: ldr x17, [x16, #0x1f8]
|
||||
// CHECK-NEXT: add x16, x16, #0x1f8
|
||||
// CHECK-NEXT: br x17
|
||||
// CHECK-NEXT: nop
|
||||
// CHECK-NEXT: nop
|
||||
|
@ -92,14 +92,14 @@ high_target2:
|
|||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: <high_target@plt>:
|
||||
// CHECK-NEXT: 10000040: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: ldr x17, [x16, #0x128]
|
||||
// CHECK-NEXT: add x16, x16, #0x128
|
||||
// CHECK-NEXT: ldr x17, [x16, #0x200]
|
||||
// CHECK-NEXT: add x16, x16, #0x200
|
||||
// CHECK-NEXT: br x17
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: <low_target@plt>:
|
||||
// CHECK-NEXT: 10000050: adrp x16, 0x10000000
|
||||
// CHECK-NEXT: ldr x17, [x16, #0x130]
|
||||
// CHECK-NEXT: add x16, x16, #0x130
|
||||
// CHECK-NEXT: ldr x17, [x16, #0x208]
|
||||
// CHECK-NEXT: add x16, x16, #0x208
|
||||
// CHECK-NEXT: br x17
|
||||
|
||||
//--- lds
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
# RUN: llvm-readelf -l %t1 | FileCheck %s
|
||||
|
||||
# CHECK: Segment Sections...
|
||||
# CHECK-NEXT: 00 .dynsym .hash .dynstr .text
|
||||
# CHECK-NEXT: 01 .foo .dynamic
|
||||
# CHECK-NEXT: 02 .foo .dynamic
|
||||
# CHECK-NEXT: 00 .text
|
||||
# CHECK-NEXT: 01 .foo .dynsym .hash .dynstr .dynamic
|
||||
# CHECK-NEXT: 02 .foo .dynsym .hash .dynstr .dynamic
|
||||
|
||||
PHDRS {
|
||||
ph_write PT_LOAD FLAGS(2);
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: split-file %s %ts
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64 %ts/s -o %t.o
|
||||
# RUN: ld.lld -pie -o %t -T %ts/t %t.o
|
||||
# RUN: llvm-readelf -l %t | FileCheck %s
|
||||
|
||||
## Check that an orphan section '.dynamic' is added to the same segment as
|
||||
## its closest-rank section '.data', even though its sort rank is lower.
|
||||
## Adding '.dynamic' to the first segment would make the segment writable.
|
||||
# CHECK: Program Headers:
|
||||
# CHECK-NEXT: Type {{.*}} Flg Align
|
||||
# CHECK-NEXT: LOAD {{.*}} R E 0x
|
||||
# CHECK-NEXT: LOAD {{.*}} RW 0x
|
||||
# CHECK-MEXT: LOAD {{.*}} R 0x
|
||||
|
||||
# CHECK: Segment Sections...
|
||||
# CHECK-NEXT: 00 .text {{$}}
|
||||
# CHECK-NEXT: 01 .data .dynamic {{$}}
|
||||
## Check that read-only non-PROGBITS orphan sections are placed after the
|
||||
## closest-rank section '.rodata' despite their sort ranks are lower.
|
||||
# CHECK-NEXT: 02 .rodata .dynsym .gnu.hash .hash .dynstr {{$}}
|
||||
|
||||
#--- s
|
||||
.text
|
||||
nop
|
||||
|
||||
.data
|
||||
.quad 0
|
||||
|
||||
.rodata
|
||||
.quad 0
|
||||
|
||||
#--- t
|
||||
PHDRS {
|
||||
exec PT_LOAD;
|
||||
rw PT_LOAD;
|
||||
ro PT_LOAD;
|
||||
}
|
||||
SECTIONS {
|
||||
.text : { *(.text) } : exec
|
||||
.data : { *(.data) } : rw
|
||||
.rodata : { *(.rodata) } : ro
|
||||
}
|
Loading…
Reference in New Issue