blob: ed2de5915e5ae5d728653f07bc0c0e57fcf57110 [file] [log] [blame]
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