1 //===--- ARMWinEHPrinter.h - Windows on ARM Unwind Information Printer ----===// 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 #ifndef LLVM_TOOLS_LLVM_READOBJ_ARMWINEHPRINTER_H 10 #define LLVM_TOOLS_LLVM_READOBJ_ARMWINEHPRINTER_H 11 12 #include "llvm/Object/COFF.h" 13 #include "llvm/Support/ErrorOr.h" 14 #include "llvm/Support/ScopedPrinter.h" 15 16 namespace llvm { 17 namespace ARM { 18 namespace WinEH { 19 class RuntimeFunction; 20 21 class Decoder { 22 static const size_t PDataEntrySize; 23 24 ScopedPrinter &SW; 25 raw_ostream &OS; 26 bool isAArch64; 27 28 struct RingEntry { 29 uint8_t Mask; 30 uint8_t Value; 31 uint8_t Length; 32 bool (Decoder::*Routine)(const uint8_t *, unsigned &, unsigned, bool); 33 }; 34 static const RingEntry Ring[]; 35 static const RingEntry Ring64[]; 36 37 bool opcode_0xxxxxxx(const uint8_t *Opcodes, unsigned &Offset, 38 unsigned Length, bool Prologue); 39 bool opcode_10Lxxxxx(const uint8_t *Opcodes, unsigned &Offset, 40 unsigned Length, bool Prologue); 41 bool opcode_1100xxxx(const uint8_t *Opcodes, unsigned &Offset, 42 unsigned Length, bool Prologue); 43 bool opcode_11010Lxx(const uint8_t *Opcodes, unsigned &Offset, 44 unsigned Length, bool Prologue); 45 bool opcode_11011Lxx(const uint8_t *Opcodes, unsigned &Offset, 46 unsigned Length, bool Prologue); 47 bool opcode_11100xxx(const uint8_t *Opcodes, unsigned &Offset, 48 unsigned Length, bool Prologue); 49 bool opcode_111010xx(const uint8_t *Opcodes, unsigned &Offset, 50 unsigned Length, bool Prologue); 51 bool opcode_1110110L(const uint8_t *Opcodes, unsigned &Offset, 52 unsigned Length, bool Prologue); 53 bool opcode_11101110(const uint8_t *Opcodes, unsigned &Offset, 54 unsigned Length, bool Prologue); 55 bool opcode_11101111(const uint8_t *Opcodes, unsigned &Offset, 56 unsigned Length, bool Prologue); 57 bool opcode_11110101(const uint8_t *Opcodes, unsigned &Offset, 58 unsigned Length, bool Prologue); 59 bool opcode_11110110(const uint8_t *Opcodes, unsigned &Offset, 60 unsigned Length, bool Prologue); 61 bool opcode_11110111(const uint8_t *Opcodes, unsigned &Offset, 62 unsigned Length, bool Prologue); 63 bool opcode_11111000(const uint8_t *Opcodes, unsigned &Offset, 64 unsigned Length, bool Prologue); 65 bool opcode_11111001(const uint8_t *Opcodes, unsigned &Offset, 66 unsigned Length, bool Prologue); 67 bool opcode_11111010(const uint8_t *Opcodes, unsigned &Offset, 68 unsigned Length, bool Prologue); 69 bool opcode_11111011(const uint8_t *Opcodes, unsigned &Offset, 70 unsigned Length, bool Prologue); 71 bool opcode_11111100(const uint8_t *Opcodes, unsigned &Offset, 72 unsigned Length, bool Prologue); 73 bool opcode_11111101(const uint8_t *Opcodes, unsigned &Offset, 74 unsigned Length, bool Prologue); 75 bool opcode_11111110(const uint8_t *Opcodes, unsigned &Offset, 76 unsigned Length, bool Prologue); 77 bool opcode_11111111(const uint8_t *Opcodes, unsigned &Offset, 78 unsigned Length, bool Prologue); 79 80 // ARM64 unwind codes start here. 81 bool opcode_alloc_s(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 82 bool Prologue); 83 bool opcode_save_r19r20_x(const uint8_t *Opcodes, unsigned &Offset, 84 unsigned Length, bool Prologue); 85 bool opcode_save_fplr(const uint8_t *Opcodes, unsigned &Offset, 86 unsigned Length, bool Prologue); 87 bool opcode_save_fplr_x(const uint8_t *Opcodes, unsigned &Offset, 88 unsigned Length, bool Prologue); 89 bool opcode_alloc_m(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 90 bool Prologue); 91 bool opcode_save_regp(const uint8_t *Opcodes, unsigned &Offset, 92 unsigned Length, bool Prologue); 93 bool opcode_save_regp_x(const uint8_t *Opcodes, unsigned &Offset, 94 unsigned Length, bool Prologue); 95 bool opcode_save_reg(const uint8_t *Opcodes, unsigned &Offset, 96 unsigned Length, bool Prologue); 97 bool opcode_save_reg_x(const uint8_t *Opcodes, unsigned &Offset, 98 unsigned Length, bool Prologue); 99 bool opcode_save_lrpair(const uint8_t *Opcodes, unsigned &Offset, 100 unsigned Length, bool Prologue); 101 bool opcode_save_fregp(const uint8_t *Opcodes, unsigned &Offset, 102 unsigned Length, bool Prologue); 103 bool opcode_save_fregp_x(const uint8_t *Opcodes, unsigned &Offset, 104 unsigned Length, bool Prologue); 105 bool opcode_save_freg(const uint8_t *Opcodes, unsigned &Offset, 106 unsigned Length, bool Prologue); 107 bool opcode_save_freg_x(const uint8_t *Opcodes, unsigned &Offset, 108 unsigned Length, bool Prologue); 109 bool opcode_alloc_l(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 110 bool Prologue); 111 bool opcode_setfp(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 112 bool Prologue); 113 bool opcode_addfp(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 114 bool Prologue); 115 bool opcode_nop(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 116 bool Prologue); 117 bool opcode_end(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 118 bool Prologue); 119 bool opcode_end_c(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 120 bool Prologue); 121 bool opcode_save_next(const uint8_t *Opcodes, unsigned &Offset, 122 unsigned Length, bool Prologue); 123 124 void decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset, 125 bool Prologue); 126 127 void printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask); 128 129 ErrorOr<object::SectionRef> 130 getSectionContaining(const object::COFFObjectFile &COFF, uint64_t Address); 131 132 ErrorOr<object::SymbolRef> 133 getSymbol(const object::COFFObjectFile &COFF, uint64_t Address, 134 bool FunctionOnly = false); 135 136 ErrorOr<object::SymbolRef> 137 getRelocatedSymbol(const object::COFFObjectFile &COFF, 138 const object::SectionRef &Section, uint64_t Offset); 139 140 bool dumpXDataRecord(const object::COFFObjectFile &COFF, 141 const object::SectionRef &Section, 142 uint64_t FunctionAddress, uint64_t VA); 143 bool dumpUnpackedEntry(const object::COFFObjectFile &COFF, 144 const object::SectionRef Section, uint64_t Offset, 145 unsigned Index, const RuntimeFunction &Entry); 146 bool dumpPackedEntry(const object::COFFObjectFile &COFF, 147 const object::SectionRef Section, uint64_t Offset, 148 unsigned Index, const RuntimeFunction &Entry); 149 bool dumpProcedureDataEntry(const object::COFFObjectFile &COFF, 150 const object::SectionRef Section, unsigned Entry, 151 ArrayRef<uint8_t> Contents); 152 void dumpProcedureData(const object::COFFObjectFile &COFF, 153 const object::SectionRef Section); 154 155 public: 156 Decoder(ScopedPrinter &SW, bool isAArch64) : SW(SW), 157 OS(SW.getOStream()), 158 isAArch64(isAArch64) {} 159 Error dumpProcedureData(const object::COFFObjectFile &COFF); 160 }; 161 } 162 } 163 } 164 165 #endif 166