[PATCH] D101116: [ELF] Support .rela.eh_frame with unordered r_offset values

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 29 08:51:27 PDT 2021


This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc9b1bd101289: [ELF] Support .rela.eh_frame with unordered r_offset values (authored by MaskRay).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101116/new/

https://reviews.llvm.org/D101116

Files:
  lld/ELF/InputSection.cpp
  lld/ELF/Relocations.cpp
  lld/ELF/Relocations.h
  lld/test/ELF/eh-frame-unordered-r_offset.s


Index: lld/test/ELF/eh-frame-unordered-r_offset.s
===================================================================
--- /dev/null
+++ lld/test/ELF/eh-frame-unordered-r_offset.s
@@ -0,0 +1,30 @@
+# REQUIRES: x86
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/a.s -o %t/a.o
+# RUN: cp %t/a.o %t/b.o
+# RUN: ld.lld -r -T %t/lds %t/a.o %t/b.o -o %t/c.o
+# RUN: llvm-readelf -r %t/c.o | FileCheck %s --check-prefix=REL
+
+## If we swap two input .eh_frame, the r_offset values in relocations will be
+## unordered.
+# REL:          Offset
+# REL-NEXT: 0000000000000050
+# REL-NEXT: 0000000000000020
+
+## Test we can handle the rare case.
+# RUN: ld.lld %t/c.o -o %t/c
+# RUN: llvm-dwarfdump --eh-frame %t/c | FileCheck %s
+
+# CHECK: 00000000 00000014 00000000 CIE
+# CHECK: 00000018 00000014 0000001c FDE cie=00000000
+# CHECK: 00000030 00000014 00000034 FDE cie=00000000
+
+#--- a.s
+.cfi_startproc
+nop
+.cfi_endproc
+
+#--- lds
+SECTIONS {
+  .eh_frame : { *b.o(.eh_frame) *a.o(.eh_frame) }
+}
Index: lld/ELF/Relocations.h
===================================================================
--- lld/ELF/Relocations.h
+++ lld/ELF/Relocations.h
@@ -196,6 +196,19 @@
 static inline int64_t getAddend(const typename ELFT::Rela &rel) {
   return rel.r_addend;
 }
+
+template <typename RelTy>
+ArrayRef<RelTy> sortRels(ArrayRef<RelTy> rels, SmallVector<RelTy, 0> &storage) {
+  auto cmp = [](const RelTy &a, const RelTy &b) {
+    return a.r_offset < b.r_offset;
+  };
+  if (!llvm::is_sorted(rels, cmp)) {
+    storage.assign(rels.begin(), rels.end());
+    llvm::stable_sort(storage, cmp);
+    rels = storage;
+  }
+  return rels;
+}
 } // namespace elf
 } // namespace lld
 
Index: lld/ELF/Relocations.cpp
===================================================================
--- lld/ELF/Relocations.cpp
+++ lld/ELF/Relocations.cpp
@@ -1576,6 +1576,13 @@
   if (config->emachine == EM_PPC64)
     checkPPC64TLSRelax<RelTy>(sec, rels);
 
+  // For EhInputSection, OffsetGetter expects the relocations to be sorted by
+  // r_offset. In rare cases (.eh_frame pieces are reordered by a linker
+  // script), the relocations may be unordered.
+  SmallVector<RelTy, 0> storage;
+  if (isa<EhInputSection>(sec))
+    rels = sortRels(rels, storage);
+
   for (auto i = rels.begin(), end = rels.end(); i != end;)
     scanReloc<ELFT>(sec, getOffset, i, rels.begin(), end);
 
Index: lld/ELF/InputSection.cpp
===================================================================
--- lld/ELF/InputSection.cpp
+++ lld/ELF/InputSection.cpp
@@ -1326,6 +1326,11 @@
 
 template <class ELFT, class RelTy>
 void EhInputSection::split(ArrayRef<RelTy> rels) {
+  // getReloc expects the relocations to be sorted by r_offset. See the comment
+  // in scanRelocs.
+  SmallVector<RelTy, 0> storage;
+  rels = sortRels(rels, storage);
+
   unsigned relI = 0;
   for (size_t off = 0, end = data().size(); off != end;) {
     size_t size = readEhRecordSize(this, off);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D101116.341535.patch
Type: text/x-patch
Size: 2965 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210429/8087cc74/attachment.bin>


More information about the llvm-commits mailing list