[lld] 1302fdc - [ELF] Avoid adding an orphan section to a less suitable segment

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 20 21:40:51 PDT 2021


Author: Igor Kudrin
Date: 2021-10-21T11:38:39+07:00
New Revision: 1302fdc233f424dbc8d15d7d88dc894dd6cdbb6c

URL: https://github.com/llvm/llvm-project/commit/1302fdc233f424dbc8d15d7d88dc894dd6cdbb6c
DIFF: https://github.com/llvm/llvm-project/commit/1302fdc233f424dbc8d15d7d88dc894dd6cdbb6c.diff

LOG: [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

Added: 
    lld/test/ELF/linkerscript/orphan-phdrs2.test

Modified: 
    lld/ELF/Writer.cpp
    lld/test/ELF/aarch64-thunk-pi.s
    lld/test/ELF/linkerscript/implicit-program-header.test

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 0e55e9cbdb57b..3e2e9a528353e 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -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;
   }
 

diff  --git a/lld/test/ELF/aarch64-thunk-pi.s b/lld/test/ELF/aarch64-thunk-pi.s
index 12a56bc287631..1f11f127109f9 100644
--- a/lld/test/ELF/aarch64-thunk-pi.s
+++ b/lld/test/ELF/aarch64-thunk-pi.s
@@ -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 at 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 at 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

diff  --git a/lld/test/ELF/linkerscript/implicit-program-header.test b/lld/test/ELF/linkerscript/implicit-program-header.test
index 2e46b3d32153e..3909c6adfffeb 100644
--- a/lld/test/ELF/linkerscript/implicit-program-header.test
+++ b/lld/test/ELF/linkerscript/implicit-program-header.test
@@ -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);

diff  --git a/lld/test/ELF/linkerscript/orphan-phdrs2.test b/lld/test/ELF/linkerscript/orphan-phdrs2.test
new file mode 100644
index 0000000000000..c302e0e70b2bb
--- /dev/null
+++ b/lld/test/ELF/linkerscript/orphan-phdrs2.test
@@ -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
+}


        


More information about the llvm-commits mailing list