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
23namespace llvm {
24
25class DWARFDebugFrame;
26
27namespace dwarf {
28class FDE;
29} // namespace dwarf
30
31namespace bolt {
32
33class BinaryContext;
34class 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.
38class CFIReaderWriter {
39public:
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 unless their initial_pc is listed
47 /// in \p FailedAddresses. All other entries are taken from the
48 /// \p OldEHFrame.
49 ///
50 /// \p EHFrameHeaderAddress specifies location of .eh_frame_hdr,
51 /// and is required for relative addressing used in the section.
52 std::vector<char>
53 generateEHFrameHeader(const DWARFDebugFrame &OldEHFrame,
54 const DWARFDebugFrame &NewEHFrame,
55 uint64_t EHFrameHeaderAddress,
56 std::vector<uint64_t> &FailedAddresses) const;
57
58 using FDEsMap = std::map<uint64_t, const dwarf::FDE *>;
59
60 const FDEsMap &getFDEs() const { return FDEs; }
61
62private:
63 BinaryContext &BC;
64 FDEsMap FDEs;
65};
66
67/// Parse an existing .eh_frame and invoke the callback for each
68/// address that needs to be fixed if we want to preserve the original
69/// .eh_frame while changing code location.
70/// This code is based on DWARFDebugFrame::parse(), but trimmed down to
71/// parse only the structures that have address references.
72class EHFrameParser {
73public:
74 using PatcherCallbackTy = std::function<void(uint64_t, uint64_t, uint64_t)>;
75
76 /// Call PatcherCallback for every encountered external reference in frame
77 /// data. The expected signature is:
78 ///
79 /// void PatcherCallback(uint64_t Value, uint64_t Offset, uint64_t Type);
80 ///
81 /// where Value is a value of the reference, Offset - is an offset into the
82 /// frame data at which the reference occurred, and Type is a DWARF encoding
83 /// type of the reference.
84 static Error parse(DWARFDataExtractor Data, uint64_t EHFrameAddress,
85 PatcherCallbackTy PatcherCallback);
86
87private:
88 EHFrameParser(DWARFDataExtractor D, uint64_t E, PatcherCallbackTy P)
89 : Data(D), EHFrameAddress(E), PatcherCallback(P), Offset(0) {}
90
91 struct CIEInfo {
92 uint64_t FDEPtrEncoding;
93 uint64_t LSDAPtrEncoding;
94 StringRef AugmentationString;
95
96 CIEInfo(uint64_t F, uint64_t L, StringRef A)
97 : FDEPtrEncoding(F), LSDAPtrEncoding(L), AugmentationString(A) {}
98 };
99
100 Error parseCIE(uint64_t StartOffset);
101 Error parseFDE(uint64_t CIEPointer, uint64_t StartStructureOffset);
102 Error parse();
103
104 DWARFDataExtractor Data;
105 uint64_t EHFrameAddress;
106 PatcherCallbackTy PatcherCallback;
107 uint64_t Offset;
108 DenseMap<uint64_t, CIEInfo *> CIEs;
109 std::vector<std::unique_ptr<CIEInfo>> Entries;
110};
111
112} // namespace bolt
113} // namespace llvm
114
115#endif
116

source code of bolt/include/bolt/Core/Exceptions.h