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