[ELF] Don't shrink RelrSection
authorFangrui Song <maskray@google.com>
Wed, 4 Sep 2019 16:27:35 +0000 (16:27 +0000)
committerFangrui Song <maskray@google.com>
Wed, 4 Sep 2019 16:27:35 +0000 (16:27 +0000)
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
lld/test/ELF/pack-dyn-relocs-relr-loop.s [new file with mode: 0644]

index 2bd9dc2..e323eca 100644 (file)
@@ -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 (file)
index 0000000..3fd524a
--- /dev/null
@@ -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