From 4514ac7cfb1091c44eb8a60220adb712c7e5622e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 2 Sep 2019 08:49:50 +0000 Subject: [PATCH] [ELF] Align SHT_LLVM_PART_EHDR to a maximum page size boundary Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=998712 SHT_LLVM_PART_EHDR marks the start of a partition. The partition sections will be extracted to a separate file. Align to the next maximum page size boundary so that we can find the ELF header at the start. We cannot benefit from overlapping p_offset ranges with the previous segment anyway. It seems we lack some llvm-objcopy --extract-main-partition and --extract-partition sanity checks. It may place EHDR at the start even if p_offset if non zero. Anyway, the lld change is justified for the reasons above. Reviewed By: ruiu Differential Revision: https://reviews.llvm.org/D67032 llvm-svn: 370629 --- lld/ELF/Writer.cpp | 12 ++++++++++-- lld/test/ELF/partitions.s | 23 +++++++++++++++-------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index df8b9a9..84e969d 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2223,13 +2223,21 @@ template void Writer::fixSectionAlignments() { // the next maximum page size boundary on transitions between executable // and non-executable segments. // + // SHT_LLVM_PART_EHDR marks the start of a partition. The partition + // sections will be extracted to a separate file. Align to the next + // maximum page size boundary so that we can find the ELF header at the + // start. We cannot benefit from overlapping p_offset ranges with the + // previous segment anyway. + // // TODO Enable this technique on all targets. bool enable = config->emachine != EM_HEXAGON && config->emachine != EM_MIPS && config->emachine != EM_X86_64; - if (!enable || (config->zSeparateCode && prev && - (prev->p_flags & PF_X) != (p->p_flags & PF_X))) + if (!enable || + (config->zSeparateCode && prev && + (prev->p_flags & PF_X) != (p->p_flags & PF_X)) || + cmd->type == SHT_LLVM_PART_EHDR) cmd->addrExpr = [] { return alignTo(script->getDot(), config->maxPageSize); }; diff --git a/lld/test/ELF/partitions.s b/lld/test/ELF/partitions.s index 0fb8dcb..5c79f69 100644 --- a/lld/test/ELF/partitions.s +++ b/lld/test/ELF/partitions.s @@ -1,13 +1,20 @@ -// REQUIRES: x86 +// REQUIRES: aarch64, x86 // RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux +// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections -z max-page-size=65536 +// RUN: llvm-readelf -S -s %t | FileCheck %s + +// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=aarch64 // RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections // RUN: llvm-readelf -S -s %t | FileCheck %s // This is basically lld/docs/partitions.dot in object file form. // Test that the sections are correctly allocated to partitions. +// part1 and part2 should be aligned to a maximum page size boundary. // CHECK: [[MAIN:[0-9]+]]] .text +// CHECK: part1 LOOS+0xFFF4C06 {{[0-9a-f]+}}0000 {{[0-9a-f]+}}0000 // CHECK: [[P1:[0-9]+]]] .text +// CHECK: part2 LOOS+0xFFF4C06 {{[0-9a-f]+}}0000 {{[0-9a-f]+}}0000 // CHECK: [[P2:[0-9]+]]] .text // CHECK: Symbol table '.symtab' @@ -30,21 +37,21 @@ .section .text._start,"ax",@progbits .globl _start _start: -call f3 +.quad f3 .section .text.f1,"ax",@progbits .globl f1 f1: -call f3 -call f4 -call f5 +.quad f3 +.quad f4 +.quad f5 .section .text.f2,"ax",@progbits .globl f2 f2: -call f3 -call f5 -call f6 +.quad f3 +.quad f5 +.quad f6 .section .text.f3,"ax",@progbits f3: -- 2.7.4