EHFrameSupport.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--------- EHFrameSupport.h - JITLink eh-frame utils --------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // EHFrame registration support for JITLink.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H
  18. #define LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H
  19. #include "llvm/ADT/Triple.h"
  20. #include "llvm/ExecutionEngine/JITLink/JITLink.h"
  21. #include "llvm/ExecutionEngine/JITSymbol.h"
  22. #include "llvm/Support/Error.h"
  23. namespace llvm {
  24. namespace jitlink {
  25. /// Inspect an eh-frame CFI record.
  26. class EHFrameCFIBlockInspector {
  27. public:
  28. /// Identify CFI record type and edges based on number and order of edges
  29. /// in the given block only. This assumes that the block contains one CFI
  30. /// record that has already been split out and fixed by the
  31. /// DWARFRecordSplitter and EHFrameEdgeFixer passes.
  32. ///
  33. /// Zero or one outgoing edges: Record is CIE. If present, edge points to
  34. /// personality.
  35. ///
  36. /// Two or three outgoing edges: Record is an FDE. First edge points to CIE,
  37. /// second to PC-begin, third (if present) to LSDA.
  38. ///
  39. /// It is illegal to call this function on a block with four or more edges.
  40. static EHFrameCFIBlockInspector FromEdgeScan(Block &B);
  41. /// Returns true if this frame is an FDE, false for a CIE.
  42. bool isFDE() const { return CIEEdge != nullptr; }
  43. /// Returns true if this frame is a CIE, false for an FDE.
  44. bool isCIE() const { return CIEEdge == nullptr; }
  45. /// If this is a CIE record, returns the Edge pointing at the personality
  46. /// function, if any.
  47. /// It is illegal to call this method on FDE records.
  48. Edge *getPersonalityEdge() const {
  49. assert(isCIE() && "CFI record is not a CIE");
  50. return PersonalityEdge;
  51. }
  52. /// If this is an FDE record, returns the Edge pointing to the CIE.
  53. /// If this is a CIE record, returns null.
  54. ///
  55. /// The result is not valid if any modification has been made to the block
  56. /// after parsing.
  57. Edge *getCIEEdge() const { return CIEEdge; }
  58. /// If this is an FDE record, returns the Edge pointing at the PC-begin
  59. /// symbol.
  60. /// If this a CIE record, returns null.
  61. Edge *getPCBeginEdge() const { return PCBeginEdge; }
  62. /// If this is an FDE record, returns the Edge pointing at the LSDA, if any.
  63. /// It is illegal to call this method on CIE records.
  64. Edge *getLSDAEdge() const {
  65. assert(isFDE() && "CFI record is not an FDE");
  66. return LSDAEdge;
  67. }
  68. private:
  69. EHFrameCFIBlockInspector(Edge *PersonalityEdge);
  70. EHFrameCFIBlockInspector(Edge &CIEEdge, Edge &PCBeginEdge, Edge *LSDAEdge);
  71. Edge *CIEEdge = nullptr;
  72. Edge *PCBeginEdge = nullptr;
  73. union {
  74. Edge *PersonalityEdge;
  75. Edge *LSDAEdge;
  76. };
  77. };
  78. /// Supports registration/deregistration of EH-frames in a target process.
  79. class EHFrameRegistrar {
  80. public:
  81. virtual ~EHFrameRegistrar();
  82. virtual Error registerEHFrames(orc::ExecutorAddrRange EHFrameSection) = 0;
  83. virtual Error deregisterEHFrames(orc::ExecutorAddrRange EHFrameSection) = 0;
  84. };
  85. /// Registers / Deregisters EH-frames in the current process.
  86. class InProcessEHFrameRegistrar final : public EHFrameRegistrar {
  87. public:
  88. Error registerEHFrames(orc::ExecutorAddrRange EHFrameSection) override;
  89. Error deregisterEHFrames(orc::ExecutorAddrRange EHFrameSection) override;
  90. };
  91. using StoreFrameRangeFunction = std::function<void(
  92. orc::ExecutorAddr EHFrameSectionAddr, size_t EHFrameSectionSize)>;
  93. /// Creates a pass that records the address and size of the EH frame section.
  94. /// If no eh-frame section is found then the address and size will both be given
  95. /// as zero.
  96. ///
  97. /// Authors of JITLinkContexts can use this function to register a post-fixup
  98. /// pass that records the range of the eh-frame section. This range can
  99. /// be used after finalization to register and deregister the frame.
  100. LinkGraphPassFunction
  101. createEHFrameRecorderPass(const Triple &TT,
  102. StoreFrameRangeFunction StoreFrameRange);
  103. } // end namespace jitlink
  104. } // end namespace llvm
  105. #endif // LLVM_EXECUTIONENGINE_JITLINK_EHFRAMESUPPORT_H
  106. #ifdef __GNUC__
  107. #pragma GCC diagnostic pop
  108. #endif