[lld] lld: relocate PHDR if sectionStartMap is not empty (PR #140126)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 15 12:29:13 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-elf

Author: Pavel Skripkin (pskrgag)

<details>
<summary>Changes</summary>

`LinkerScript::allocateHeaders()` checks if PHDR segment is located below minimal virtual address provided in linker script. However user could pass section bases via `-T` command line argument, which may lead to unsorted (or overlapping) segments in resulting elf.

To fix it, check PHDR segment when `sectionStartMap` is not empty, which contains bases passed via `-T` argument

Closes #<!-- -->138584 

---
Full diff: https://github.com/llvm/llvm-project/pull/140126.diff


3 Files Affected:

- (modified) lld/ELF/Writer.cpp (+1-1) 
- (modified) lld/test/ELF/sectionstart.s (+24) 
- (modified) lld/test/ELF/ttext-tdata-tbss.s (-2) 


``````````diff
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 28b24f90716b8..a11bc76a0fd18 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -331,7 +331,7 @@ template <class ELFT> void Writer<ELFT>::run() {
   for (OutputSection *sec : ctx.outputSections)
     sec->maybeCompress<ELFT>(ctx);
 
-  if (ctx.script->hasSectionsCommand)
+  if (ctx.script->hasSectionsCommand || !ctx.arg.sectionStartMap.empty())
     ctx.script->allocateHeaders(ctx.mainPart->phdrs);
 
   // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
diff --git a/lld/test/ELF/sectionstart.s b/lld/test/ELF/sectionstart.s
index d694c9375fd80..8eb50263fe6aa 100644
--- a/lld/test/ELF/sectionstart.s
+++ b/lld/test/ELF/sectionstart.s
@@ -11,6 +11,30 @@
 # CHECK-NEXT:    2 .data         00000004 0000000000110000 DATA
 # CHECK-NEXT:    3 .bss          00000004 0000000000200000 BSS
 
+## Check that PHDRS are allocated below .text if .text is below default
+## base for non-pie case
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -Ttext=0x3000 -o %t
+# RUN: llvm-readelf -l %t | FileCheck --check-prefix=CHECK-TEXT %s
+
+# CHECK-TEXT: Program Headers:
+# CHECK-TEXT-NEXT:  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+# CHECK-TEXT-NEXT:  PHDR 0x000040 0x0000000000002040 0x0000000000002040 0x000118 0x000118 R 0x8
+# CHECK-TEXT-NEXT:  LOAD 0x000000 0x0000000000002000 0x0000000000002000 0x000158 0x000158 R 0x1000
+# CHECK-TEXT-NEXT:  LOAD 0x001000 0x0000000000003000 0x0000000000003000 0x000001 0x000001 R E 0x1000
+
+## Check that PHDRS are deleted if they don't fit
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -Ttext=0x0 -o %t
+# RUN: llvm-readelf -l %t | FileCheck --check-prefix=CHECK-TEXT-ZERO %s
+
+# CHECK-TEXT-ZERO: Program Headers:
+# CHECK-TEXT-ZERO-NEXT:  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+# CHECK-TEXT-ZERO-NEXT:  LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000001 0x000001 R E 0x1000
+# CHECK-TEXT-ZERO-NEXT:  LOAD 0x001001 0x0000000000001001 0x0000000000001001 0x000004 0x000008 RW 0x1000
+
 ## The same, but dropped "0x" prefix.
 # RUN: ld.lld %t.o --section-start .text=100000 \
 # RUN:   --section-start .data=110000 --section-start .bss=0x200000 -o %t1
diff --git a/lld/test/ELF/ttext-tdata-tbss.s b/lld/test/ELF/ttext-tdata-tbss.s
index c8254d6969293..01b6e51718b99 100644
--- a/lld/test/ELF/ttext-tdata-tbss.s
+++ b/lld/test/ELF/ttext-tdata-tbss.s
@@ -24,8 +24,6 @@
 # USER1-NEXT: .rodata PROGBITS 0000000000009008 002008 000008
 # USER1-NEXT: .aw     PROGBITS 000000000000a010 002010 000008
 # USER1:      Type
-# USER1-NEXT: PHDR 0x000040 0x0000000000200040
-# USER1-NEXT: LOAD 0x000000 0x0000000000200000
 # USER1-NEXT: LOAD 0x001000 0x0000000000000000
 
 ## Specify --image-base to make program headers look normal.

``````````

</details>


https://github.com/llvm/llvm-project/pull/140126


More information about the llvm-commits mailing list