[lld] c49f83b - [ELF] Don't advance sh_offset for an empty section whose PT_LOAD is removed (due to p_memsz=0)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon May 4 08:11:08 PDT 2020


Author: Fangrui Song
Date: 2020-05-04T08:07:34-07:00
New Revision: c49f83b6e9e383ac9df02ab4d95974d7bb1e5ddc

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

LOG: [ELF] Don't advance sh_offset for an empty section whose PT_LOAD is removed (due to p_memsz=0)

removeEmptyPTLoad() removes empty (p_memsz=0) PT_LOAD segments.  In
assignFileOffsets(), setFileOffset() unnecessarily advances file offsets
for containing empty sections.

This is exposed by arm Linux kernel's multi_v5_defconfig
(see https://bugs.llvm.org/show_bug.cgi?id=45632)

```
ld.lld (max-page-size=65536):
  [34] .init.data        PROGBITS        c0c24000 c34000 0128ac 00  WA  0   0 4096
  [35] .text_itcm        PROGBITS        fffe0000 c50000 000000 00  WA  0   0  1
  [36] .data_dtcm        PROGBITS        fffe8000 c58000 000000 00  WA  0   0  1
  [37] .data             PROGBITS        c0c38000 c58000 0647a0 00  WA  0   0 32

arm-linux-gnueabi-ld (max-page-size=65536):
  [23] .init.data        PROGBITS        c0c12000 c22000 0128ac 00  WA  0   0 4096
  [24] .text_itcm        PROGBITS        fffe0000 ca2558 000000 00   W  0   0  1
  [25] .data_dtcm        PROGBITS        fffe8000 ca2558 000000 00   W  0   0  1
  [26] .data             PROGBITS        c0c26000 c36000 0647a0 00  WA  0   0 32
```

This patch clears OutputSection::ptLoad if ptLoad is removed by
removeEmptyPTLoad(). Conceptually this removes "dangling" references.

Reviewed By: psmith

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

Added: 
    

Modified: 
    lld/ELF/Writer.cpp
    lld/test/ELF/linkerscript/at8.test
    lld/test/ELF/linkerscript/empty-sections-expressions.test
    lld/test/ELF/linkerscript/nobits-offset.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index b5a8c33ddd8d..5fa4c44355f4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -153,14 +153,23 @@ template <class ELFT> void writeResult() {
 }
 
 static void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) {
-  llvm::erase_if(phdrs, [&](const PhdrEntry *p) {
-    if (p->p_type != PT_LOAD)
-      return false;
-    if (!p->firstSec)
-      return true;
-    uint64_t size = p->lastSec->addr + p->lastSec->size - p->firstSec->addr;
-    return size == 0;
-  });
+  auto it = std::stable_partition(
+      phdrs.begin(), phdrs.end(), [&](const PhdrEntry *p) {
+        if (p->p_type != PT_LOAD)
+          return true;
+        if (!p->firstSec)
+          return false;
+        uint64_t size = p->lastSec->addr + p->lastSec->size - p->firstSec->addr;
+        return size != 0;
+      });
+
+  // Clear OutputSection::ptLoad for sections contained in removed
+  // segments.
+  DenseSet<PhdrEntry *> removed(it, phdrs.end());
+  for (OutputSection *sec : outputSections)
+    if (removed.count(sec->ptLoad))
+      sec->ptLoad = nullptr;
+  phdrs.erase(it, phdrs.end());
 }
 
 void copySectionsIntoPartitions() {

diff  --git a/lld/test/ELF/linkerscript/at8.test b/lld/test/ELF/linkerscript/at8.test
index ab0e3c63095d..c611c2e24404 100644
--- a/lld/test/ELF/linkerscript/at8.test
+++ b/lld/test/ELF/linkerscript/at8.test
@@ -20,7 +20,7 @@ SECTIONS {
 # PT_LOAD header.
 
 # CHECK: Name              Type            Address          Off
-# CHECK: .text             PROGBITS        0000000008000000 001000
+# CHECK: .text             PROGBITS        0000000008000000 000158
 # CHECK: .sec1             PROGBITS        0000000020000000 001000
 # CHECK: .sec2             PROGBITS        0000000020000008 001008
 # CHECK: .sec3             PROGBITS        0000000020000010 001010

diff  --git a/lld/test/ELF/linkerscript/empty-sections-expressions.test b/lld/test/ELF/linkerscript/empty-sections-expressions.test
index ebc43f453a32..ed6c45de6656 100644
--- a/lld/test/ELF/linkerscript/empty-sections-expressions.test
+++ b/lld/test/ELF/linkerscript/empty-sections-expressions.test
@@ -9,7 +9,7 @@
 
 # CHECK:      Name   Type     Address          Off    Size
 # CHECK-NEXT:        NULL     0000000000000000 000000 000000
-# CHECK-NEXT: .empty PROGBITS 0000000000080000 001000 000000
+# CHECK-NEXT: .empty PROGBITS 0000000000080000 000158 000000
 # CHECK-NEXT: .text  PROGBITS 0000000000080000 001000 000001
 # CHECK-NEXT: .data  PROGBITS 0000000000080001 001001 000001
 
@@ -19,7 +19,7 @@
 # CHECK-NEXT:  LOAD 0x001001 0x0000000000080001 0x0000000000082000
 
 # CHECK:      Section to Segment mapping:
-# CHECK:       00 .empty .text {{$}}
+# CHECK:       00 .text {{$}}
 # CHECK-NEXT:  01 .data {{$}}
 
 SECTIONS {

diff  --git a/lld/test/ELF/linkerscript/nobits-offset.s b/lld/test/ELF/linkerscript/nobits-offset.s
index 682190c0d78f..35397ec330ea 100644
--- a/lld/test/ELF/linkerscript/nobits-offset.s
+++ b/lld/test/ELF/linkerscript/nobits-offset.s
@@ -14,12 +14,12 @@
 
 # CHECK:      Name  Type     Address          Off     Size
 # CHECK-NEXT:       NULL     0000000000000000 000000  000000
-# CHECK-NEXT: .text PROGBITS 0000000000000000 001000  000000
-# CHECK-NEXT: .sec1 NOBITS   0000000000000000 001000  000001
-# CHECK-NEXT: .bss  NOBITS   0000000000000400 001400  000001
+# CHECK-NEXT: .text PROGBITS 0000000000000000 000158  000000
+# CHECK-NEXT: .sec1 NOBITS   0000000000000000 000158  000001
+# CHECK-NEXT: .bss  NOBITS   0000000000000400 000400  000001
 
 # CHECK:      Type Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
-# CHECK-NEXT: LOAD 0x001400 0x0000000000000400 0x0000000000000400 0x000000 0x000001 RW  0x1000
+# CHECK-NEXT: LOAD 0x000400 0x0000000000000400 0x0000000000000400 0x000000 0x000001 RW  0x1000
 
 # CHECK:      00 .bss {{$}}
 


        


More information about the llvm-commits mailing list