[PATCH] D18911: ELF: Emit .eh_frame_hdr entries for FDEs with duplicate PCs.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 8 15:03:05 PDT 2016


pcc created this revision.
pcc added reviewers: ruiu, rafael.
pcc added a subscriber: llvm-commits.

It is possible to have FDEs with duplicate PCs if ICF was able to merge
functions with FDEs, or if the input files for some reason contained duplicate
FDEs.  We previously weren't handling this correctly when producing the
contents of the .eh_frame_hdr section; we were dropping entries and leaving
null entries at the end of the section, which confused consumers of unwind
data, such as the backtrace() function.

Fix the bug by collecting the FDEs into a std::multimap rather than a std::map.

http://reviews.llvm.org/D18911

Files:
  ELF/OutputSections.cpp
  test/ELF/eh-frame-hdr-icf.s

Index: test/ELF/eh-frame-hdr-icf.s
===================================================================
--- /dev/null
+++ test/ELF/eh-frame-hdr-icf.s
@@ -0,0 +1,26 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr
+# RUN: llvm-objdump -s %t2 | FileCheck %s
+
+# CHECK: Contents of section .eh_frame_hdr:
+# CHECK-NEXT: 101a0 011b033b b4ffffff 02000000 600e0000
+# CHECK-NEXT: 101b0 d0ffffff 600e0000 e8ffffff
+#                   ^ FDE for f1      ^ FDE for f2
+
+.globl _start, f1, f2
+_start:
+  ret
+
+.section .text.f1, "ax"
+f1:
+  .cfi_startproc
+  ret
+  .cfi_endproc
+
+.section .text.f2, "ax"
+f2:
+  .cfi_startproc
+  ret
+  .cfi_endproc
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -746,11 +746,13 @@
   Buf += 12;
 
   // InitialPC -> Offset in .eh_frame, sorted by InitialPC.
-  std::map<uintX_t, size_t> PcToOffset;
+  // We use a multimap in order to handle duplicate PCs, which can happen if ICF
+  // was able to merge functions with FDEs.
+  std::multimap<uintX_t, size_t> PcToOffsets;
   for (const FdeData &F : FdeList)
-    PcToOffset[getFdePc(EhVA, F)] = F.Off;
+    PcToOffsets.insert({getFdePc(EhVA, F), F.Off});
 
-  for (auto &I : PcToOffset) {
+  for (auto &I : PcToOffsets) {
     // The first four bytes are an offset to the initial PC value for the FDE.
     write32<E>(Buf, I.first - VA);
     // The last four bytes are an offset to the FDE data itself.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D18911.53096.patch
Type: text/x-patch
Size: 1585 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160408/07a9f4e9/attachment.bin>


More information about the llvm-commits mailing list