xref: /openbsd-src/gnu/llvm/llvm/lib/ExecutionEngine/JITLink/EHFrameSupportImpl.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===------- EHFrameSupportImpl.h - JITLink eh-frame utils ------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // EHFrame registration support for JITLink.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
1409467b48Spatrick #define LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
1509467b48Spatrick 
1609467b48Spatrick #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
1709467b48Spatrick 
1809467b48Spatrick #include "llvm/ExecutionEngine/JITLink/JITLink.h"
1909467b48Spatrick #include "llvm/Support/BinaryStreamReader.h"
2009467b48Spatrick 
2109467b48Spatrick namespace llvm {
2209467b48Spatrick namespace jitlink {
2309467b48Spatrick 
2409467b48Spatrick /// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA
2509467b48Spatrick /// edges.
2609467b48Spatrick class EHFrameEdgeFixer {
2709467b48Spatrick public:
28*d415bd75Srobert   /// Create an eh-frame edge fixer.
29*d415bd75Srobert   /// If a given edge-kind is not supported on the target architecture then
30*d415bd75Srobert   /// Edge::Invalid should be used.
3173471bf0Spatrick   EHFrameEdgeFixer(StringRef EHFrameSectionName, unsigned PointerSize,
32*d415bd75Srobert                    Edge::Kind Pointer32, Edge::Kind Pointer64,
33*d415bd75Srobert                    Edge::Kind Delta32, Edge::Kind Delta64,
3473471bf0Spatrick                    Edge::Kind NegDelta32);
3509467b48Spatrick   Error operator()(LinkGraph &G);
3609467b48Spatrick 
3709467b48Spatrick private:
3809467b48Spatrick 
3909467b48Spatrick   struct AugmentationInfo {
4009467b48Spatrick     bool AugmentationDataPresent = false;
4109467b48Spatrick     bool EHDataFieldPresent = false;
4209467b48Spatrick     uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0};
4309467b48Spatrick   };
4409467b48Spatrick 
4509467b48Spatrick   struct CIEInformation {
4609467b48Spatrick     CIEInformation() = default;
CIEInformationCIEInformation4709467b48Spatrick     CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {}
4809467b48Spatrick     Symbol *CIESymbol = nullptr;
49*d415bd75Srobert     bool AugmentationDataPresent = false;
50*d415bd75Srobert     bool LSDAPresent = false;
51*d415bd75Srobert     uint8_t LSDAEncoding = 0;
52*d415bd75Srobert     uint8_t AddressEncoding = 0;
5309467b48Spatrick   };
5409467b48Spatrick 
5509467b48Spatrick   struct EdgeTarget {
5609467b48Spatrick     EdgeTarget() = default;
EdgeTargetEdgeTarget5709467b48Spatrick     EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {}
5809467b48Spatrick 
5909467b48Spatrick     Symbol *Target = nullptr;
6009467b48Spatrick     Edge::AddendT Addend = 0;
6109467b48Spatrick   };
6209467b48Spatrick 
6309467b48Spatrick   using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>;
64*d415bd75Srobert   using CIEInfosMap = DenseMap<orc::ExecutorAddr, CIEInformation>;
6509467b48Spatrick 
6609467b48Spatrick   struct ParseContext {
ParseContextParseContext6709467b48Spatrick     ParseContext(LinkGraph &G) : G(G) {}
6809467b48Spatrick 
findCIEInfoParseContext69*d415bd75Srobert     Expected<CIEInformation *> findCIEInfo(orc::ExecutorAddr Address) {
7009467b48Spatrick       auto I = CIEInfos.find(Address);
7109467b48Spatrick       if (I == CIEInfos.end())
7209467b48Spatrick         return make_error<JITLinkError>("No CIE found at address " +
7309467b48Spatrick                                         formatv("{0:x16}", Address));
7409467b48Spatrick       return &I->second;
7509467b48Spatrick     }
7609467b48Spatrick 
7709467b48Spatrick     LinkGraph &G;
7809467b48Spatrick     CIEInfosMap CIEInfos;
7909467b48Spatrick     BlockAddressMap AddrToBlock;
80*d415bd75Srobert     DenseMap<orc::ExecutorAddr, Symbol *> AddrToSym;
8109467b48Spatrick   };
8209467b48Spatrick 
8309467b48Spatrick   Error processBlock(ParseContext &PC, Block &B);
8409467b48Spatrick   Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset,
85*d415bd75Srobert                    size_t RecordLength, size_t CIEDeltaFieldOffset,
86*d415bd75Srobert                    const BlockEdgeMap &BlockEdges);
8709467b48Spatrick   Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset,
8809467b48Spatrick                    size_t RecordLength, size_t CIEDeltaFieldOffset,
89*d415bd75Srobert                    uint32_t CIEDelta, const BlockEdgeMap &BlockEdges);
9009467b48Spatrick 
9109467b48Spatrick   Expected<AugmentationInfo>
9209467b48Spatrick   parseAugmentationString(BinaryStreamReader &RecordReader);
9373471bf0Spatrick 
94*d415bd75Srobert   Expected<uint8_t> readPointerEncoding(BinaryStreamReader &RecordReader,
95*d415bd75Srobert                                         Block &InBlock, const char *FieldName);
96*d415bd75Srobert   Error skipEncodedPointer(uint8_t PointerEncoding,
9773471bf0Spatrick                            BinaryStreamReader &RecordReader);
98*d415bd75Srobert   Expected<Symbol *> getOrCreateEncodedPointerEdge(
99*d415bd75Srobert       ParseContext &PC, const BlockEdgeMap &BlockEdges, uint8_t PointerEncoding,
100*d415bd75Srobert       BinaryStreamReader &RecordReader, Block &BlockToFix,
101*d415bd75Srobert       size_t PointerFieldOffset, const char *FieldName);
10273471bf0Spatrick 
103*d415bd75Srobert   Expected<Symbol &> getOrCreateSymbol(ParseContext &PC,
104*d415bd75Srobert                                        orc::ExecutorAddr Addr);
10509467b48Spatrick 
10609467b48Spatrick   StringRef EHFrameSectionName;
10773471bf0Spatrick   unsigned PointerSize;
108*d415bd75Srobert   Edge::Kind Pointer32;
109*d415bd75Srobert   Edge::Kind Pointer64;
11073471bf0Spatrick   Edge::Kind Delta32;
111*d415bd75Srobert   Edge::Kind Delta64;
11273471bf0Spatrick   Edge::Kind NegDelta32;
11373471bf0Spatrick };
11473471bf0Spatrick 
11573471bf0Spatrick /// Add a 32-bit null-terminator to the end of the eh-frame section.
11673471bf0Spatrick class EHFrameNullTerminator {
11773471bf0Spatrick public:
11873471bf0Spatrick   EHFrameNullTerminator(StringRef EHFrameSectionName);
11973471bf0Spatrick   Error operator()(LinkGraph &G);
12073471bf0Spatrick 
12173471bf0Spatrick private:
12273471bf0Spatrick   static char NullTerminatorBlockContent[];
12373471bf0Spatrick   StringRef EHFrameSectionName;
12409467b48Spatrick };
12509467b48Spatrick 
12609467b48Spatrick } // end namespace jitlink
12709467b48Spatrick } // end namespace llvm
12809467b48Spatrick 
12909467b48Spatrick #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
130