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