[PATCH] [ELF] Use pcrel format for eh_frame_ptr field encoding

Simon Atanasyan simon at atanasyan.com
Sun Mar 15 23:32:26 PDT 2015


Hi shankarke, ruiu,

The `eh_frame_ptr` field in the `.eh_frame_hdr` section contains an address of the `.eh_frame` section. Using an absolute 32-bit format for encoding of this field does not work for 64-bit targets. It is better to use a relative format because it covers both 32-bit and 64-bit cases. Sure this work if a distance between `.eh_frame_hdr` and `.eh_frame` sections is less than 4 Gb. I think it is a rather correct assumption.

REPOSITORY
  rL LLVM

http://reviews.llvm.org/D8352

Files:
  lib/ReaderWriter/ELF/SectionChunks.h
  test/elf/eh_frame_hdr.test

Index: lib/ReaderWriter/ELF/SectionChunks.h
===================================================================
--- lib/ReaderWriter/ELF/SectionChunks.h
+++ lib/ReaderWriter/ELF/SectionChunks.h
@@ -1436,7 +1436,8 @@
 public:
   EHFrameHeader(const ELFLinkingContext &context, StringRef name,
                 TargetLayout<ELFT> &layout, int32_t order)
-      : Section<ELFT>(context, name, "EHFrameHeader"), _layout(layout) {
+      : Section<ELFT>(context, name, "EHFrameHeader"), _ehFrameOffset(0),
+        _layout(layout) {
     this->setOrder(order);
     this->_entSize = 0;
     this->_type = SHT_PROGBITS;
@@ -1453,24 +1454,27 @@
 
   void finalize() override {
     OutputSection<ELFT> *s = _layout.findOutputSection(".eh_frame");
-    _ehFrameAddr = s ? s->virtualAddr() : 0;
+    OutputSection<ELFT> *h = _layout.findOutputSection(".eh_frame_hdr");
+    if (s && h)
+      _ehFrameOffset = s->virtualAddr() - (h->virtualAddr() + 4);
   }
 
-  virtual void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
-                     llvm::FileOutputBuffer &buffer) override {
+  void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
+             llvm::FileOutputBuffer &buffer) override {
     uint8_t *chunkBuffer = buffer.getBufferStart();
     uint8_t *dest = chunkBuffer + this->fileOffset();
     int pos = 0;
     dest[pos++] = 1; // version
-    dest[pos++] = llvm::dwarf::DW_EH_PE_udata4; // eh_frame_ptr_enc
+    dest[pos++] = llvm::dwarf::DW_EH_PE_pcrel |
+                  llvm::dwarf::DW_EH_PE_sdata4; // eh_frame_ptr_enc
     dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // fde_count_enc
     dest[pos++] = llvm::dwarf::DW_EH_PE_omit; // table_enc
-    *reinterpret_cast<typename llvm::object::ELFFile<ELFT>::Elf_Word *>(
-         dest + pos) = (uint32_t)_ehFrameAddr;
+    *reinterpret_cast<typename llvm::object::ELFFile<ELFT>::Elf_Sword *>(
+        dest + pos) = _ehFrameOffset;
   }
 
 private:
-  uint64_t _ehFrameAddr;
+  int32_t _ehFrameOffset;
   TargetLayout<ELFT> &_layout;
 };
 } // end namespace elf
Index: test/elf/eh_frame_hdr.test
===================================================================
--- test/elf/eh_frame_hdr.test
+++ test/elf/eh_frame_hdr.test
@@ -1,7 +1,7 @@
 #RUN: yaml2obj -format=elf %s > %t
 #RUN: lld -flavor gnu -target x86_64-linux %t --noinhibit-exec \
 #RUN:   -o %t1
-#RUN: llvm-readobj -s %t1 | FileCheck %s
+#RUN: llvm-objdump -s %t1 | FileCheck %s
 
 !ELF
 FileHeader:
@@ -23,4 +23,8 @@
     Type: STT_SECTION
     Section: .eh_frame
 
-#CHECK: .eh_frame_hdr
+# CHECK:      Contents of section .eh_frame:
+# CHECK-NEXT:  4001e0 00
+# CHECK-NEXT: Contents of section .eh_frame_hdr:
+# CHECK-NEXT:  4001e8 011bffff f4ffffff
+#                              ^ 0x4001e0 - 0x4001e8 - 4 = 0xfffffff4

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D8352.22012.patch
Type: text/x-patch
Size: 2766 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150316/37c7ccd9/attachment.bin>


More information about the llvm-commits mailing list