| From 7afffb54eac8c7aedc8c24f75ccdd70b176a9d9f Mon Sep 17 00:00:00 2001 |
| From: Fangrui Song <maskray@google.com> |
| Date: Wed, 4 Sep 2019 16:27:35 +0000 |
| Subject: [PATCH] [ELF] Don't shrink RelrSection |
| |
| Fixes PR43214. |
| |
| The size of SHT_RELR may oscillate between 2 numbers (see D53003 for a |
| similar --pack-dyn-relocs=android issue). This can happen if the shrink |
| of SHT_RELR causes it to take more words to encode relocation offsets |
| (this can happen with thunks or segments with overlapping p_offset |
| ranges), and the expansion of SHT_RELR causes it to take fewer words to |
| encode relocation offsets. |
| |
| To avoid the issue, add padding 1s to the end of the relocation section |
| if its size would decrease. Trailing 1s do not decode to more relocations. |
| |
| Reviewed By: peter.smith |
| |
| Differential Revision: https://reviews.llvm.org/D67164 |
| |
| llvm-svn: 370923 |
| --- |
| lld/ELF/SyntheticSections.cpp | 8 ++++++ |
| lld/test/ELF/pack-dyn-relocs-relr-loop.s | 36 ++++++++++++++++++++++++ |
| 2 files changed, 44 insertions(+) |
| create mode 100644 lld/test/ELF/pack-dyn-relocs-relr-loop.s |
| |
| diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp |
| index 2bd9dc2d341..e323ecaa9d7 100644 |
| --- a/lld/ELF/SyntheticSections.cpp |
| +++ b/lld/ELF/SyntheticSections.cpp |
| @@ -1957,6 +1957,14 @@ template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() { |
| } |
| } |
| |
| + // Don't allow the section to shrink; otherwise the size of the section can |
| + // oscillate infinitely. Trailing 1s do not decode to more relocations. |
| + if (relrRelocs.size() < oldSize) { |
| + log(".relr.dyn needs " + Twine(oldSize - relrRelocs.size()) + |
| + " padding word(s)"); |
| + relrRelocs.resize(oldSize, Elf_Relr(1)); |
| + } |
| + |
| return relrRelocs.size() != oldSize; |
| } |
| |
| diff --git a/lld/test/ELF/pack-dyn-relocs-relr-loop.s b/lld/test/ELF/pack-dyn-relocs-relr-loop.s |
| new file mode 100644 |
| index 00000000000..3fd524a65dc |
| --- /dev/null |
| +++ b/lld/test/ELF/pack-dyn-relocs-relr-loop.s |
| @@ -0,0 +1,36 @@ |
| +# REQUIRES: aarch64 |
| +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o |
| +# RUN: ld.lld -pie --pack-dyn-relocs=relr -z max-page-size=4096 --verbose %t.o -o %t 2>&1 | FileCheck %s |
| +# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELR %s |
| + |
| +## This test makes sure we don't shrink .relr.dyn, otherwise its size may |
| +## oscillate between 2 words and 3 words. |
| + |
| +## The test is very sensitive to the exact section sizes and offsets, |
| +## make sure .data is located at a page boundary. |
| + |
| +# CHECK: .relr.dyn needs 1 padding word(s) |
| + |
| +# RELR: .relr.dyn { |
| +# RELR-NEXT: 0x2F40 R_AARCH64_RELATIVE - 0x0 |
| +# RELR-NEXT: 0x2F48 R_AARCH64_RELATIVE - 0x0 |
| +# RELR-NEXT: 0x3000 R_AARCH64_RELATIVE - 0x0 |
| +# RELR-NEXT: } |
| + |
| +.section .data.rel.ro |
| +.align 3 |
| +.space 0xce0 |
| +foo: |
| +## Encoded by the first word of .relr.dyn |
| +.quad foo |
| + |
| +## Encoded by the second word of .relr.dyn |
| +.quad foo |
| + |
| +.section .data |
| +.align 3 |
| +## If .data is at 0x3000, the relocation will be encoded by the second word. |
| +## If we shrink .relr.dyn, the end of .dynamic will be at 0x2ff8 and .data |
| +## will be at 0x3ff8, we will need the third word to encode this relocation, |
| +## which will cause .relr.dyn to expand again. |
| +.quad foo |
| -- |
| 2.23.0.700.g56cf767bdb-goog |
| |