mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
[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
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {{$}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user