[llvm] r359105 - [JITLink] Refer to FDE's CIE (not the most recent CIE) when parsing eh-frame.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 24 08:15:55 PDT 2019


Author: lhames
Date: Wed Apr 24 08:15:55 2019
New Revision: 359105

URL: http://llvm.org/viewvc/llvm-project?rev=359105&view=rev
Log:
[JITLink] Refer to FDE's CIE (not the most recent CIE) when parsing eh-frame.

Frame Descriptor Entries (FDEs) have a pointer back to a Common Information
Entry (CIE) that describes how the rest FDE should be parsed. JITLink had been
assuming that FDEs always referred to the most recent CIE encountered, but the
spec allows them to point back to any previously encountered CIE. This patch
fixes JITLink to look up the correct CIE for the FDE.

The testcase is a MachO binary with an FDE that refers to a CIE that is not the
one immediately proceeding it (the layout can be viewed wit
'dwarfdump --eh-frame <testcase>'. This test case had to be a binary as llvm-mc
now sorts FDEs (as of r356216) to ensure FDEs *do* point to the most recent CIE.

Added:
    llvm/trunk/test/ExecutionEngine/JITLink/X86/Inputs/
    llvm/trunk/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o
    llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
Modified:
    llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
    llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
    llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s
    llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp

Modified: llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp?rev=359105&r1=359104&r2=359105&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp Wed Apr 24 08:15:55 2019
@@ -163,8 +163,7 @@ Error EHFrameParser::processCIE() {
 
   LLVM_DEBUG(dbgs() << "  Record is CIE\n");
 
-  /// Reset state for the new CIE.
-  LSDAFieldPresent = false;
+  CIEInformation CIEInfo(*CurRecordAtom);
 
   uint8_t Version = 0;
   if (auto Err = EHFrameReader.readInteger(Version))
@@ -219,7 +218,7 @@ Error EHFrameParser::processCIE() {
   while (uint8_t Field = *NextField++) {
     switch (Field) {
     case 'L': {
-      LSDAFieldPresent = true;
+      CIEInfo.FDEsHaveLSDAField = true;
       uint8_t LSDAPointerEncoding;
       if (auto Err = EHFrameReader.readInteger(LSDAPointerEncoding))
         return Err;
@@ -268,6 +267,10 @@ Error EHFrameParser::processCIE() {
     return make_error<JITLinkError>("Read past the end of the augmentation "
                                     "data while parsing fields");
 
+  assert(!CIEInfos.count(CurRecordAtom->getAddress()) &&
+         "Multiple CIEs recorded at the same address?");
+  CIEInfos[CurRecordAtom->getAddress()] = std::move(CIEInfo);
+
   return Error::success();
 }
 
@@ -280,14 +283,18 @@ Error EHFrameParser::processFDE(JITTarge
            << format("0x%016" PRIx64, CIEPointerAddress - CIEPointer) << "\n";
   });
 
-  auto CIEAtom = G.findAtomByAddress(CIEPointerAddress - CIEPointer);
-  if (!CIEAtom)
-    return CIEAtom.takeError();
+  auto CIEInfoItr = CIEInfos.find(CIEPointerAddress - CIEPointer);
+  if (CIEInfoItr == CIEInfos.end())
+    return make_error<JITLinkError>(
+        "FDE at " + formatv("{0:x16}", CurRecordAtom->getAddress()) +
+        " points to non-existant CIE at " +
+        formatv("{0:x16}", CIEPointerAddress - CIEPointer));
+  auto &CIEInfo = CIEInfoItr->second;
 
   // The CIEPointer looks good. Add a relocation.
   CurRecordAtom->addEdge(FDEToCIERelocKind,
                          CIEPointerAddress - CurRecordAtom->getAddress(),
-                         *CIEAtom, 0);
+                         *CIEInfo.CIEAtom, 0);
 
   // Read and sanity check the PC-start pointer and size.
   JITTargetAddress PCBeginAddress = EHFrameAddress + EHFrameReader.getOffset();
@@ -329,15 +336,15 @@ Error EHFrameParser::processFDE(JITTarge
   if (auto Err = EHFrameReader.skip(G.getPointerSize()))
     return Err;
 
-  if (LSDAFieldPresent) {
+  if (CIEInfo.FDEsHaveLSDAField) {
     uint64_t AugmentationDataSize;
     if (auto Err = EHFrameReader.readULEB128(AugmentationDataSize))
       return Err;
     if (AugmentationDataSize != G.getPointerSize())
-      return make_error<JITLinkError>("Unexpected FDE augmentation data size "
-                                      "(expected " +
-                                      Twine(G.getPointerSize()) + ", got " +
-                                      Twine(AugmentationDataSize) + ")");
+      return make_error<JITLinkError>(
+          "Unexpected FDE augmentation data size (expected " +
+          Twine(G.getPointerSize()) + ", got " + Twine(AugmentationDataSize) +
+          ") for FDE at " + formatv("{0:x16}", CurRecordAtom->getAddress()));
     JITTargetAddress LSDAAddress = EHFrameAddress + EHFrameReader.getOffset();
     auto LSDADelta = readAbsolutePointer();
     if (!LSDADelta)

Modified: llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h?rev=359105&r1=359104&r2=359105&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h (original)
+++ llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h Wed Apr 24 08:15:55 2019
@@ -44,13 +44,20 @@ private:
   Error processCIE();
   Error processFDE(JITTargetAddress CIEPointerAddress, uint32_t CIEPointer);
 
+  struct CIEInformation {
+    CIEInformation() = default;
+    CIEInformation(DefinedAtom &CIEAtom) : CIEAtom(&CIEAtom) {}
+    DefinedAtom *CIEAtom = nullptr;
+    bool FDEsHaveLSDAField = false;
+  };
+
   AtomGraph &G;
   Section &EHFrameSection;
   StringRef EHFrameContent;
   JITTargetAddress EHFrameAddress;
   BinaryStreamReader EHFrameReader;
   DefinedAtom *CurRecordAtom = nullptr;
-  bool LSDAFieldPresent = false;
+  DenseMap<JITTargetAddress, CIEInformation> CIEInfos;
   Edge::Kind FDEToCIERelocKind;
   Edge::Kind FDEToTargetRelocKind;
 };

Added: llvm/trunk/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o?rev=359105&view=auto
==============================================================================
Binary files llvm/trunk/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o (added) and llvm/trunk/test/ExecutionEngine/JITLink/X86/Inputs/MachO_x86-64_ehframe.o Wed Apr 24 08:15:55 2019 differ

Added: llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test?rev=359105&view=auto
==============================================================================
--- llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test (added)
+++ llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test Wed Apr 24 08:15:55 2019
@@ -0,0 +1,5 @@
+# RUN: llvm-jitlink -noexec  %S/Inputs/MachO_x86-64_ehframe.o
+#
+# Perform a no-exec link of MachO_x86-64_ehframe and verify that it does not
+# generate any errors despite the last FDE referring to the first CIE (rather
+# than the most recent).
\ No newline at end of file

Modified: llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s?rev=359105&r1=359104&r2=359105&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s (original)
+++ llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s Wed Apr 24 08:15:55 2019
@@ -1,6 +1,6 @@
 # RUN: rm -rf %t && mkdir -p %t
-# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/test_x86-64.o %s
-# RUN: llvm-jitlink -noexec -define-abs external_data=0xdeadbeef -define-abs external_func=0xcafef00d -check=%s %t/test_x86-64.o
+# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t/macho_reloc.o %s
+# RUN: llvm-jitlink -noexec -define-abs external_data=0xdeadbeef -define-abs external_func=0xcafef00d -check=%s %t/macho_reloc.o
 
         .section        __TEXT,__text,regular,pure_instructions
 
@@ -32,8 +32,8 @@ _main:
 # Validate both the reference to the GOT entry, and also the content of the GOT
 # entry.
 #
-# jitlink-check: decode_operand(test_gotld, 4) = got_addr(test_x86-64.o, external_data) - next_pc(test_gotld)
-# jitlink-check: *{8}(got_addr(test_x86-64.o, external_data)) = external_data
+# jitlink-check: decode_operand(test_gotld, 4) = got_addr(macho_reloc.o, external_data) - next_pc(test_gotld)
+# jitlink-check: *{8}(got_addr(macho_reloc.o, external_data)) = external_data
         .globl  test_gotld
         .align  4, 0x90
 test_gotld:
@@ -43,8 +43,8 @@ test_gotld:
 # Check that calls to external functions trigger the generation of stubs and GOT
 # entries.
 #
-# jitlink-check: decode_operand(test_external_call, 0) = stub_addr(test_x86-64.o, external_func) - next_pc(test_external_call)
-# jitlink-check: *{8}(got_addr(test_x86-64.o, external_func)) = external_func
+# jitlink-check: decode_operand(test_external_call, 0) = stub_addr(macho_reloc.o, external_func) - next_pc(test_external_call)
+# jitlink-check: *{8}(got_addr(macho_reloc.o, external_func)) = external_func
         .globl  test_external_call
         .align  4, 0x90
 test_external_call:
@@ -84,22 +84,22 @@ signed4:
         movl $0xAAAAAAAA, named_data(%rip)
 
         .globl signedanon
-# jitlink-check: decode_operand(signedanon, 4) = section_addr(test_x86-64.o, __data) - next_pc(signedanon)
+# jitlink-check: decode_operand(signedanon, 4) = section_addr(macho_reloc.o, __data) - next_pc(signedanon)
 signedanon:
         movq Lanon_data(%rip), %rax
 
         .globl signed1anon
-# jitlink-check: decode_operand(signed1anon, 3) = section_addr(test_x86-64.o, __data) - next_pc(signed1anon)
+# jitlink-check: decode_operand(signed1anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed1anon)
 signed1anon:
         movb $0xAA, Lanon_data(%rip)
 
         .globl signed2anon
-# jitlink-check: decode_operand(signed2anon, 3) = section_addr(test_x86-64.o, __data) - next_pc(signed2anon)
+# jitlink-check: decode_operand(signed2anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed2anon)
 signed2anon:
         movw $0xAAAA, Lanon_data(%rip)
 
         .globl signed4anon
-# jitlink-check: decode_operand(signed4anon, 3) = section_addr(test_x86-64.o, __data) - next_pc(signed4anon)
+# jitlink-check: decode_operand(signed4anon, 3) = section_addr(macho_reloc.o, __data) - next_pc(signed4anon)
 signed4anon:
         movl $0xAAAAAAAA, Lanon_data(%rip)
 
@@ -117,13 +117,13 @@ Lanon_data:
 # invalid because the minuend can not be local.
 #
 # Note: +8 offset in expression below to accounts for sizeof(Lanon_data).
-# jitlink-check: *{8}(section_addr(test_x86-64.o, __data) + 8) = (section_addr(test_x86-64.o, __data) + 8) - named_data + 2
+# jitlink-check: *{8}(section_addr(macho_reloc.o, __data) + 8) = (section_addr(macho_reloc.o, __data) + 8) - named_data + 2
         .p2align  3
 Lanon_minuend_quad:
         .quad Lanon_minuend_quad - named_data + 2
 
 # Note: +16 offset in expression below to accounts for sizeof(Lanon_data) + sizeof(Lanon_minuend_long).
-# jitlink-check: *{4}(section_addr(test_x86-64.o, __data) + 16) = ((section_addr(test_x86-64.o, __data) + 16) - named_data + 2)[31:0]
+# jitlink-check: *{4}(section_addr(macho_reloc.o, __data) + 16) = ((section_addr(macho_reloc.o, __data) + 16) - named_data + 2)[31:0]
         .p2align  2
 Lanon_minuend_long:
         .long Lanon_minuend_long - named_data + 2
@@ -147,7 +147,7 @@ named_func_addr:
 # Check X86_64_RELOC_UNSIGNED / non-extern handling by putting the address of a
 # local anonymous function in a pointer variable.
 #
-# jitlink-check: *{8}anon_func_addr = section_addr(test_x86-64.o, __text)
+# jitlink-check: *{8}anon_func_addr = section_addr(macho_reloc.o, __text)
         .globl  anon_func_addr
         .p2align  3
 anon_func_addr:
@@ -155,7 +155,7 @@ anon_func_addr:
 
 # X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend
 #
-# jitlink-check: *{8}minuend_quad1 = section_addr(test_x86-64.o, __data) - minuend_quad1 + 2
+# jitlink-check: *{8}minuend_quad1 = section_addr(macho_reloc.o, __data) - minuend_quad1 + 2
 # Only the form "B: .quad LA - B + C" is tested. The form "B: .quad B - LA + C" is
 # invalid because the minuend can not be local.
         .globl  minuend_quad1
@@ -163,7 +163,7 @@ anon_func_addr:
 minuend_quad1:
         .quad Lanon_data - minuend_quad1 + 2
 
-# jitlink-check: *{4}minuend_long1 = (section_addr(test_x86-64.o, __data) - minuend_long1 + 2)[31:0]
+# jitlink-check: *{4}minuend_long1 = (section_addr(macho_reloc.o, __data) - minuend_long1 + 2)[31:0]
         .globl  minuend_long1
         .p2align  2
 minuend_long1:

Modified: llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp?rev=359105&r1=359104&r2=359105&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp (original)
+++ llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp Wed Apr 24 08:15:55 2019
@@ -326,14 +326,37 @@ Session::findSymbolInfo(StringRef Symbol
 
 } // end namespace llvm
 
+Triple getFirstFileTriple() {
+  assert(!InputFiles.empty() && "InputFiles can not be empty");
+  auto ObjBuffer =
+      ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
+  auto Obj = ExitOnErr(
+      object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
+  return Obj->makeTriple();
+}
+
+void setEntryPointNameIfNotProvided(const Session &S) {
+  if (EntryPointName.empty()) {
+    if (S.TT.getObjectFormat() == Triple::MachO)
+      EntryPointName = "_main";
+    else
+      EntryPointName = "main";
+  }
+}
+
 Error loadProcessSymbols(Session &S) {
   std::string ErrMsg;
   if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, &ErrMsg))
     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
 
   char GlobalPrefix = S.TT.getObjectFormat() == Triple::MachO ? '_' : '\0';
-  S.ES.getMainJITDylib().setGenerator(ExitOnErr(
-      orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(GlobalPrefix)));
+  auto InternedEntryPointName = S.ES.intern(EntryPointName);
+  auto FilterMainEntryPoint = [InternedEntryPointName](SymbolStringPtr Name) {
+    return Name != InternedEntryPointName;
+  };
+  S.ES.getMainJITDylib().setGenerator(
+      ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
+          GlobalPrefix, FilterMainEntryPoint)));
 
   return Error::success();
 }
@@ -352,15 +375,6 @@ Error loadDylibs() {
   return Error::success();
 }
 
-Triple getFirstFileTriple() {
-  assert(!InputFiles.empty() && "InputFiles can not be empty");
-  auto ObjBuffer =
-      ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
-  auto Obj = ExitOnErr(
-      object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
-  return Obj->makeTriple();
-}
-
 Error loadObjects(Session &S) {
 
   std::map<unsigned, JITDylib *> IdxToJLD;
@@ -542,16 +556,6 @@ static void dumpSessionStats(Session &S)
 }
 
 static Expected<JITEvaluatedSymbol> getMainEntryPoint(Session &S) {
-
-  // First, if the entry point has not been set, set it to a sensible default
-  // for this process.
-  if (EntryPointName.empty()) {
-    if (S.TT.getObjectFormat() == Triple::MachO)
-      EntryPointName = "_main";
-    else
-      EntryPointName = "main";
-  }
-
   return S.ES.lookup(S.JDSearchOrder, EntryPointName);
 }
 
@@ -584,6 +588,8 @@ int main(int argc, char *argv[]) {
 
   Session S(getFirstFileTriple());
 
+  setEntryPointNameIfNotProvided(S);
+
   if (!NoProcessSymbols)
     ExitOnErr(loadProcessSymbols(S));
   ExitOnErr(loadDylibs());




More information about the llvm-commits mailing list