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 BinaryFunction;
34 
35 /// \brief Wraps up information to read all CFI instructions and feed them to a
36 /// BinaryFunction, as well as rewriting CFI sections.
37 class CFIReaderWriter {
38 public:
39   explicit CFIReaderWriter(const DWARFDebugFrame &EHFrame);
40 
41   bool fillCFIInfoFor(BinaryFunction &Function) const;
42 
43   /// Generate .eh_frame_hdr from old and new .eh_frame sections.
44   ///
45   /// Take FDEs from the \p NewEHFrame unless their initial_pc is listed
46   /// in \p FailedAddresses. 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>
52   generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame,
53                         const DWARFDebugFrame &NewEHFrame,
54                         uint64_t EHFrameHeaderAddress,
55                         std::vector<uint64_t> &FailedAddresses) const;
56 
57   using FDEsMap = std::map<uint64_t, const dwarf::FDE *>;
58 
getFDEs()59   const FDEsMap &getFDEs() const { return FDEs; }
60 
61 private:
62   FDEsMap FDEs;
63 };
64 
65 /// Parse an existing .eh_frame and invoke the callback for each
66 /// address that needs to be fixed if we want to preserve the original
67 /// .eh_frame while changing code location.
68 /// This code is based on DWARFDebugFrame::parse(), but trimmed down to
69 /// parse only the structures that have address references.
70 class EHFrameParser {
71 public:
72   using PatcherCallbackTy = std::function<void(uint64_t, uint64_t, uint64_t)>;
73 
74   /// Call PatcherCallback for every encountered external reference in frame
75   /// data. The expected signature is:
76   ///
77   ///   void PatcherCallback(uint64_t Value, uint64_t Offset, uint64_t Type);
78   ///
79   /// where Value is a value of the reference, Offset - is an offset into the
80   /// frame data at which the reference occured, and Type is a DWARF encoding
81   /// type of the reference.
82   static Error parse(DWARFDataExtractor Data, uint64_t EHFrameAddress,
83                      PatcherCallbackTy PatcherCallback);
84 
85 private:
EHFrameParser(DWARFDataExtractor D,uint64_t E,PatcherCallbackTy P)86   EHFrameParser(DWARFDataExtractor D, uint64_t E, PatcherCallbackTy P)
87       : Data(D), EHFrameAddress(E), PatcherCallback(P), Offset(0) {}
88 
89   struct CIEInfo {
90     uint64_t FDEPtrEncoding;
91     uint64_t LSDAPtrEncoding;
92     StringRef AugmentationString;
93 
CIEInfoCIEInfo94     CIEInfo(uint64_t F, uint64_t L, StringRef A)
95         : FDEPtrEncoding(F), LSDAPtrEncoding(L), AugmentationString(A) {}
96   };
97 
98   Error parseCIE(uint64_t StartOffset);
99   Error parseFDE(uint64_t CIEPointer, uint64_t StartStructureOffset);
100   Error parse();
101 
102   DWARFDataExtractor Data;
103   uint64_t EHFrameAddress;
104   PatcherCallbackTy PatcherCallback;
105   uint64_t Offset;
106   DenseMap<uint64_t, CIEInfo *> CIEs;
107   std::vector<std::unique_ptr<CIEInfo>> Entries;
108 };
109 
110 } // namespace bolt
111 } // namespace llvm
112 
113 #endif
114