1//===------- EHFrameSupportImpl.h - JITLink eh-frame utils ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// EHFrame registration support for JITLink.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
14#define LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
15
16#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
17
18#include "llvm/ExecutionEngine/JITLink/JITLink.h"
19#include "llvm/Support/BinaryStreamReader.h"
20
21namespace llvm {
22namespace jitlink {
23
24/// A LinkGraph pass that splits blocks in an eh-frame section into sub-blocks
25/// representing individual eh-frames.
26/// EHFrameSplitter should not be run without EHFrameEdgeFixer, which is
27/// responsible for adding FDE-to-CIE edges.
28class EHFrameSplitter {
29public:
30  EHFrameSplitter(StringRef EHFrameSectionName);
31  Error operator()(LinkGraph &G);
32
33private:
34  Error processBlock(LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache);
35
36  StringRef EHFrameSectionName;
37};
38
39/// A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA
40/// edges.
41class EHFrameEdgeFixer {
42public:
43  EHFrameEdgeFixer(StringRef EHFrameSectionName, Edge::Kind FDEToCIE,
44                   Edge::Kind FDEToPCBegin, Edge::Kind FDEToLSDA);
45  Error operator()(LinkGraph &G);
46
47private:
48
49  struct AugmentationInfo {
50    bool AugmentationDataPresent = false;
51    bool EHDataFieldPresent = false;
52    uint8_t Fields[4] = {0x0, 0x0, 0x0, 0x0};
53  };
54
55  struct CIEInformation {
56    CIEInformation() = default;
57    CIEInformation(Symbol &CIESymbol) : CIESymbol(&CIESymbol) {}
58    Symbol *CIESymbol = nullptr;
59    bool FDEsHaveLSDAField = false;
60  };
61
62  struct EdgeTarget {
63    EdgeTarget() = default;
64    EdgeTarget(const Edge &E) : Target(&E.getTarget()), Addend(E.getAddend()) {}
65
66    Symbol *Target = nullptr;
67    Edge::AddendT Addend = 0;
68  };
69
70  using BlockEdgeMap = DenseMap<Edge::OffsetT, EdgeTarget>;
71  using CIEInfosMap = DenseMap<JITTargetAddress, CIEInformation>;
72
73  struct ParseContext {
74    ParseContext(LinkGraph &G) : G(G) {}
75
76    Expected<CIEInformation *> findCIEInfo(JITTargetAddress Address) {
77      auto I = CIEInfos.find(Address);
78      if (I == CIEInfos.end())
79        return make_error<JITLinkError>("No CIE found at address " +
80                                        formatv("{0:x16}", Address));
81      return &I->second;
82    }
83
84    LinkGraph &G;
85    CIEInfosMap CIEInfos;
86    BlockAddressMap AddrToBlock;
87    SymbolAddressMap AddrToSyms;
88  };
89
90  Error processBlock(ParseContext &PC, Block &B);
91  Error processCIE(ParseContext &PC, Block &B, size_t RecordOffset,
92                   size_t RecordLength, size_t CIEDeltaFieldOffset);
93  Error processFDE(ParseContext &PC, Block &B, size_t RecordOffset,
94                   size_t RecordLength, size_t CIEDeltaFieldOffset,
95                   uint32_t CIEDelta, BlockEdgeMap &BlockEdges);
96
97  Expected<AugmentationInfo>
98  parseAugmentationString(BinaryStreamReader &RecordReader);
99  Expected<JITTargetAddress>
100  readAbsolutePointer(LinkGraph &G, BinaryStreamReader &RecordReader);
101  Expected<Symbol &> getOrCreateSymbol(ParseContext &PC, JITTargetAddress Addr);
102
103  StringRef EHFrameSectionName;
104  Edge::Kind FDEToCIE;
105  Edge::Kind FDEToPCBegin;
106  Edge::Kind FDEToLSDA;
107};
108
109} // end namespace jitlink
110} // end namespace llvm
111
112#endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORTIMPL_H
113