10b57cec5SDimitry Andric //===--- ARMWinEHPrinter.h - Windows on ARM Unwind Information Printer ----===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_TOOLS_LLVM_READOBJ_ARMWINEHPRINTER_H 100b57cec5SDimitry Andric #define LLVM_TOOLS_LLVM_READOBJ_ARMWINEHPRINTER_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 130b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h" 140b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric namespace llvm { 170b57cec5SDimitry Andric namespace ARM { 180b57cec5SDimitry Andric namespace WinEH { 190b57cec5SDimitry Andric class RuntimeFunction; 20e8d8bef9SDimitry Andric class RuntimeFunctionARM64; 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric class Decoder { 230b57cec5SDimitry Andric static const size_t PDataEntrySize; 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric ScopedPrinter &SW; 260b57cec5SDimitry Andric raw_ostream &OS; 270b57cec5SDimitry Andric bool isAArch64; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric struct RingEntry { 300b57cec5SDimitry Andric uint8_t Mask; 310b57cec5SDimitry Andric uint8_t Value; 320b57cec5SDimitry Andric uint8_t Length; 330b57cec5SDimitry Andric bool (Decoder::*Routine)(const uint8_t *, unsigned &, unsigned, bool); 340b57cec5SDimitry Andric }; 350b57cec5SDimitry Andric static const RingEntry Ring[]; 360b57cec5SDimitry Andric static const RingEntry Ring64[]; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric bool opcode_0xxxxxxx(const uint8_t *Opcodes, unsigned &Offset, 390b57cec5SDimitry Andric unsigned Length, bool Prologue); 400b57cec5SDimitry Andric bool opcode_10Lxxxxx(const uint8_t *Opcodes, unsigned &Offset, 410b57cec5SDimitry Andric unsigned Length, bool Prologue); 420b57cec5SDimitry Andric bool opcode_1100xxxx(const uint8_t *Opcodes, unsigned &Offset, 430b57cec5SDimitry Andric unsigned Length, bool Prologue); 440b57cec5SDimitry Andric bool opcode_11010Lxx(const uint8_t *Opcodes, unsigned &Offset, 450b57cec5SDimitry Andric unsigned Length, bool Prologue); 460b57cec5SDimitry Andric bool opcode_11011Lxx(const uint8_t *Opcodes, unsigned &Offset, 470b57cec5SDimitry Andric unsigned Length, bool Prologue); 480b57cec5SDimitry Andric bool opcode_11100xxx(const uint8_t *Opcodes, unsigned &Offset, 490b57cec5SDimitry Andric unsigned Length, bool Prologue); 500b57cec5SDimitry Andric bool opcode_111010xx(const uint8_t *Opcodes, unsigned &Offset, 510b57cec5SDimitry Andric unsigned Length, bool Prologue); 520b57cec5SDimitry Andric bool opcode_1110110L(const uint8_t *Opcodes, unsigned &Offset, 530b57cec5SDimitry Andric unsigned Length, bool Prologue); 540b57cec5SDimitry Andric bool opcode_11101110(const uint8_t *Opcodes, unsigned &Offset, 550b57cec5SDimitry Andric unsigned Length, bool Prologue); 560b57cec5SDimitry Andric bool opcode_11101111(const uint8_t *Opcodes, unsigned &Offset, 570b57cec5SDimitry Andric unsigned Length, bool Prologue); 580b57cec5SDimitry Andric bool opcode_11110101(const uint8_t *Opcodes, unsigned &Offset, 590b57cec5SDimitry Andric unsigned Length, bool Prologue); 600b57cec5SDimitry Andric bool opcode_11110110(const uint8_t *Opcodes, unsigned &Offset, 610b57cec5SDimitry Andric unsigned Length, bool Prologue); 620b57cec5SDimitry Andric bool opcode_11110111(const uint8_t *Opcodes, unsigned &Offset, 630b57cec5SDimitry Andric unsigned Length, bool Prologue); 640b57cec5SDimitry Andric bool opcode_11111000(const uint8_t *Opcodes, unsigned &Offset, 650b57cec5SDimitry Andric unsigned Length, bool Prologue); 660b57cec5SDimitry Andric bool opcode_11111001(const uint8_t *Opcodes, unsigned &Offset, 670b57cec5SDimitry Andric unsigned Length, bool Prologue); 680b57cec5SDimitry Andric bool opcode_11111010(const uint8_t *Opcodes, unsigned &Offset, 690b57cec5SDimitry Andric unsigned Length, bool Prologue); 700b57cec5SDimitry Andric bool opcode_11111011(const uint8_t *Opcodes, unsigned &Offset, 710b57cec5SDimitry Andric unsigned Length, bool Prologue); 720b57cec5SDimitry Andric bool opcode_11111100(const uint8_t *Opcodes, unsigned &Offset, 730b57cec5SDimitry Andric unsigned Length, bool Prologue); 740b57cec5SDimitry Andric bool opcode_11111101(const uint8_t *Opcodes, unsigned &Offset, 750b57cec5SDimitry Andric unsigned Length, bool Prologue); 760b57cec5SDimitry Andric bool opcode_11111110(const uint8_t *Opcodes, unsigned &Offset, 770b57cec5SDimitry Andric unsigned Length, bool Prologue); 780b57cec5SDimitry Andric bool opcode_11111111(const uint8_t *Opcodes, unsigned &Offset, 790b57cec5SDimitry Andric unsigned Length, bool Prologue); 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric // ARM64 unwind codes start here. 820b57cec5SDimitry Andric bool opcode_alloc_s(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 830b57cec5SDimitry Andric bool Prologue); 840b57cec5SDimitry Andric bool opcode_save_r19r20_x(const uint8_t *Opcodes, unsigned &Offset, 850b57cec5SDimitry Andric unsigned Length, bool Prologue); 860b57cec5SDimitry Andric bool opcode_save_fplr(const uint8_t *Opcodes, unsigned &Offset, 870b57cec5SDimitry Andric unsigned Length, bool Prologue); 880b57cec5SDimitry Andric bool opcode_save_fplr_x(const uint8_t *Opcodes, unsigned &Offset, 890b57cec5SDimitry Andric unsigned Length, bool Prologue); 900b57cec5SDimitry Andric bool opcode_alloc_m(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 910b57cec5SDimitry Andric bool Prologue); 920b57cec5SDimitry Andric bool opcode_save_regp(const uint8_t *Opcodes, unsigned &Offset, 930b57cec5SDimitry Andric unsigned Length, bool Prologue); 940b57cec5SDimitry Andric bool opcode_save_regp_x(const uint8_t *Opcodes, unsigned &Offset, 950b57cec5SDimitry Andric unsigned Length, bool Prologue); 960b57cec5SDimitry Andric bool opcode_save_reg(const uint8_t *Opcodes, unsigned &Offset, 970b57cec5SDimitry Andric unsigned Length, bool Prologue); 980b57cec5SDimitry Andric bool opcode_save_reg_x(const uint8_t *Opcodes, unsigned &Offset, 990b57cec5SDimitry Andric unsigned Length, bool Prologue); 1000b57cec5SDimitry Andric bool opcode_save_lrpair(const uint8_t *Opcodes, unsigned &Offset, 1010b57cec5SDimitry Andric unsigned Length, bool Prologue); 1020b57cec5SDimitry Andric bool opcode_save_fregp(const uint8_t *Opcodes, unsigned &Offset, 1030b57cec5SDimitry Andric unsigned Length, bool Prologue); 1040b57cec5SDimitry Andric bool opcode_save_fregp_x(const uint8_t *Opcodes, unsigned &Offset, 1050b57cec5SDimitry Andric unsigned Length, bool Prologue); 1060b57cec5SDimitry Andric bool opcode_save_freg(const uint8_t *Opcodes, unsigned &Offset, 1070b57cec5SDimitry Andric unsigned Length, bool Prologue); 1080b57cec5SDimitry Andric bool opcode_save_freg_x(const uint8_t *Opcodes, unsigned &Offset, 1090b57cec5SDimitry Andric unsigned Length, bool Prologue); 1100b57cec5SDimitry Andric bool opcode_alloc_l(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 1110b57cec5SDimitry Andric bool Prologue); 1120b57cec5SDimitry Andric bool opcode_setfp(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 1130b57cec5SDimitry Andric bool Prologue); 1140b57cec5SDimitry Andric bool opcode_addfp(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 1150b57cec5SDimitry Andric bool Prologue); 1160b57cec5SDimitry Andric bool opcode_nop(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 1170b57cec5SDimitry Andric bool Prologue); 1180b57cec5SDimitry Andric bool opcode_end(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 1190b57cec5SDimitry Andric bool Prologue); 1200b57cec5SDimitry Andric bool opcode_end_c(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 1210b57cec5SDimitry Andric bool Prologue); 1220b57cec5SDimitry Andric bool opcode_save_next(const uint8_t *Opcodes, unsigned &Offset, 1230b57cec5SDimitry Andric unsigned Length, bool Prologue); 124bdd1243dSDimitry Andric bool opcode_save_any_reg(const uint8_t *Opcodes, unsigned &Offset, 125bdd1243dSDimitry Andric unsigned Length, bool Prologue); 126e8d8bef9SDimitry Andric bool opcode_trap_frame(const uint8_t *Opcodes, unsigned &Offset, 127e8d8bef9SDimitry Andric unsigned Length, bool Prologue); 128e8d8bef9SDimitry Andric bool opcode_machine_frame(const uint8_t *Opcodes, unsigned &Offset, 129e8d8bef9SDimitry Andric unsigned Length, bool Prologue); 130e8d8bef9SDimitry Andric bool opcode_context(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, 131e8d8bef9SDimitry Andric bool Prologue); 132*5f757f3fSDimitry Andric bool opcode_ec_context(const uint8_t *Opcodes, unsigned &Offset, 133*5f757f3fSDimitry Andric unsigned Length, bool Prologue); 134e8d8bef9SDimitry Andric bool opcode_clear_unwound_to_call(const uint8_t *Opcodes, unsigned &Offset, 135e8d8bef9SDimitry Andric unsigned Length, bool Prologue); 136bdd1243dSDimitry Andric bool opcode_pac_sign_lr(const uint8_t *Opcodes, unsigned &Offset, 137bdd1243dSDimitry Andric unsigned Length, bool Prologue); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric void decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset, 1400b57cec5SDimitry Andric bool Prologue); 1410b57cec5SDimitry Andric 14281ad6265SDimitry Andric void printGPRMask(uint16_t Mask); 14381ad6265SDimitry Andric void printVFPMask(uint32_t Mask); 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric ErrorOr<object::SectionRef> 1460b57cec5SDimitry Andric getSectionContaining(const object::COFFObjectFile &COFF, uint64_t Address); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric ErrorOr<object::SymbolRef> 1490b57cec5SDimitry Andric getSymbol(const object::COFFObjectFile &COFF, uint64_t Address, 1500b57cec5SDimitry Andric bool FunctionOnly = false); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric ErrorOr<object::SymbolRef> 1530b57cec5SDimitry Andric getRelocatedSymbol(const object::COFFObjectFile &COFF, 1540b57cec5SDimitry Andric const object::SectionRef &Section, uint64_t Offset); 1550b57cec5SDimitry Andric 156fe6060f1SDimitry Andric ErrorOr<object::SymbolRef> 157fe6060f1SDimitry Andric getSymbolForLocation(const object::COFFObjectFile &COFF, 158fe6060f1SDimitry Andric const object::SectionRef &Section, 159fe6060f1SDimitry Andric uint64_t OffsetInSection, uint64_t ImmediateOffset, 160fe6060f1SDimitry Andric uint64_t &SymbolAddress, uint64_t &SymbolOffset, 161fe6060f1SDimitry Andric bool FunctionOnly = false); 162fe6060f1SDimitry Andric 163fe6060f1SDimitry Andric object::SymbolRef getPreferredSymbol(const object::COFFObjectFile &COFF, 164349cc55cSDimitry Andric object::SymbolRef Sym, 165349cc55cSDimitry Andric uint64_t &SymbolOffset); 166fe6060f1SDimitry Andric 1670b57cec5SDimitry Andric bool dumpXDataRecord(const object::COFFObjectFile &COFF, 1680b57cec5SDimitry Andric const object::SectionRef &Section, 1690b57cec5SDimitry Andric uint64_t FunctionAddress, uint64_t VA); 1700b57cec5SDimitry Andric bool dumpUnpackedEntry(const object::COFFObjectFile &COFF, 1710b57cec5SDimitry Andric const object::SectionRef Section, uint64_t Offset, 1720b57cec5SDimitry Andric unsigned Index, const RuntimeFunction &Entry); 1730b57cec5SDimitry Andric bool dumpPackedEntry(const object::COFFObjectFile &COFF, 1740b57cec5SDimitry Andric const object::SectionRef Section, uint64_t Offset, 1750b57cec5SDimitry Andric unsigned Index, const RuntimeFunction &Entry); 176e8d8bef9SDimitry Andric bool dumpPackedARM64Entry(const object::COFFObjectFile &COFF, 177e8d8bef9SDimitry Andric const object::SectionRef Section, uint64_t Offset, 178e8d8bef9SDimitry Andric unsigned Index, const RuntimeFunctionARM64 &Entry); 1790b57cec5SDimitry Andric bool dumpProcedureDataEntry(const object::COFFObjectFile &COFF, 1800b57cec5SDimitry Andric const object::SectionRef Section, unsigned Entry, 1810b57cec5SDimitry Andric ArrayRef<uint8_t> Contents); 1820b57cec5SDimitry Andric void dumpProcedureData(const object::COFFObjectFile &COFF, 1830b57cec5SDimitry Andric const object::SectionRef Section); 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric public: 1860b57cec5SDimitry Andric Decoder(ScopedPrinter &SW, bool isAArch64) : SW(SW), 1870b57cec5SDimitry Andric OS(SW.getOStream()), 1880b57cec5SDimitry Andric isAArch64(isAArch64) {} 1890b57cec5SDimitry Andric Error dumpProcedureData(const object::COFFObjectFile &COFF); 1900b57cec5SDimitry Andric }; 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric #endif 196