aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm16/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
blob: 822bc3c44bb6c0942b07903db9ba2f20e47cdf49 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===--------- EHFrameSupport.h - JITLink eh-frame utils --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// EHFrame registration support for JITLink.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H
#define LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H

#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/Support/Error.h"

namespace llvm {
namespace jitlink {

/// Inspect an eh-frame CFI record.
class EHFrameCFIBlockInspector {
public:
  /// Identify CFI record type and edges based on number and order of edges
  /// in the given block only. This assumes that the block contains one CFI
  /// record that has already been split out and fixed by the
  /// DWARFRecordSplitter and EHFrameEdgeFixer passes.
  ///
  /// Zero or one outgoing edges: Record is CIE. If present, edge points to
  /// personality.
  ///
  /// Two or three outgoing edges: Record is an FDE. First edge points to CIE,
  /// second to PC-begin, third (if present) to LSDA.
  ///
  /// It is illegal to call this function on a block with four or more edges.
  static EHFrameCFIBlockInspector FromEdgeScan(Block &B);

  /// Returns true if this frame is an FDE, false for a CIE.
  bool isFDE() const { return CIEEdge != nullptr; }

  /// Returns true if this frame is a CIE, false for an FDE.
  bool isCIE() const { return CIEEdge == nullptr; }

  /// If this is a CIE record, returns the Edge pointing at the personality
  /// function, if any.
  /// It is illegal to call this method on FDE records.
  Edge *getPersonalityEdge() const {
    assert(isCIE() && "CFI record is not a CIE");
    return PersonalityEdge;
  }

  /// If this is an FDE record, returns the Edge pointing to the CIE.
  /// If this is a CIE record, returns null.
  ///
  /// The result is not valid if any modification has been made to the block
  /// after parsing.
  Edge *getCIEEdge() const { return CIEEdge; }

  /// If this is an FDE record, returns the Edge pointing at the PC-begin
  /// symbol.
  /// If this a CIE record, returns null.
  Edge *getPCBeginEdge() const { return PCBeginEdge; }

  /// If this is an FDE record, returns the Edge pointing at the LSDA, if any.
  /// It is illegal to call this method on CIE records.
  Edge *getLSDAEdge() const {
    assert(isFDE() && "CFI record is not an FDE");
    return LSDAEdge;
  }

private:
  EHFrameCFIBlockInspector(Edge *PersonalityEdge);
  EHFrameCFIBlockInspector(Edge &CIEEdge, Edge &PCBeginEdge, Edge *LSDAEdge);

  Edge *CIEEdge = nullptr;
  Edge *PCBeginEdge = nullptr;
  union {
    Edge *PersonalityEdge;
    Edge *LSDAEdge;
  };
};

/// Supports registration/deregistration of EH-frames in a target process.
class EHFrameRegistrar {
public:
  virtual ~EHFrameRegistrar();
  virtual Error registerEHFrames(orc::ExecutorAddrRange EHFrameSection) = 0;
  virtual Error deregisterEHFrames(orc::ExecutorAddrRange EHFrameSection) = 0;
};

/// Registers / Deregisters EH-frames in the current process.
class InProcessEHFrameRegistrar final : public EHFrameRegistrar {
public:
  Error registerEHFrames(orc::ExecutorAddrRange EHFrameSection) override;

  Error deregisterEHFrames(orc::ExecutorAddrRange EHFrameSection) override;
};

using StoreFrameRangeFunction = std::function<void(
    orc::ExecutorAddr EHFrameSectionAddr, size_t EHFrameSectionSize)>;

/// Creates a pass that records the address and size of the EH frame section.
/// If no eh-frame section is found then the address and size will both be given
/// as zero.
///
/// Authors of JITLinkContexts can use this function to register a post-fixup
/// pass that records the range of the eh-frame section. This range can
/// be used after finalization to register and deregister the frame.
LinkGraphPassFunction
createEHFrameRecorderPass(const Triple &TT,
                          StoreFrameRangeFunction StoreFrameRange);

} // end namespace jitlink
} // end namespace llvm

#endif // LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif