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