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