1cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//===-- ARMWinEHPrinter.cpp - Windows on ARM EH Data Printer ----*- C++ -*-===//
2cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
3cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//                     The LLVM Compiler Infrastructure
4cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
5cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// This file is distributed under the University of Illinois Open Source
6cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// License. See LICENSE.TXT for details.
7cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
8cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//===----------------------------------------------------------------------===//
9cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
10cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// Windows on ARM uses a series of serialised data structures (RuntimeFunction)
11cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// to create a table of information for unwinding.  In order to conserve space,
12cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// there are two different ways that this data is represented.
13cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
14cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// For functions with canonical forms for the prologue and epilogue, the data
15cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// can be stored in a "packed" form.  In this case, the data is packed into the
16cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// RuntimeFunction's remaining 30-bits and can fully describe the entire frame.
17cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
18cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        +---------------------------------------+
19cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        |         Function Entry Address        |
20cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        +---------------------------------------+
21cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        |           Packed Form Data            |
22cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        +---------------------------------------+
23cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
24cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// This layout is parsed by Decoder::dumpPackedEntry.  No unwind bytecode is
25cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// associated with such a frame as they can be derived from the provided data.
26cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// The decoder does not synthesize this data as it is unnecessary for the
27cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// purposes of validation, with the synthesis being required only by a proper
28cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// unwinder.
29cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
30cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// For functions that are large or do not match canonical forms, the data is
31cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// split up into two portions, with the actual data residing in the "exception
32cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// data" table (.xdata) with a reference to the entry from the "procedure data"
33cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// (.pdata) entry.
34cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
35cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// The exception data contains information about the frame setup, all of the
36cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// epilouge scopes (for functions for which there are multiple exit points) and
37cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// the associated exception handler.  Additionally, the entry contains byte-code
38cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// describing how to unwind the function (c.f. Decoder::decodeOpcodes).
39cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
40cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        +---------------------------------------+
41cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        |         Function Entry Address        |
42cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        +---------------------------------------+
43cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        |      Exception Data Entry Address     |
44cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//        +---------------------------------------+
45cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
46cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// This layout is parsed by Decoder::dumpUnpackedEntry.  Such an entry must
47cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// first resolve the exception data entry address.  This structure
48cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// (ExceptionDataRecord) has a variable sized header
49cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// (c.f. ARM::WinEH::HeaderWords) and encodes most of the same information as
50cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// the packed form.  However, because this information is insufficient to
51cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// synthesize the unwinding, there are associated unwinding bytecode which make
52cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// up the bulk of the Decoder.
53cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
54cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// The decoder itself is table-driven, using the first byte to determine the
55cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// opcode and dispatching to the associated printing routine.  The bytecode
56cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// itself is a variable length instruction encoding that can fully describe the
57cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// state of the stack and the necessary operations for unwinding to the
58cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// beginning of the frame.
59cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines//
60cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// The byte-code maintains a 1-1 instruction mapping, indicating both the width
61cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// of the instruction (Thumb2 instructions are variable length, 16 or 32 bits
62cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// wide) allowing the program to unwind from any point in the prologue, body, or
63cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// epilogue of the function.
64cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
65cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "ARMWinEHPrinter.h"
66cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "Error.h"
67cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/ADT/StringExtras.h"
68cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/ADT/STLExtras.h"
69cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/ARMWinEH.h"
70cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/Format.h"
71cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
72cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesusing namespace llvm;
73cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesusing namespace llvm::object;
74cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesusing namespace llvm::support;
75cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
76cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesnamespace llvm {
77cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesraw_ostream &operator<<(raw_ostream &OS, const ARM::WinEH::ReturnType &RT) {
78cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  switch (RT) {
79cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  case ARM::WinEH::ReturnType::RT_POP:
80cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << "pop {pc}";
81cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    break;
82cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  case ARM::WinEH::ReturnType::RT_B:
83cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << "b target";
84cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    break;
85cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  case ARM::WinEH::ReturnType::RT_BW:
86cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << "b.w target";
87cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    break;
88cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  case ARM::WinEH::ReturnType::RT_NoEpilogue:
89cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << "(no epilogue)";
90cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    break;
91cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
92cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return OS;
93cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
94cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
95cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
96cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic std::string formatSymbol(StringRef Name, uint64_t Address,
97cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                uint64_t Offset = 0) {
98cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  std::string Buffer;
99cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  raw_string_ostream OS(Buffer);
100cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
101cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!Name.empty())
102cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << Name << " ";
103cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
104cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Offset)
105cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << format("+0x%X (0x%" PRIX64 ")", Offset, Address);
106cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  else if (!Name.empty())
107cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << format("(0x%" PRIX64 ")", Address);
108cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  else
109cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    OS << format("0x%" PRIX64, Address);
110cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
111cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return OS.str();
112cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
113cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
114cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesnamespace llvm {
115cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesnamespace ARM {
116cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesnamespace WinEH {
117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesconst size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);
118cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
119cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// TODO name the uops more appropriately
120cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesconst Decoder::RingEntry Decoder::Ring[] = {
121cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0x80, 0x00, &Decoder::opcode_0xxxxxxx },  // UOP_STACK_FREE (16-bit)
122cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xc0, 0x80, &Decoder::opcode_10Lxxxxx },  // UOP_POP (32-bit)
123cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xf0, 0xc0, &Decoder::opcode_1100xxxx },  // UOP_STACK_SAVE (16-bit)
124cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xf8, 0xd0, &Decoder::opcode_11010Lxx },  // UOP_POP (16-bit)
125cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xf8, 0xd8, &Decoder::opcode_11011Lxx },  // UOP_POP (32-bit)
126cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xf8, 0xe0, &Decoder::opcode_11100xxx },  // UOP_VPOP (32-bit)
127cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xfc, 0xe8, &Decoder::opcode_111010xx },  // UOP_STACK_FREE (32-bit)
128cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xfe, 0xec, &Decoder::opcode_1110110L },  // UOP_POP (16-bit)
129cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xee, &Decoder::opcode_11101110 },  // UOP_MICROSOFT_SPECIFIC (16-bit)
130cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                              // UOP_PUSH_MACHINE_FRAME
131cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                              // UOP_PUSH_CONTEXT
132cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                              // UOP_PUSH_TRAP_FRAME
133cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                              // UOP_REDZONE_RESTORE_LR
134cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xef, &Decoder::opcode_11101111 },  // UOP_LDRPC_POSTINC (32-bit)
135cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xf5, &Decoder::opcode_11110101 },  // UOP_VPOP (32-bit)
136cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xf6, &Decoder::opcode_11110110 },  // UOP_VPOP (32-bit)
137cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xf7, &Decoder::opcode_11110111 },  // UOP_STACK_RESTORE (16-bit)
138cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xf8, &Decoder::opcode_11111000 },  // UOP_STACK_RESTORE (16-bit)
139cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xf9, &Decoder::opcode_11111001 },  // UOP_STACK_RESTORE (32-bit)
140cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xfa, &Decoder::opcode_11111010 },  // UOP_STACK_RESTORE (32-bit)
141cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xfb, &Decoder::opcode_11111011 },  // UOP_NOP (16-bit)
142cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xfc, &Decoder::opcode_11111100 },  // UOP_NOP (32-bit)
143cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xfd, &Decoder::opcode_11111101 },  // UOP_NOP (16-bit) / END
144cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xfe, &Decoder::opcode_11111110 },  // UOP_NOP (32-bit) / END
145cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  { 0xff, 0xff, &Decoder::opcode_11111111 },  // UOP_END
146cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines};
147cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
148cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesvoid Decoder::printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask) {
149cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  static const char * const GPRRegisterNames[16] = {
150cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
151cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    "r11", "ip", "sp", "lr", "pc",
152cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  };
153cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
154cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const uint16_t GPRMask = std::get<0>(RegisterMask);
155cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const uint16_t VFPMask = std::get<1>(RegisterMask);
156cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
157cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '{';
158cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  bool Comma = false;
159cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned RI = 0, RE = 11; RI < RE; ++RI) {
160cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (GPRMask & (1 << RI)) {
161cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (Comma)
162cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        OS << ", ";
163cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      OS << GPRRegisterNames[RI];
164cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Comma = true;
165cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
166cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
167cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
168cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (VFPMask & (1 << RI)) {
169cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (Comma)
170cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        OS << ", ";
171cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      OS << "d" << unsigned(RI);
172cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Comma = true;
173cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
174cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
175cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned RI = 11, RE = 16; RI < RE; ++RI) {
176cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (GPRMask & (1 << RI)) {
177cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (Comma)
178cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        OS << ", ";
179cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      OS << GPRRegisterNames[RI];
180cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Comma = true;
181cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
182cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
183cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '}';
184cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
185cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
186cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesErrorOr<object::SectionRef>
187cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesDecoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {
188cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (const auto &Section : COFF.sections()) {
189cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    uint64_t Address;
190cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    uint64_t Size;
191cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
192cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (std::error_code EC = Section.getAddress(Address))
193cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return EC;
194cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (std::error_code EC = Section.getSize(Size))
195cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return EC;
196cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
197cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (VA >= Address && (VA - Address) <= Size)
198cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return Section;
199cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
200cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return readobj_error::unknown_symbol;
201cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
202cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
203cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF,
204cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                              uint64_t VA, bool FunctionOnly) {
205cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (const auto &Symbol : COFF.symbols()) {
206cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (FunctionOnly) {
207cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      SymbolRef::Type Type;
208cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (std::error_code EC = Symbol.getType(Type))
209cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        return EC;
210cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if (Type != SymbolRef::ST_Function)
211cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        continue;
212cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
213cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
214cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    uint64_t Address;
215cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (std::error_code EC = Symbol.getAddress(Address))
216cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return EC;
217cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (Address == VA)
218cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return Symbol;
219cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
220cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return readobj_error::unknown_symbol;
221cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
222cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
223cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,
224cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                               const SectionRef &Section,
225cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                               uint64_t Offset) {
226cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (const auto &Relocation : Section.relocations()) {
227cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    uint64_t RelocationOffset;
228cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (auto Error = Relocation.getOffset(RelocationOffset))
229cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return Error;
230cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (RelocationOffset == Offset)
231cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return *Relocation.getSymbol();
232cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
233cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return readobj_error::unknown_symbol;
234cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
235cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
236cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_0xxxxxxx(const ulittle8_t *OC, unsigned &Offset,
237cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
238cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint8_t Imm = OC[Offset] & 0x7f;
239cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; %s sp, #(%u * 4)\n",
240cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           OC[Offset],
241cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           static_cast<const char *>(Prologue ? "sub" : "add"),
242cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           Imm);
243cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
244cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
245cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
246cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
247cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_10Lxxxxx(const ulittle8_t *OC, unsigned &Offset,
248cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
249cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned Link = (OC[Offset] & 0x20) >> 5;
250cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))
251cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                        | ((OC[Offset + 0] & 0x1f) << 8)
252cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                        | ((OC[Offset + 1] & 0xff) << 0);
253cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert((~RegisterMask & (1 << 13)) && "sp must not be set");
254cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");
255cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
256cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",
257cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           OC[Offset + 0], OC[Offset + 1],
258cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           Prologue ? "push" : "pop");
259cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  printRegisters(std::make_pair(RegisterMask, 0));
260cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
261cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
262cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset;
263cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
264cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
265cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
266cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_1100xxxx(const ulittle8_t *OC, unsigned &Offset,
267cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
268cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Prologue)
269cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.startLine() << format("0x%02x                ; mov r%u, sp\n",
270cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                             OC[Offset], OC[Offset] & 0xf);
271cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  else
272cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.startLine() << format("0x%02x                ; mov sp, r%u\n",
273cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                             OC[Offset], OC[Offset] & 0xf);
274cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
275cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
276cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
277cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
278cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11010Lxx(const ulittle8_t *OC, unsigned &Offset,
279cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
280cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned Link = (OC[Offset] & 0x4) >> 3;
281cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned Count = (OC[Offset] & 0x3);
282cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
283cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
284cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                   | (((1 << (Count + 1)) - 1) << 4);
285cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
286cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
287cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           Prologue ? "push" : "pop");
288cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  printRegisters(std::make_pair(GPRMask, 0));
289cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
290cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
291cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
292cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
293cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
294cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
295cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11011Lxx(const ulittle8_t *OC, unsigned &Offset,
296cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
297cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned Link = (OC[Offset] & 0x4) >> 2;
298cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned Count = (OC[Offset] & 0x3) + 4;
299cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
300cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
301cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                   | (((1 << (Count + 1)) - 1) << 4);
302cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
303cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],
304cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           Prologue ? "push" : "pop");
305cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  printRegisters(std::make_pair(GPRMask, 0));
306cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
307cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
308cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
309cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
310cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
311cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
312cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11100xxx(const ulittle8_t *OC, unsigned &Offset,
313cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
314cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned High = (OC[Offset] & 0x7);
315cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);
316cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
317cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
318cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           Prologue ? "vpush" : "vpop");
319cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  printRegisters(std::make_pair(0, VFPMask));
320cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
321cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
322cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
323cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
324cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
325cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
326cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_111010xx(const ulittle8_t *OC, unsigned &Offset,
327cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
328cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);
329cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
330cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x 0x%02x           ; %s.w sp, #(%u * 4)\n",
331cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           OC[Offset + 0], OC[Offset + 1],
332cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           static_cast<const char *>(Prologue ? "sub" : "add"),
333cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           Imm);
334cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
335cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset;
336cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
337cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
338cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
339cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_1110110L(const ulittle8_t *OC, unsigned &Offset,
340cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
341cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))
342cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  | ((OC[Offset + 1] & 0xff) << 0);
343cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
344cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
345cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           OC[Offset + 1], Prologue ? "push" : "pop");
346cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  printRegisters(std::make_pair(GPRMask, 0));
347cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
348cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
349cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset;
350cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
351cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
352cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
353cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11101110(const ulittle8_t *OC, unsigned &Offset,
354cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
355cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert(!Prologue && "may not be used in prologue");
356cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
357cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (OC[Offset + 1] & 0xf0)
358cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
359cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                             OC[Offset + 0], OC[Offset +  1]);
360cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  else
361cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.startLine()
362cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      << format("0x%02x 0x%02x           ; microsoft-specific (type: %u)\n",
363cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);
364cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
365cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset;
366cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
367cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
368cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
369cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11101111(const ulittle8_t *OC, unsigned &Offset,
370cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
371cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert(!Prologue && "may not be used in prologue");
372cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
373cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (OC[Offset + 1] & 0xf0)
374cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
375cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                             OC[Offset + 0], OC[Offset +  1]);
376cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  else
377cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.startLine()
378cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      << format("0x%02x 0x%02x           ; ldr.w lr, [sp], #%u\n",
379cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
380cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
381cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset;
382cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
383cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
384cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
385cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11110101(const ulittle8_t *OC, unsigned &Offset,
386cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
387cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
388cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
389cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t VFPMask = ((1 << (End - Start)) - 1) << Start;
390cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
391cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
392cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
393cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  printRegisters(std::make_pair(0, VFPMask));
394cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
395cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
396cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset;
397cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
398cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
399cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
400cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11110110(const ulittle8_t *OC, unsigned &Offset,
401cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
402cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
403cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
404cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t VFPMask = ((1 << (End - Start)) - 1) << 16;
405cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
406cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
407cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
408cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  printRegisters(std::make_pair(0, VFPMask));
409cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
410cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
411cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset;
412cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
413cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
414cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
415cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11110111(const ulittle8_t *OC, unsigned &Offset,
416cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
417cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
418cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
419cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x 0x%02x 0x%02x      ; %s sp, sp, #(%u * 4)\n",
420cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
421cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           static_cast<const char *>(Prologue ? "sub" : "add"),
422cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           Imm);
423cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
424cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset, ++Offset;
425cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
426cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
427cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
428cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111000(const ulittle8_t *OC, unsigned &Offset,
429cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
430cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t Imm = (OC[Offset + 1] << 16)
431cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               | (OC[Offset + 2] << 8)
432cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               | (OC[Offset + 3] << 0);
433cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
434cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine()
435cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
436cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
437cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
438cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
439cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset, ++Offset, ++Offset;
440cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
441cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
442cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
443cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111001(const ulittle8_t *OC, unsigned &Offset,
444cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
445cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
446cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
447cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine()
448cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    << format("0x%02x 0x%02x 0x%02x      ; %s.w sp, sp, #(%u * 4)\n",
449cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
450cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
451cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
452cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset, ++Offset;
453cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
454cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
455cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
456cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111010(const ulittle8_t *OC, unsigned &Offset,
457cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
458cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint32_t Imm = (OC[Offset + 1] << 16)
459cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               | (OC[Offset + 2] << 8)
460cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               | (OC[Offset + 3] << 0);
461cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
462cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine()
463cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
464cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
465cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
466cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
467cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset, ++Offset, ++Offset, ++Offset;
468cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
469cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
470cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
471cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111011(const ulittle8_t *OC, unsigned &Offset,
472cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
473cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
474cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
475cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
476cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
477cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
478cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111100(const ulittle8_t *OC, unsigned &Offset,
479cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
480cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; nop.w\n", OC[Offset]);
481cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
482cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return false;
483cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
484cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
485cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111101(const ulittle8_t *OC, unsigned &Offset,
486cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
487cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; b\n", OC[Offset]);
488cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
489cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return true;
490cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
491cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
492cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111110(const ulittle8_t *OC, unsigned &Offset,
493cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
494cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << format("0x%02x                ; b.w\n", OC[Offset]);
495cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
496cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return true;
497cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
498cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
499cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::opcode_11111111(const ulittle8_t *OC, unsigned &Offset,
500cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Length, bool Prologue) {
501cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ++Offset;
502cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return true;
503cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
504cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
505cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesvoid Decoder::decodeOpcodes(ArrayRef<ulittle8_t> Opcodes, unsigned Offset,
506cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                            bool Prologue) {
507cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
508cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
509cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  bool Terminated = false;
510cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
511cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    for (unsigned DI = 0;; ++DI) {
512cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      if ((Opcodes[OI] & Ring[DI].Mask) == Ring[DI].Value) {
513cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        Terminated = (this->*Ring[DI].Routine)(Opcodes.data(), OI, 0, Prologue);
514cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        break;
515cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      }
516cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      assert(DI < array_lengthof(Ring) && "unhandled opcode");
517cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
518cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
519cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
520cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
521cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
522cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              const SectionRef &Section,
523cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              uint64_t FunctionAddress, uint64_t VA) {
524cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ArrayRef<uint8_t> Contents;
525cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
526cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return false;
527cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
528cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t SectionVA;
529cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Section.getAddress(SectionVA))
530cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return false;
531cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
532cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t Offset = VA - SectionVA;
533cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const ulittle32_t *Data =
534cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
535cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const ExceptionDataRecord XData(Data);
536cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
537cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  DictScope XRS(SW, "ExceptionData");
538cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printNumber("FunctionLength", XData.FunctionLength() << 1);
539cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printNumber("Version", XData.Vers());
540cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printBoolean("ExceptionData", XData.X());
541cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printBoolean("EpiloguePacked", XData.E());
542cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printBoolean("Fragment", XData.F());
543cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",
544cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 XData.EpilogueCount());
545cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printNumber("ByteCodeLength",
546cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 static_cast<uint64_t>(XData.CodeWords() * sizeof(uint32_t)));
547cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
548cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (XData.E()) {
549cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ArrayRef<ulittle8_t> UC = XData.UnwindByteCode();
550cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!XData.F()) {
551cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ListScope PS(SW, "Prologue");
552cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      decodeOpcodes(UC, 0, /*Prologue=*/true);
553cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
554cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (XData.EpilogueCount()) {
555cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ListScope ES(SW, "Epilogue");
556cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);
557cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
558cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  } else {
559cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes();
560cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ListScope ESS(SW, "EpilogueScopes");
561cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    for (const EpilogueScope ES : EpilogueScopes) {
562cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      DictScope ESES(SW, "EpilogueScope");
563cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      SW.printNumber("StartOffset", ES.EpilogueStartOffset());
564cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      SW.printNumber("Condition", ES.Condition());
565cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      SW.printNumber("EpilogueStartIndex", ES.EpilogueStartIndex());
566cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
567cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      ListScope Opcodes(SW, "Opcodes");
568cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      decodeOpcodes(XData.UnwindByteCode(), ES.EpilogueStartIndex(),
569cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    /*Prologue=*/false);
570cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
571cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
572cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
573cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (XData.X()) {
574cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    const uint32_t Address = XData.ExceptionHandlerRVA();
575cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    const uint32_t Parameter = XData.ExceptionHandlerParameter();
576cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    const size_t HandlerOffset = HeaderWords(XData)
577cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                               + (XData.E() ? 0 : XData.EpilogueCount())
578cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                               + XData.CodeWords();
579cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
580cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ErrorOr<SymbolRef> Symbol =
581cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      getRelocatedSymbol(COFF, Section, HandlerOffset * sizeof(uint32_t));
582cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!Symbol)
583cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true);
584cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
585cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    StringRef Name;
586cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (Symbol)
587cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Symbol->getName(Name);
588cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
589cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ListScope EHS(SW, "ExceptionHandler");
590cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.printString("Routine", formatSymbol(Name, Address));
591cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.printHex("Parameter", Parameter);
592cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
593cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
594cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return true;
595cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
596cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
597cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
598cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                const SectionRef Section, uint64_t Offset,
599cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                unsigned Index, const RuntimeFunction &RF) {
600cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
601cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines         "packed entry cannot be treated as an unpacked entry");
602cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
603cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
604cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!Function)
605cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
606cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
607cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ErrorOr<SymbolRef> XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4);
608cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!XDataRecord)
609cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    XDataRecord = getSymbol(COFF, RF.ExceptionInformationRVA());
610cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
611cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!RF.BeginAddress && !Function)
612cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return false;
613cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!RF.UnwindData && !XDataRecord)
614cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return false;
615cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
616cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  StringRef FunctionName;
617cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t FunctionAddress;
618cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Function) {
619cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Function->getName(FunctionName);
620cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Function->getAddress(FunctionAddress);
621cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  } else {
622cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    const pe32_header *PEHeader;
623cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (COFF.getPE32Header(PEHeader))
624cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return false;
625cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
626cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
627cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
628cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
629cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
630cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (XDataRecord) {
631cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    StringRef Name;
632cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    uint64_t Address;
633cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
634cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    XDataRecord->getName(Name);
635cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    XDataRecord->getAddress(Address);
636cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
637cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.printString("ExceptionRecord", formatSymbol(Name, Address));
638cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
639cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    section_iterator SI = COFF.section_end();
640cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (XDataRecord->getSection(SI))
641cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return false;
642cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
643cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return dumpXDataRecord(COFF, *SI, FunctionAddress, Address);
644cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  } else {
645cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    const pe32_header *PEHeader;
646cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (COFF.getPE32Header(PEHeader))
647cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return false;
648cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
649cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    uint64_t Address = PEHeader->ImageBase + RF.ExceptionInformationRVA();
650cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    SW.printString("ExceptionRecord", formatSymbol("", Address));
651cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
652cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    ErrorOr<SectionRef> Section =
653cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      getSectionContaining(COFF, RF.ExceptionInformationRVA());
654cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!Section)
655cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return false;
656cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
657cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return dumpXDataRecord(COFF, *Section, FunctionAddress,
658cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                           RF.ExceptionInformationRVA());
659cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
660cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
661cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
662cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
663cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              const SectionRef Section, uint64_t Offset,
664cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                              unsigned Index, const RuntimeFunction &RF) {
665cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
666cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
667cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines         "unpacked entry cannot be treated as a packed entry");
668cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
669cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
670cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (!Function)
671cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
672cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
673cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  StringRef FunctionName;
674cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t FunctionAddress;
675cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Function) {
676cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Function->getName(FunctionName);
677cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Function->getAddress(FunctionAddress);
678cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  } else {
679cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    const pe32_header *PEHeader;
680cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (COFF.getPE32Header(PEHeader))
681cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return false;
682cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
683cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
684cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
685cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
686cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printBoolean("Fragment",
687cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
688cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printNumber("FunctionLength", RF.FunctionLength());
689cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
690cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printBoolean("HomedParameters", RF.H());
691cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.startLine() << "SavedRegisters: ";
692cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                 printRegisters(SavedRegisterMask(RF));
693cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  OS << '\n';
694cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
695cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
696cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return true;
697cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
698cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
699cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,
700cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                     const SectionRef Section, unsigned Index,
701cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                     ArrayRef<uint8_t> Contents) {
702cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  uint64_t Offset = PDataEntrySize * Index;
703cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const ulittle32_t *Data =
704cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
705cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
706cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  const RuntimeFunction Entry(Data);
707cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  DictScope RFS(SW, "RuntimeFunction");
708cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)
709cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);
710cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return dumpPackedEntry(COFF, Section, Offset, Index, Entry);
711cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
712cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
713cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesvoid Decoder::dumpProcedureData(const COFFObjectFile &COFF,
714cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                const SectionRef Section) {
715cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ArrayRef<uint8_t> Contents;
716cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
717cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return;
718cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
719cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Contents.size() % PDataEntrySize) {
720cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n";
721cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return;
722cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
723cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
724cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI)
725cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (!dumpProcedureDataEntry(COFF, Section, EI, Contents))
726cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      break;
727cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
728cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
729cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstd::error_code Decoder::dumpProcedureData(const COFFObjectFile &COFF) {
730cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (const auto &Section : COFF.sections()) {
731cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    StringRef SectionName;
732cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (std::error_code EC =
733cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            COFF.getSectionName(COFF.getCOFFSection(Section), SectionName))
734cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      return EC;
735cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
736cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (SectionName.startswith(".pdata"))
737cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      dumpProcedureData(COFF, Section);
738cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
739cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return std::error_code();
740cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
741cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
742cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
743cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
744cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
745