[JITLink] Add a null-terminator to eh-frame sections on ELF/x86-64.
authorLang Hames <lhames@gmail.com>
Wed, 10 Mar 2021 05:54:18 +0000 (21:54 -0800)
committerLang Hames <lhames@gmail.com>
Wed, 10 Mar 2021 06:16:11 +0000 (22:16 -0800)
__register_ehframes on Linux requires a null terminator to identify the end of
this section.

llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h
llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp

index 3602601..93123ca 100644 (file)
@@ -730,6 +730,29 @@ Expected<Symbol &> EHFrameEdgeFixer::getOrCreateSymbol(ParseContext &PC,
   return PC.G.addAnonymousSymbol(*B, Addr - B->getAddress(), 0, false, false);
 }
 
+char EHFrameNullTerminator::NullTerminatorBlockContent[] = {0, 0, 0, 0};
+
+EHFrameNullTerminator::EHFrameNullTerminator(StringRef EHFrameSectionName)
+    : EHFrameSectionName(EHFrameSectionName) {}
+
+Error EHFrameNullTerminator::operator()(LinkGraph &G) {
+  auto *EHFrame = G.findSectionByName(EHFrameSectionName);
+
+  if (!EHFrame)
+    return Error::success();
+
+  LLVM_DEBUG({
+    dbgs() << "EHFrameNullTerminator adding null terminator to "
+           << EHFrameSectionName << "\n";
+  });
+
+  auto &NullTerminatorBlock =
+      G.createContentBlock(*EHFrame, StringRef(NullTerminatorBlockContent, 4),
+                           0xfffffffffffffffc, 1, 0);
+  G.addAnonymousSymbol(NullTerminatorBlock, 0, 4, false, true);
+  return Error::success();
+}
+
 EHFrameRegistrar::~EHFrameRegistrar() {}
 
 Error InProcessEHFrameRegistrar::registerEHFrames(
index 5e68e72..b4c4b0f 100644 (file)
@@ -116,6 +116,17 @@ private:
   Edge::Kind NegDelta32;
 };
 
+/// Add a 32-bit null-terminator to the end of the eh-frame section.
+class EHFrameNullTerminator {
+public:
+  EHFrameNullTerminator(StringRef EHFrameSectionName);
+  Error operator()(LinkGraph &G);
+
+private:
+  static char NullTerminatorBlockContent[];
+  StringRef EHFrameSectionName;
+};
+
 } // end namespace jitlink
 } // end namespace llvm
 
index f81e674..e43e960 100644 (file)
@@ -768,6 +768,7 @@ void link_ELF_x86_64(std::unique_ptr<LinkGraph> G,
     Config.PrePrunePasses.push_back(EHFrameSplitter(".eh_frame"));
     Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
         ".eh_frame", G->getPointerSize(), Delta64, Delta32, NegDelta32));
+    Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
 
     // Construct a JITLinker and run the link function.
     // Add a mark-live pass.