[lld] r337382 - [ELF] - Stop silently producing a broken .eh_frame_hdr.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 18 04:56:53 PDT 2018


Author: grimar
Date: Wed Jul 18 04:56:53 2018
New Revision: 337382

URL: http://llvm.org/viewvc/llvm-project?rev=337382&view=rev
Log:
[ELF] - Stop silently producing a broken .eh_frame_hdr.

Currently, getFdePC() returns uint64_t. Its because the following
encodings might use 8 bytes: DW_EH_PE_absptr and DW_EH_PE_udata8.

But caller assigns returned value to uint32_t field:
https://github.com/llvm-mirror/lld/blob/master/ELF/SyntheticSections.cpp#L508

Value is used for building .eh_frame_hdr section.
We use DW_EH_PE_sdata4 encoding for building it at this moment:
https://github.com/llvm-mirror/lld/blob/master/ELF/SyntheticSections.cpp#L2545

And that means that an overflow issue might happen if
DW_EH_PE_absptr/DW_EH_PE_udata8 address encodings are present
in .eh_frame. In that case, before this patch, we silently would
truncate the address and produced broken .eh_frame_hdr section.

It would be not hard to support real 64-bit values for
DW_EH_PE_absptr/DW_EH_PE_udata8 encodings, but it is
unclear if it is usefull and if we should do it.

Since nobody faced/reported it, int this patch I only implement
a check to stop producing broken output silently for now.

Added:
    lld/trunk/test/ELF/eh-frame-pcaddr-overflow.s
Modified:
    lld/trunk/ELF/SyntheticSections.cpp

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=337382&r1=337381&r2=337382&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Jul 18 04:56:53 2018
@@ -505,9 +505,11 @@ std::vector<EhFrameSection::FdeData> EhF
   for (CieRecord *Rec : CieRecords) {
     uint8_t Enc = getFdeEncoding(Rec->Cie);
     for (EhSectionPiece *Fde : Rec->Fdes) {
-      uint32_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
+      uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);
+      if (Pc > UINT32_MAX)
+        fatal(toString(Fde->Sec) + ": PC address is too large: " + Twine(Pc));
       uint32_t FdeVA = getParent()->Addr + Fde->OutputOff;
-      Ret.push_back({Pc, FdeVA});
+      Ret.push_back({(uint32_t)Pc, FdeVA});
     }
   }
   return Ret;

Added: lld/trunk/test/ELF/eh-frame-pcaddr-overflow.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/eh-frame-pcaddr-overflow.s?rev=337382&view=auto
==============================================================================
--- lld/trunk/test/ELF/eh-frame-pcaddr-overflow.s (added)
+++ lld/trunk/test/ELF/eh-frame-pcaddr-overflow.s Wed Jul 18 04:56:53 2018
@@ -0,0 +1,32 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld --eh-frame-hdr --section-start .text=0x1000000000000000 \
+# RUN:   %t.o -o /dev/null 2>&1 | FileCheck %s
+# CHECK: error: {{.*}}.o:(.eh_frame): PC address is too large: 2387527121043355528
+
+.text
+.global foo
+foo:
+ nop
+
+.section .eh_frame, "a"
+  .long 12   # Size
+  .long 0x00 # ID
+  .byte 0x01 # Version.
+  
+  .byte 0x52 # Augmentation string: 'R','\0'
+  .byte 0x00
+  
+  .byte 0x01
+  
+  .byte 0x01 # LEB128
+  .byte 0x01 # LEB128
+
+  .byte 0x00 # DW_EH_PE_absptr
+
+  .byte 0xFF
+ 
+  .long 12  # Size
+  .long 0x14 # ID
+  .quad foo + 0x1122334455667788




More information about the llvm-commits mailing list