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

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri May 1 17:16:04 PDT 2020


MaskRay created this revision.
MaskRay added reviewers: grimar, psmith, ruiu.
Herald added subscribers: llvm-commits, kristof.beyls, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D79254

Files:
  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


Index: lld/test/ELF/linkerscript/nobits-offset.s
===================================================================
--- lld/test/ELF/linkerscript/nobits-offset.s
+++ 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 {{$}}
 
Index: lld/test/ELF/linkerscript/empty-sections-expressions.test
===================================================================
--- lld/test/ELF/linkerscript/empty-sections-expressions.test
+++ 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 {
Index: lld/test/ELF/linkerscript/at8.test
===================================================================
--- lld/test/ELF/linkerscript/at8.test
+++ lld/test/ELF/linkerscript/at8.test
@@ -20,7 +20,7 @@
 # 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
Index: lld/ELF/Writer.cpp
===================================================================
--- lld/ELF/Writer.cpp
+++ lld/ELF/Writer.cpp
@@ -153,14 +153,23 @@
 }
 
 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() {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D79254.261510.patch
Type: text/x-patch
Size: 3710 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200502/ab9f6c5e/attachment.bin>


More information about the llvm-commits mailing list