Avoid empty .eh_frame sections.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 2 May 2017 15:45:31 +0000 (15:45 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 2 May 2017 15:45:31 +0000 (15:45 +0000)
Strip on OpenBSD does not correctly handle an empty .eh_frame section
and produces broken binaries in that case. Currently lld creates such
an empty .eh_frame section, despite the fact that the OpenBSD crtend.o
explicitly inserts a terminator. The Linux LSB "standard":

https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html#EHFRAME

explicitly says that

    The .eh_frame section shall contain 1 or more Call Frame Information (CFI) records.

This diff includes a test that specifically tests the issue I'm seeing
on OpenBSD.

Patch by Mark Kettenis!

llvm-svn: 301931

lld/ELF/SyntheticSections.cpp
lld/test/ELF/Inputs/eh-frame-end.s [new file with mode: 0644]
lld/test/ELF/eh-frame-begin-end.s [new file with mode: 0644]

index 66445d0..a271d31 100644 (file)
@@ -541,6 +541,13 @@ template <class ELFT> void EhFrameSection<ELFT>::finalizeContents() {
       Off += alignTo(Fde->size(), Config->Wordsize);
     }
   }
+
+  // The LSB standard does not allow a .eh_frame section with zero
+  // Call Frame Information records. Therefore add a CIE record length
+  // 0 as a terminator if this .eh_frame section is empty.
+  if (Off == 0)
+    Off = 4;
+
   this->Size = Off;
 }
 
diff --git a/lld/test/ELF/Inputs/eh-frame-end.s b/lld/test/ELF/Inputs/eh-frame-end.s
new file mode 100644 (file)
index 0000000..b7334d8
--- /dev/null
@@ -0,0 +1,2 @@
+       .section ".eh_frame", "a", @progbits
+       .long 0
diff --git a/lld/test/ELF/eh-frame-begin-end.s b/lld/test/ELF/eh-frame-begin-end.s
new file mode 100644 (file)
index 0000000..a7f0bb7
--- /dev/null
@@ -0,0 +1,17 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %p/Inputs/eh-frame-end.s -o %t2.o
+// RUN: ld.lld %t.o %t2.o -o %t
+// RUN: llvm-readobj -sections %t | FileCheck %s
+
+// CHECK:      Name: .eh_frame
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT:   SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x200120
+// CHECK-NEXT: Offset: 0x120
+// CHECK-NEXT: Size: 4
+
+       .section ".eh_frame", "a", @progbits
+__EH_FRAME_BEGIN__: