xref: /llvm-project/bolt/include/bolt/Core/Exceptions.h (revision 1b8e0cf090a08b2c517eb2a3e101332d692063c2)
1 //===- bolt/Core/Exceptions.h - Helpers for C++ exceptions ------*- 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 // This file contains declarations of classes for handling C++ exception info.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef BOLT_CORE_EXCEPTIONS_H
14 #define BOLT_CORE_EXCEPTIONS_H
15 
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
18 #include "llvm/Support/Error.h"
19 #include <cstdint>
20 #include <map>
21 #include <vector>
22 
23 namespace llvm {
24 
25 class DWARFDebugFrame;
26 
27 namespace dwarf {
28 class FDE;
29 } // namespace dwarf
30 
31 namespace bolt {
32 
33 class BinaryContext;
34 class BinaryFunction;
35 
36 /// \brief Wraps up information to read all CFI instructions and feed them to a
37 /// BinaryFunction, as well as rewriting CFI sections.
38 class CFIReaderWriter {
39 public:
40   explicit CFIReaderWriter(BinaryContext &BC, const DWARFDebugFrame &EHFrame);
41 
42   bool fillCFIInfoFor(BinaryFunction &Function) const;
43 
44   /// Generate .eh_frame_hdr from old and new .eh_frame sections.
45   ///
46   /// Take FDEs from the \p NewEHFrame. All other entries are taken from the
47   /// \p OldEHFrame.
48   ///
49   /// \p EHFrameHeaderAddress specifies location of .eh_frame_hdr,
50   /// and is required for relative addressing used in the section.
51   std::vector<char> generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame,
52                                           const DWARFDebugFrame &NewEHFrame,
53                                           uint64_t EHFrameHeaderAddress) const;
54 
55   using FDEsMap = std::map<uint64_t, const dwarf::FDE *>;
56 
57   const FDEsMap &getFDEs() const { return FDEs; }
58 
59 private:
60   BinaryContext &BC;
61   FDEsMap FDEs;
62 };
63 
64 /// Parse an existing .eh_frame and invoke the callback for each
65 /// address that needs to be fixed if we want to preserve the original
66 /// .eh_frame while changing code location.
67 /// This code is based on DWARFDebugFrame::parse(), but trimmed down to
68 /// parse only the structures that have address references.
69 class EHFrameParser {
70 public:
71   using PatcherCallbackTy = std::function<void(uint64_t, uint64_t, uint64_t)>;
72 
73   /// Call PatcherCallback for every encountered external reference in frame
74   /// data. The expected signature is:
75   ///
76   ///   void PatcherCallback(uint64_t Value, uint64_t Offset, uint64_t Type);
77   ///
78   /// where Value is a value of the reference, Offset - is an offset into the
79   /// frame data at which the reference occurred, and Type is a DWARF encoding
80   /// type of the reference.
81   static Error parse(DWARFDataExtractor Data, uint64_t EHFrameAddress,
82                      PatcherCallbackTy PatcherCallback);
83 
84 private:
85   EHFrameParser(DWARFDataExtractor D, uint64_t E, PatcherCallbackTy P)
86       : Data(D), EHFrameAddress(E), PatcherCallback(P), Offset(0) {}
87 
88   struct CIEInfo {
89     uint64_t FDEPtrEncoding;
90     uint64_t LSDAPtrEncoding;
91     StringRef AugmentationString;
92 
93     CIEInfo(uint64_t F, uint64_t L, StringRef A)
94         : FDEPtrEncoding(F), LSDAPtrEncoding(L), AugmentationString(A) {}
95   };
96 
97   Error parseCIE(uint64_t StartOffset);
98   Error parseFDE(uint64_t CIEPointer, uint64_t StartStructureOffset);
99   Error parse();
100 
101   DWARFDataExtractor Data;
102   uint64_t EHFrameAddress;
103   PatcherCallbackTy PatcherCallback;
104   uint64_t Offset;
105   DenseMap<uint64_t, CIEInfo *> CIEs;
106   std::vector<std::unique_ptr<CIEInfo>> Entries;
107 };
108 
109 } // namespace bolt
110 } // namespace llvm
111 
112 #endif
113