xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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