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_save_any_reg(const uint8_t *Opcodes, unsigned &Offset, 125 unsigned Length, bool Prologue); 126 bool opcode_trap_frame(const uint8_t *Opcodes, unsigned &Offset, 127 unsigned Length, bool Prologue); 128 bool opcode_machine_frame(const uint8_t *Opcodes, unsigned &Offset, 129 unsigned Length, bool Prologue); 130 bool opcode_context(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 131 bool Prologue); 132 bool opcode_ec_context(const uint8_t *Opcodes, unsigned &Offset, 133 unsigned Length, bool Prologue); 134 bool opcode_clear_unwound_to_call(const uint8_t *Opcodes, unsigned &Offset, 135 unsigned Length, bool Prologue); 136 bool opcode_pac_sign_lr(const uint8_t *Opcodes, unsigned &Offset, 137 unsigned Length, bool Prologue); 138 139 void decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset, 140 bool Prologue); 141 142 void printGPRMask(uint16_t Mask); 143 void printVFPMask(uint32_t Mask); 144 145 ErrorOr<object::SectionRef> 146 getSectionContaining(const object::COFFObjectFile &COFF, uint64_t Address); 147 148 ErrorOr<object::SymbolRef> 149 getSymbol(const object::COFFObjectFile &COFF, uint64_t Address, 150 bool FunctionOnly = false); 151 152 ErrorOr<object::SymbolRef> 153 getRelocatedSymbol(const object::COFFObjectFile &COFF, 154 const object::SectionRef &Section, uint64_t Offset); 155 156 ErrorOr<object::SymbolRef> 157 getSymbolForLocation(const object::COFFObjectFile &COFF, 158 const object::SectionRef &Section, 159 uint64_t OffsetInSection, uint64_t ImmediateOffset, 160 uint64_t &SymbolAddress, uint64_t &SymbolOffset, 161 bool FunctionOnly = false); 162 163 object::SymbolRef getPreferredSymbol(const object::COFFObjectFile &COFF, 164 object::SymbolRef Sym, 165 uint64_t &SymbolOffset); 166 167 bool dumpXDataRecord(const object::COFFObjectFile &COFF, 168 const object::SectionRef &Section, 169 uint64_t FunctionAddress, uint64_t VA); 170 bool dumpUnpackedEntry(const object::COFFObjectFile &COFF, 171 const object::SectionRef Section, uint64_t Offset, 172 unsigned Index, const RuntimeFunction &Entry); 173 bool dumpPackedEntry(const object::COFFObjectFile &COFF, 174 const object::SectionRef Section, uint64_t Offset, 175 unsigned Index, const RuntimeFunction &Entry); 176 bool dumpPackedARM64Entry(const object::COFFObjectFile &COFF, 177 const object::SectionRef Section, uint64_t Offset, 178 unsigned Index, const RuntimeFunctionARM64 &Entry); 179 bool dumpProcedureDataEntry(const object::COFFObjectFile &COFF, 180 const object::SectionRef Section, unsigned Entry, 181 ArrayRef<uint8_t> Contents); 182 void dumpProcedureData(const object::COFFObjectFile &COFF, 183 const object::SectionRef Section); 184 185 public: 186 Decoder(ScopedPrinter &SW, bool isAArch64) : SW(SW), 187 OS(SW.getOStream()), 188 isAArch64(isAArch64) {} 189 Error dumpProcedureData(const object::COFFObjectFile &COFF); 190 }; 191 } 192 } 193 } 194 195 #endif 196