[llvm] 6884fbc - [JITLink] Enable exception handling for ELF.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 24 20:31:37 PST 2021


Author: Lang Hames
Date: 2021-01-25T15:31:27+11:00
New Revision: 6884fbc2c4fb46d0528c02d16d510f4f725fac11

URL: https://github.com/llvm/llvm-project/commit/6884fbc2c4fb46d0528c02d16d510f4f725fac11
DIFF: https://github.com/llvm/llvm-project/commit/6884fbc2c4fb46d0528c02d16d510f4f725fac11.diff

LOG: [JITLink] Enable exception handling for ELF.

Adds the EHFrameSplitter and EHFrameEdgeFixer passes to the default JITLink
pass pipeline for ELF/x86-64, and teaches EHFrameEdgeFixer to handle some
new pointer encodings.

Together these changes enable exception handling (at least for the basic
cases that I've tested so far) for ELF/x86-64 objects loaded via JITLink.

Added: 
    llvm/test/ExecutionEngine/JITLink/X86/ELF_ehframe_basic.s

Modified: 
    llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
    llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
    llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
    llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
    llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
index 8b730bc23ce0..3602601287f4 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
@@ -119,9 +119,10 @@ Error EHFrameSplitter::processBlock(LinkGraph &G, Block &B,
 }
 
 EHFrameEdgeFixer::EHFrameEdgeFixer(StringRef EHFrameSectionName,
-                                   Edge::Kind Delta64, Edge::Kind NegDelta32)
-    : EHFrameSectionName(EHFrameSectionName), Delta64(Delta64),
-      NegDelta32(NegDelta32) {}
+                                   unsigned PointerSize, Edge::Kind Delta64,
+                                   Edge::Kind Delta32, Edge::Kind NegDelta32)
+    : EHFrameSectionName(EHFrameSectionName), PointerSize(PointerSize),
+      Delta64(Delta64), Delta32(Delta32), NegDelta32(NegDelta32) {}
 
 Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
   auto *EHFrame = G.findSectionByName(EHFrameSectionName);
@@ -134,6 +135,11 @@ Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
     return Error::success();
   }
 
+  // Check that we support the graph's pointer size.
+  if (G.getPointerSize() != 4 && G.getPointerSize() != 8)
+    return make_error<JITLinkError>(
+        "EHFrameEdgeFixer only supports 32 and 64 bit targets");
+
   LLVM_DEBUG({
     dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n";
   });
@@ -258,7 +264,6 @@ Error EHFrameEdgeFixer::processBlock(ParseContext &PC, Block &B) {
 Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
                                    size_t RecordOffset, size_t RecordLength,
                                    size_t CIEDeltaFieldOffset) {
-  using namespace dwarf;
 
   LLVM_DEBUG(dbgs() << "      Record is CIE\n");
 
@@ -329,11 +334,12 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
       uint8_t LSDAPointerEncoding;
       if (auto Err = RecordReader.readInteger(LSDAPointerEncoding))
         return Err;
-      if (LSDAPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
+      if (!isSupportedPointerEncoding(LSDAPointerEncoding))
         return make_error<JITLinkError>(
             "Unsupported LSDA pointer encoding " +
             formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " +
             formatv("{0:x16}", CIESymbol.getAddress()));
+      CIEInfo.LSDAPointerEncoding = LSDAPointerEncoding;
       break;
     }
     case 'P': {
@@ -341,7 +347,8 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
       if (auto Err = RecordReader.readInteger(PersonalityPointerEncoding))
         return Err;
       if (PersonalityPointerEncoding !=
-          (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4))
+          (dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
+           dwarf::DW_EH_PE_sdata4))
         return make_error<JITLinkError>(
             "Unspported personality pointer "
             "encoding " +
@@ -356,12 +363,12 @@ Error EHFrameEdgeFixer::processCIE(ParseContext &PC, Block &B,
       uint8_t FDEPointerEncoding;
       if (auto Err = RecordReader.readInteger(FDEPointerEncoding))
         return Err;
-      if (FDEPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
+      if (!isSupportedPointerEncoding(FDEPointerEncoding))
         return make_error<JITLinkError>(
-            "Unsupported FDE address pointer "
-            "encoding " +
+            "Unsupported FDE pointer encoding " +
             formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " +
             formatv("{0:x16}", CIESymbol.getAddress()));
+      CIEInfo.FDEPointerEncoding = FDEPointerEncoding;
       break;
     }
     default:
@@ -445,11 +452,13 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
     JITTargetAddress PCBeginFieldOffset = RecordReader.getOffset();
     auto PCEdgeItr = BlockEdges.find(RecordOffset + PCBeginFieldOffset);
     if (PCEdgeItr == BlockEdges.end()) {
-      auto PCBeginDelta = readAbsolutePointer(PC.G, RecordReader);
-      if (!PCBeginDelta)
-        return PCBeginDelta.takeError();
-      JITTargetAddress PCBegin =
-          RecordAddress + PCBeginFieldOffset + *PCBeginDelta;
+      auto PCBeginPtrInfo =
+          readEncodedPointer(CIEInfo->FDEPointerEncoding,
+                             RecordAddress + PCBeginFieldOffset, RecordReader);
+      if (!PCBeginPtrInfo)
+        return PCBeginPtrInfo.takeError();
+      JITTargetAddress PCBegin = PCBeginPtrInfo->first;
+      Edge::Kind PCBeginEdgeKind = PCBeginPtrInfo->second;
       LLVM_DEBUG({
         dbgs() << "        Adding edge at "
                << formatv("{0:x16}", RecordAddress + PCBeginFieldOffset)
@@ -458,7 +467,8 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
       auto PCBeginSym = getOrCreateSymbol(PC, PCBegin);
       if (!PCBeginSym)
         return PCBeginSym.takeError();
-      B.addEdge(Delta64, RecordOffset + PCBeginFieldOffset, *PCBeginSym, 0);
+      B.addEdge(PCBeginEdgeKind, RecordOffset + PCBeginFieldOffset, *PCBeginSym,
+                0);
       PCBeginBlock = &PCBeginSym->getBlock();
     } else {
       auto &EI = PCEdgeItr->second;
@@ -479,38 +489,42 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
                                         " points at external block");
       }
       PCBeginBlock = &EI.Target->getBlock();
-      if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
+      if (auto Err = RecordReader.skip(
+              getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
         return Err;
     }
 
     // Add a keep-alive edge from the FDE target to the FDE to ensure that the
     // FDE is kept alive if its target is.
     assert(PCBeginBlock && "PC-begin block not recorded");
+    LLVM_DEBUG({
+      dbgs() << "        Adding keep-alive edge from target at "
+             << formatv("{0:x16}", PCBeginBlock->getAddress()) << " to FDE at "
+             << formatv("{0:x16}", RecordAddress) << "\n";
+    });
     PCBeginBlock->addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
   }
 
   // Skip over the PC range size field.
-  if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
+  if (auto Err = RecordReader.skip(
+          getPointerEncodingDataSize(CIEInfo->FDEPointerEncoding)))
     return Err;
 
   if (CIEInfo->FDEsHaveLSDAField) {
     uint64_t AugmentationDataSize;
     if (auto Err = RecordReader.readULEB128(AugmentationDataSize))
       return Err;
-    if (AugmentationDataSize != PC.G.getPointerSize())
-      return make_error<JITLinkError>(
-          "Unexpected FDE augmentation data size (expected " +
-          Twine(PC.G.getPointerSize()) + ", got " +
-          Twine(AugmentationDataSize) + ") for FDE at " +
-          formatv("{0:x16}", RecordAddress));
 
     JITTargetAddress LSDAFieldOffset = RecordReader.getOffset();
     auto LSDAEdgeItr = BlockEdges.find(RecordOffset + LSDAFieldOffset);
     if (LSDAEdgeItr == BlockEdges.end()) {
-      auto LSDADelta = readAbsolutePointer(PC.G, RecordReader);
-      if (!LSDADelta)
-        return LSDADelta.takeError();
-      JITTargetAddress LSDA = RecordAddress + LSDAFieldOffset + *LSDADelta;
+      auto LSDAPointerInfo =
+          readEncodedPointer(CIEInfo->LSDAPointerEncoding,
+                             RecordAddress + LSDAFieldOffset, RecordReader);
+      if (!LSDAPointerInfo)
+        return LSDAPointerInfo.takeError();
+      JITTargetAddress LSDA = LSDAPointerInfo->first;
+      Edge::Kind LSDAEdgeKind = LSDAPointerInfo->second;
       auto LSDASym = getOrCreateSymbol(PC, LSDA);
       if (!LSDASym)
         return LSDASym.takeError();
@@ -519,7 +533,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
                << formatv("{0:x16}", RecordAddress + LSDAFieldOffset)
                << " to LSDA at " << formatv("{0:x16}", LSDA) << "\n";
       });
-      B.addEdge(Delta64, RecordOffset + LSDAFieldOffset, *LSDASym, 0);
+      B.addEdge(LSDAEdgeKind, RecordOffset + LSDAFieldOffset, *LSDASym, 0);
     } else {
       LLVM_DEBUG({
         auto &EI = LSDAEdgeItr->second;
@@ -530,7 +544,7 @@ Error EHFrameEdgeFixer::processFDE(ParseContext &PC, Block &B,
           dbgs() << " + " << formatv("{0:x16}", EI.Addend);
         dbgs() << "\n";
       });
-      if (auto Err = RecordReader.skip(PC.G.getPointerSize()))
+      if (auto Err = RecordReader.skip(AugmentationDataSize))
         return Err;
     }
   } else {
@@ -581,23 +595,110 @@ EHFrameEdgeFixer::parseAugmentationString(BinaryStreamReader &RecordReader) {
   return std::move(AugInfo);
 }
 
-Expected<JITTargetAddress>
-EHFrameEdgeFixer::readAbsolutePointer(LinkGraph &G,
-                                      BinaryStreamReader &RecordReader) {
+bool EHFrameEdgeFixer::isSupportedPointerEncoding(uint8_t PointerEncoding) {
+  using namespace dwarf;
+
+  // We only support PC-rel for now.
+  if ((PointerEncoding & 0x70) != DW_EH_PE_pcrel)
+    return false;
+
+  // readEncodedPointer does not handle indirect.
+  if (PointerEncoding & DW_EH_PE_indirect)
+    return false;
+
+  // Supported datatypes.
+  switch (PointerEncoding & 0xf) {
+  case DW_EH_PE_absptr:
+  case DW_EH_PE_udata4:
+  case DW_EH_PE_udata8:
+  case DW_EH_PE_sdata4:
+  case DW_EH_PE_sdata8:
+    return true;
+  }
+
+  return false;
+}
+
+unsigned EHFrameEdgeFixer::getPointerEncodingDataSize(uint8_t PointerEncoding) {
+  using namespace dwarf;
+
+  assert(isSupportedPointerEncoding(PointerEncoding) &&
+         "Unsupported pointer encoding");
+  switch (PointerEncoding & 0xf) {
+  case DW_EH_PE_absptr:
+    return PointerSize;
+  case DW_EH_PE_udata4:
+  case DW_EH_PE_sdata4:
+    return 4;
+  case DW_EH_PE_udata8:
+  case DW_EH_PE_sdata8:
+    return 8;
+  default:
+    llvm_unreachable("Unsupported encoding");
+  }
+}
+
+Expected<std::pair<JITTargetAddress, Edge::Kind>>
+EHFrameEdgeFixer::readEncodedPointer(uint8_t PointerEncoding,
+                                     JITTargetAddress PointerFieldAddress,
+                                     BinaryStreamReader &RecordReader) {
   static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t),
                 "Result must be able to hold a uint64_t");
+  assert(isSupportedPointerEncoding(PointerEncoding) &&
+         "Unsupported pointer encoding");
+
+  using namespace dwarf;
+
+  // Isolate data type, remap absptr to udata4 or udata8. This relies on us
+  // having verified that the graph uses 32-bit or 64-bit pointers only at the
+  // start of this pass.
+  uint8_t EffectiveType = PointerEncoding & 0xf;
+  if (EffectiveType == DW_EH_PE_absptr)
+    EffectiveType = (PointerSize == 8) ? DW_EH_PE_udata8 : DW_EH_PE_udata4;
+
   JITTargetAddress Addr;
-  if (G.getPointerSize() == 8) {
-    if (auto Err = RecordReader.readInteger(Addr))
+  Edge::Kind PointerEdgeKind;
+  switch (EffectiveType) {
+  case DW_EH_PE_udata4: {
+    uint32_t Val;
+    if (auto Err = RecordReader.readInteger(Val))
       return std::move(Err);
-  } else if (G.getPointerSize() == 4) {
-    uint32_t Addr32;
-    if (auto Err = RecordReader.readInteger(Addr32))
+    Addr = PointerFieldAddress + Val;
+    PointerEdgeKind = Delta32;
+    break;
+  }
+  case DW_EH_PE_udata8: {
+    uint64_t Val;
+    if (auto Err = RecordReader.readInteger(Val))
       return std::move(Err);
-    Addr = Addr32;
-  } else
-    llvm_unreachable("Pointer size is not 32-bit or 64-bit");
-  return Addr;
+    Addr = PointerFieldAddress + Val;
+    PointerEdgeKind = Delta64;
+    break;
+  }
+  case DW_EH_PE_sdata4: {
+    int32_t Val;
+    if (auto Err = RecordReader.readInteger(Val))
+      return std::move(Err);
+    Addr = PointerFieldAddress + Val;
+    PointerEdgeKind = Delta32;
+    break;
+  }
+  case DW_EH_PE_sdata8: {
+    int64_t Val;
+    if (auto Err = RecordReader.readInteger(Val))
+      return std::move(Err);
+    Addr = PointerFieldAddress + Val;
+    PointerEdgeKind = Delta64;
+    break;
+  }
+  }
+
+  if (PointerEdgeKind == Edge::Invalid)
+    return make_error<JITLinkError>(
+        "Unspported edge kind for encoded pointer at " +
+        formatv("{0:x}", PointerFieldAddress));
+
+  return std::make_pair(Addr, Delta64);
 }
 
 Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,

diff  --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
index 83f27a285998..5e68e72ba18d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
@@ -40,7 +40,8 @@ class EHFrameSplitter {
 /// edges.
 class EHFrameEdgeFixer {
 public:
-  EHFrameEdgeFixer(StringRef EHFrameSectionName, Edge::Kind Delta64,
+  EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize,
+                   Edge::Kind Delta64, Edge::Kind Delta32,
                    Edge::Kind NegDelta32);
   Error operator()(LinkGraph &G);
 
@@ -57,6 +58,8 @@ class EHFrameEdgeFixer {
     CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {}
     Symbol *CIESymbol = nullptr;
     bool FDEsHaveLSDAField = false;
+    uint8_t FDEPointerEncoding = 0;
+    uint8_t LSDAPointerEncoding = 0;
   };
 
   struct EdgeTarget {
@@ -96,12 +99,20 @@ class EHFrameEdgeFixer {
 
   Expected<AugmentationInfo>
   parseAugmentationString(BinaryStreamReader &RecordReader);
-  Expected<JITTargetAddress>
-  readAbsolutePointer(LinkGraph &G, BinaryStreamReader &RecordReader);
+
+  static bool isSupportedPointerEncoding(uint8_t PointerEncoding);
+  unsigned getPointerEncodingDataSize(uint8_t PointerEncoding);
+  Expected<std::pair<JITTargetAddress, Edge::Kind>>
+  readEncodedPointer(uint8_t PointerEncoding,
+                     JITTargetAddress PointerFieldAddress,
+                     BinaryStreamReader &RecordReader);
+
   Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, JITTargetAddress Addr);
 
   StringRef EHFrameSectionName;
+  unsigned PointerSize;
   Edge::Kind Delta64;
+  Edge::Kind Delta32;
   Edge::Kind NegDelta32;
 };
 

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index 0ca2130150a6..2a92f28030ce 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -11,12 +11,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
-#include "BasicGOTAndStubsBuilder.h"
-#include "JITLinkGeneric.h"
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Support/Endian.h"
 
+#include "BasicGOTAndStubsBuilder.h"
+#include "EHFrameSupportImpl.h"
+#include "JITLinkGeneric.h"
+
 #define DEBUG_TYPE "jitlink"
 
 using namespace llvm;
@@ -238,6 +240,8 @@ class ELFLinkGraphBuilder_x86_64 {
     switch (Type) {
     case ELF::R_X86_64_PC32:
       return ELF_x86_64_Edges::ELFX86RelocationKind::PCRel32;
+    case ELF::R_X86_64_PC64:
+      return ELF_x86_64_Edges::ELFX86RelocationKind::Delta64;
     case ELF::R_X86_64_64:
       return ELF_x86_64_Edges::ELFX86RelocationKind::Pointer64;
     case ELF::R_X86_64_GOTPCREL:
@@ -404,9 +408,6 @@ class ELFLinkGraphBuilder_x86_64 {
       LLVM_DEBUG({
         dbgs() << "Adding relocations from section " << *RelSectName << "\n";
       });
-      // Deal with .eh_frame later
-      if (*RelSectName == StringRef(".rela.eh_frame"))
-        continue;
 
       auto UpdateSection = Obj.getSection(SecRef.sh_info);
       if (!UpdateSection)
@@ -734,6 +735,11 @@ class ELFJITLinker_x86_64 : public JITLinker<ELFJITLinker_x86_64> {
       *(ulittle64_t *)FixupPtr = Value;
       break;
     }
+    case ELFX86RelocationKind::Delta64: {
+      int64_t Value = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+      *(little64_t *)FixupPtr = Value;
+      break;
+    }
     }
     return Error::success();
   }
@@ -760,21 +766,28 @@ void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
                      std::unique_ptr<JITLinkContext> Ctx) {
   PassConfiguration Config;
 
-  // Construct a JITLinker and run the link function.
-  // Add a mark-live pass.
-  if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
-    Config.PrePrunePasses.push_back(std::move(MarkLive));
-  else
-    Config.PrePrunePasses.push_back(markAllSymbolsLive);
+  if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
 
-  // Add an in-place GOT/Stubs pass.
-  Config.PostPrunePasses.push_back([](LinkGraph &G) -> Error {
-    ELF_x86_64_GOTAndStubsBuilder(G).run();
-    return Error::success();
-  });
+    Config.PrePrunePasses.push_back(EHFrameSplitter(".eh_frame"));
+    Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
+        ".eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32));
 
-  // Add GOT/Stubs optimizer pass.
-  Config.PreFixupPasses.push_back(optimizeELF_x86_64_GOTAndStubs);
+    // Construct a JITLinker and run the link function.
+    // Add a mark-live pass.
+    if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
+      Config.PrePrunePasses.push_back(std::move(MarkLive));
+    else
+      Config.PrePrunePasses.push_back(markAllSymbolsLive);
+
+    // Add an in-place GOT/Stubs pass.
+    Config.PostPrunePasses.push_back([](LinkGraph &G) -> Error {
+      ELF_x86_64_GOTAndStubsBuilder(G).run();
+      return Error::success();
+    });
+
+    // Add GOT/Stubs optimizer pass.
+    Config.PreFixupPasses.push_back(optimizeELF_x86_64_GOTAndStubs);
+  }
 
   if (auto Err = Ctx->modifyPassConfig(G->getTargetTriple(), Config))
     return Ctx->notifyFailed(std::move(Err));

diff  --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
index 3555d66ace35..26e6859de91d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
@@ -16,10 +16,10 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/Object/MachO.h"
 
 #include "EHFrameSupportImpl.h"
 #include "JITLinkGeneric.h"
-#include "llvm/Object/MachO.h"
 
 #include <list>
 

diff  --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
index 24559cc7e772..bde4a19e71ba 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
@@ -669,8 +669,8 @@ void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
   if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
     // Add eh-frame passses.
     Config.PrePrunePasses.push_back(EHFrameSplitter("__eh_frame"));
-    Config.PrePrunePasses.push_back(
-        EHFrameEdgeFixer("__eh_frame", Delta64, NegDelta32));
+    Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
+        "__eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32));
 
     // Add a mark-live pass.
     if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/ELF_ehframe_basic.s b/llvm/test/ExecutionEngine/JITLink/X86/ELF_ehframe_basic.s
new file mode 100644
index 000000000000..fe00d23f6f66
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/ELF_ehframe_basic.s
@@ -0,0 +1,115 @@
+# REQUIRES: asserts
+# RUN: llvm-mc -triple=x86_64-unknown-linux -position-independent \
+# RUN:     -filetype=obj -o %t %s
+# RUN: llvm-jitlink -debug-only=jitlink -define-abs bar=0x01 -noexec %t 2>&1 | \
+# RUN:     FileCheck %s
+#
+# Check that a basic .eh-frame section is recognized and parsed. We
+# Expect to see two FDEs with corresponding keep-alive edges.
+#
+# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at
+# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at
+
+	.text
+	.file	"exceptions.cpp"
+	.globl	foo
+	.p2align	4, 0x90
+	.type	foo, at function
+foo:
+	.cfi_startproc
+
+	pushq	%rax
+	.cfi_def_cfa_offset 16
+	movl	$4, %edi
+	callq	__cxa_allocate_exception at PLT
+	movl	$1, (%rax)
+	movq	_ZTIi at GOTPCREL(%rip), %rsi
+	movq	%rax, %rdi
+	xorl	%edx, %edx
+	callq	__cxa_throw at PLT
+.Lfunc_end0:
+	.size	foo, .Lfunc_end0-foo
+	.cfi_endproc
+
+	.globl	main
+	.p2align	4, 0x90
+	.type	main, at function
+main:
+.Lfunc_begin0:
+	.cfi_startproc
+	.cfi_personality 155, DW.ref.__gxx_personality_v0
+	.cfi_lsda 27, .Lexception0
+
+	pushq	%rbx
+	.cfi_def_cfa_offset 16
+	.cfi_offset %rbx, -16
+	xorl	%ebx, %ebx
+.Ltmp0:
+	callq	bar at PLT
+.Ltmp1:
+
+	movl	%ebx, %eax
+	popq	%rbx
+	.cfi_def_cfa_offset 8
+	retq
+.LBB1_1:
+	.cfi_def_cfa_offset 16
+.Ltmp2:
+	movq	%rax, %rdi
+	callq	__cxa_begin_catch at PLT
+	callq	__cxa_end_catch at PLT
+	movl	$1, %ebx
+	movl	%ebx, %eax
+	popq	%rbx
+	.cfi_def_cfa_offset 8
+	retq
+.Lfunc_end1:
+	.size	main, .Lfunc_end1-main
+	.cfi_endproc
+	.section	.gcc_except_table,"a", at progbits
+	.p2align	2
+GCC_except_table1:
+.Lexception0:
+	.byte	255
+	.byte	156
+	.uleb128 .Lttbase0-.Lttbaseref0
+.Lttbaseref0:
+	.byte	1
+	.uleb128 .Lcst_end0-.Lcst_begin0
+.Lcst_begin0:
+	.uleb128 .Ltmp0-.Lfunc_begin0
+	.uleb128 .Ltmp1-.Ltmp0
+	.uleb128 .Ltmp2-.Lfunc_begin0
+	.byte	1
+	.uleb128 .Ltmp1-.Lfunc_begin0
+	.uleb128 .Lfunc_end1-.Ltmp1
+	.byte	0
+	.byte	0
+.Lcst_end0:
+	.byte	1
+
+	.byte	0
+	.p2align	2
+
+.Ltmp3:
+	.quad	.L_ZTIi.DW.stub-.Ltmp3
+.Lttbase0:
+	.p2align	2
+
+	.data
+	.p2align	3
+.L_ZTIi.DW.stub:
+	.quad	_ZTIi
+	.hidden	DW.ref.__gxx_personality_v0
+	.weak	DW.ref.__gxx_personality_v0
+	.section	.data.DW.ref.__gxx_personality_v0,"aGw", at progbits,DW.ref.__gxx_personality_v0,comdat
+	.p2align	3
+	.type	DW.ref.__gxx_personality_v0, at object
+	.size	DW.ref.__gxx_personality_v0, 8
+DW.ref.__gxx_personality_v0:
+	.quad	__gxx_personality_v0
+	.ident	"clang version 12.0.0 (git at github.com:llvm/llvm-project.git afd483e57d166418e94a65bd9716e7dc4c114eed)"
+	.section	".note.GNU-stack","", at progbits
+	.addrsig
+	.addrsig_sym __gxx_personality_v0
+	.addrsig_sym _ZTIi


        


More information about the llvm-commits mailing list