1//===-- ARMWinEHPrinter.cpp - Windows on ARM EH Data Printer ----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// Windows on ARM uses a series of serialised data structures (RuntimeFunction)
10// to create a table of information for unwinding.  In order to conserve space,
11// there are two different ways that this data is represented.
12//
13// For functions with canonical forms for the prologue and epilogue, the data
14// can be stored in a "packed" form.  In this case, the data is packed into the
15// RuntimeFunction's remaining 30-bits and can fully describe the entire frame.
16//
17//        +---------------------------------------+
18//        |         Function Entry Address        |
19//        +---------------------------------------+
20//        |           Packed Form Data            |
21//        +---------------------------------------+
22//
23// This layout is parsed by Decoder::dumpPackedEntry.  No unwind bytecode is
24// associated with such a frame as they can be derived from the provided data.
25// The decoder does not synthesize this data as it is unnecessary for the
26// purposes of validation, with the synthesis being required only by a proper
27// unwinder.
28//
29// For functions that are large or do not match canonical forms, the data is
30// split up into two portions, with the actual data residing in the "exception
31// data" table (.xdata) with a reference to the entry from the "procedure data"
32// (.pdata) entry.
33//
34// The exception data contains information about the frame setup, all of the
35// epilogue scopes (for functions for which there are multiple exit points) and
36// the associated exception handler.  Additionally, the entry contains byte-code
37// describing how to unwind the function (c.f. Decoder::decodeOpcodes).
38//
39//        +---------------------------------------+
40//        |         Function Entry Address        |
41//        +---------------------------------------+
42//        |      Exception Data Entry Address     |
43//        +---------------------------------------+
44//
45// This layout is parsed by Decoder::dumpUnpackedEntry.  Such an entry must
46// first resolve the exception data entry address.  This structure
47// (ExceptionDataRecord) has a variable sized header
48// (c.f. ARM::WinEH::HeaderWords) and encodes most of the same information as
49// the packed form.  However, because this information is insufficient to
50// synthesize the unwinding, there are associated unwinding bytecode which make
51// up the bulk of the Decoder.
52//
53// The decoder itself is table-driven, using the first byte to determine the
54// opcode and dispatching to the associated printing routine.  The bytecode
55// itself is a variable length instruction encoding that can fully describe the
56// state of the stack and the necessary operations for unwinding to the
57// beginning of the frame.
58//
59// The byte-code maintains a 1-1 instruction mapping, indicating both the width
60// of the instruction (Thumb2 instructions are variable length, 16 or 32 bits
61// wide) allowing the program to unwind from any point in the prologue, body, or
62// epilogue of the function.
63
64#include "ARMWinEHPrinter.h"
65#include "llvm/ADT/STLExtras.h"
66#include "llvm/ADT/StringExtras.h"
67#include "llvm/Support/ARMWinEH.h"
68#include "llvm/Support/Format.h"
69
70using namespace llvm;
71using namespace llvm::object;
72using namespace llvm::support;
73
74namespace llvm {
75raw_ostream &operator<<(raw_ostream &OS, const ARM::WinEH::ReturnType &RT) {
76  switch (RT) {
77  case ARM::WinEH::ReturnType::RT_POP:
78    OS << "pop {pc}";
79    break;
80  case ARM::WinEH::ReturnType::RT_B:
81    OS << "b target";
82    break;
83  case ARM::WinEH::ReturnType::RT_BW:
84    OS << "b.w target";
85    break;
86  case ARM::WinEH::ReturnType::RT_NoEpilogue:
87    OS << "(no epilogue)";
88    break;
89  }
90  return OS;
91}
92}
93
94static std::string formatSymbol(StringRef Name, uint64_t Address,
95                                uint64_t Offset = 0) {
96  std::string Buffer;
97  raw_string_ostream OS(Buffer);
98
99  if (!Name.empty())
100    OS << Name << " ";
101
102  if (Offset)
103    OS << format("+0x%" PRIX64 " (0x%" PRIX64 ")", Offset, Address);
104  else if (!Name.empty())
105    OS << format("(0x%" PRIX64 ")", Address);
106  else
107    OS << format("0x%" PRIX64, Address);
108
109  return OS.str();
110}
111
112namespace llvm {
113namespace ARM {
114namespace WinEH {
115const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);
116
117// TODO name the uops more appropriately
118const Decoder::RingEntry Decoder::Ring[] = {
119  { 0x80, 0x00, 1, &Decoder::opcode_0xxxxxxx },  // UOP_STACK_FREE (16-bit)
120  { 0xc0, 0x80, 2, &Decoder::opcode_10Lxxxxx },  // UOP_POP (32-bit)
121  { 0xf0, 0xc0, 1, &Decoder::opcode_1100xxxx },  // UOP_STACK_SAVE (16-bit)
122  { 0xf8, 0xd0, 1, &Decoder::opcode_11010Lxx },  // UOP_POP (16-bit)
123  { 0xf8, 0xd8, 1, &Decoder::opcode_11011Lxx },  // UOP_POP (32-bit)
124  { 0xf8, 0xe0, 1, &Decoder::opcode_11100xxx },  // UOP_VPOP (32-bit)
125  { 0xfc, 0xe8, 2, &Decoder::opcode_111010xx },  // UOP_STACK_FREE (32-bit)
126  { 0xfe, 0xec, 2, &Decoder::opcode_1110110L },  // UOP_POP (16-bit)
127  { 0xff, 0xee, 2, &Decoder::opcode_11101110 },  // UOP_MICROSOFT_SPECIFIC (16-bit)
128                                              // UOP_PUSH_MACHINE_FRAME
129                                              // UOP_PUSH_CONTEXT
130                                              // UOP_PUSH_TRAP_FRAME
131                                              // UOP_REDZONE_RESTORE_LR
132  { 0xff, 0xef, 2, &Decoder::opcode_11101111 },  // UOP_LDRPC_POSTINC (32-bit)
133  { 0xff, 0xf5, 2, &Decoder::opcode_11110101 },  // UOP_VPOP (32-bit)
134  { 0xff, 0xf6, 2, &Decoder::opcode_11110110 },  // UOP_VPOP (32-bit)
135  { 0xff, 0xf7, 3, &Decoder::opcode_11110111 },  // UOP_STACK_RESTORE (16-bit)
136  { 0xff, 0xf8, 4, &Decoder::opcode_11111000 },  // UOP_STACK_RESTORE (16-bit)
137  { 0xff, 0xf9, 3, &Decoder::opcode_11111001 },  // UOP_STACK_RESTORE (32-bit)
138  { 0xff, 0xfa, 4, &Decoder::opcode_11111010 },  // UOP_STACK_RESTORE (32-bit)
139  { 0xff, 0xfb, 1, &Decoder::opcode_11111011 },  // UOP_NOP (16-bit)
140  { 0xff, 0xfc, 1, &Decoder::opcode_11111100 },  // UOP_NOP (32-bit)
141  { 0xff, 0xfd, 1, &Decoder::opcode_11111101 },  // UOP_NOP (16-bit) / END
142  { 0xff, 0xfe, 1, &Decoder::opcode_11111110 },  // UOP_NOP (32-bit) / END
143  { 0xff, 0xff, 1, &Decoder::opcode_11111111 },  // UOP_END
144};
145
146
147// Unwind opcodes for ARM64.
148// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
149const Decoder::RingEntry Decoder::Ring64[] = {
150  { 0xe0, 0x00, 1, &Decoder::opcode_alloc_s },
151  { 0xe0, 0x20, 1, &Decoder::opcode_save_r19r20_x },
152  { 0xc0, 0x40, 1, &Decoder::opcode_save_fplr },
153  { 0xc0, 0x80, 1, &Decoder::opcode_save_fplr_x },
154  { 0xf8, 0xc0, 2, &Decoder::opcode_alloc_m },
155  { 0xfc, 0xc8, 2, &Decoder::opcode_save_regp },
156  { 0xfc, 0xcc, 2, &Decoder::opcode_save_regp_x },
157  { 0xfc, 0xd0, 2, &Decoder::opcode_save_reg },
158  { 0xfe, 0xd4, 2, &Decoder::opcode_save_reg_x },
159  { 0xfe, 0xd6, 2, &Decoder::opcode_save_lrpair },
160  { 0xfe, 0xd8, 2, &Decoder::opcode_save_fregp },
161  { 0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x },
162  { 0xfe, 0xdc, 2, &Decoder::opcode_save_freg },
163  { 0xff, 0xde, 2, &Decoder::opcode_save_freg_x },
164  { 0xff, 0xe0, 4, &Decoder::opcode_alloc_l },
165  { 0xff, 0xe1, 1, &Decoder::opcode_setfp },
166  { 0xff, 0xe2, 2, &Decoder::opcode_addfp },
167  { 0xff, 0xe3, 1, &Decoder::opcode_nop },
168  { 0xff, 0xe4, 1, &Decoder::opcode_end },
169  { 0xff, 0xe5, 1, &Decoder::opcode_end_c },
170  { 0xff, 0xe6, 1, &Decoder::opcode_save_next },
171  { 0xff, 0xe8, 1, &Decoder::opcode_trap_frame },
172  { 0xff, 0xe9, 1, &Decoder::opcode_machine_frame },
173  { 0xff, 0xea, 1, &Decoder::opcode_context },
174  { 0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call },
175};
176
177void Decoder::printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask) {
178  static const char * const GPRRegisterNames[16] = {
179    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
180    "r11", "ip", "sp", "lr", "pc",
181  };
182
183  const uint16_t GPRMask = std::get<0>(RegisterMask);
184  const uint16_t VFPMask = std::get<1>(RegisterMask);
185
186  OS << '{';
187  ListSeparator LS;
188  for (unsigned RI = 0, RE = 11; RI < RE; ++RI)
189    if (GPRMask & (1 << RI))
190      OS << LS << GPRRegisterNames[RI];
191  for (unsigned RI = 0, RE = 32; RI < RE; ++RI)
192    if (VFPMask & (1 << RI))
193      OS << LS << "d" << unsigned(RI);
194  for (unsigned RI = 11, RE = 16; RI < RE; ++RI)
195    if (GPRMask & (1 << RI))
196      OS << LS << GPRRegisterNames[RI];
197  OS << '}';
198}
199
200ErrorOr<object::SectionRef>
201Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {
202  for (const auto &Section : COFF.sections()) {
203    uint64_t Address = Section.getAddress();
204    uint64_t Size = Section.getSize();
205
206    if (VA >= Address && (VA - Address) <= Size)
207      return Section;
208  }
209  return inconvertibleErrorCode();
210}
211
212ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF,
213                                              uint64_t VA, bool FunctionOnly) {
214  for (const auto &Symbol : COFF.symbols()) {
215    Expected<SymbolRef::Type> Type = Symbol.getType();
216    if (!Type)
217      return errorToErrorCode(Type.takeError());
218    if (FunctionOnly && *Type != SymbolRef::ST_Function)
219      continue;
220
221    Expected<uint64_t> Address = Symbol.getAddress();
222    if (!Address)
223      return errorToErrorCode(Address.takeError());
224    if (*Address == VA)
225      return Symbol;
226  }
227  return inconvertibleErrorCode();
228}
229
230ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,
231                                               const SectionRef &Section,
232                                               uint64_t Offset) {
233  for (const auto &Relocation : Section.relocations()) {
234    uint64_t RelocationOffset = Relocation.getOffset();
235    if (RelocationOffset == Offset)
236      return *Relocation.getSymbol();
237  }
238  return inconvertibleErrorCode();
239}
240
241SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF,
242                                      SymbolRef Sym) {
243  // The symbol resolved by getRelocatedSymbol can be any internal
244  // nondescriptive symbol; try to resolve a more descriptive one.
245  COFFSymbolRef CoffSym = COFF.getCOFFSymbol(Sym);
246  if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL)
247    return Sym;
248  for (const auto &S : COFF.symbols()) {
249    COFFSymbolRef CS = COFF.getCOFFSymbol(S);
250    if (CS.getSectionNumber() == CoffSym.getSectionNumber() &&
251        CS.getValue() == CoffSym.getValue()) {
252      if (CS.isExternal())
253        return S;
254      if (CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL) {
255        Sym = S;
256        CoffSym = CS;
257      }
258    }
259  }
260  return Sym;
261}
262
263ErrorOr<SymbolRef> Decoder::getSymbolForLocation(
264    const COFFObjectFile &COFF, const SectionRef &Section,
265    uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress,
266    uint64_t &SymbolOffset, bool FunctionOnly) {
267  // Try to locate a relocation that points at the offset in the section
268  ErrorOr<SymbolRef> SymOrErr =
269      getRelocatedSymbol(COFF, Section, OffsetInSection);
270  if (SymOrErr) {
271    // We found a relocation symbol; the immediate offset needs to be added
272    // to the symbol address.
273    SymbolOffset = ImmediateOffset;
274
275    Expected<uint64_t> AddressOrErr = SymOrErr->getAddress();
276    if (!AddressOrErr) {
277      std::string Buf;
278      llvm::raw_string_ostream OS(Buf);
279      logAllUnhandledErrors(AddressOrErr.takeError(), OS);
280      OS.flush();
281      report_fatal_error(Buf);
282    }
283    // We apply SymbolOffset here directly. We return it separately to allow
284    // the caller to print it as an offset on the symbol name.
285    SymbolAddress = *AddressOrErr + SymbolOffset;
286  } else {
287    // No matching relocation found; operating on a linked image. Try to
288    // find a descriptive symbol if possible. The immediate offset contains
289    // the image relative address, and we shouldn't add any offset to the
290    // symbol.
291    SymbolAddress = COFF.getImageBase() + ImmediateOffset;
292    SymbolOffset = 0;
293    SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly);
294  }
295  if (SymOrErr && FunctionOnly) // Resolve label symbols into function names
296    SymOrErr = getPreferredSymbol(COFF, *SymOrErr);
297  return SymOrErr;
298}
299
300bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset,
301                              unsigned Length, bool Prologue) {
302  uint8_t Imm = OC[Offset] & 0x7f;
303  SW.startLine() << format("0x%02x                ; %s sp, #(%u * 4)\n",
304                           OC[Offset],
305                           static_cast<const char *>(Prologue ? "sub" : "add"),
306                           Imm);
307  ++Offset;
308  return false;
309}
310
311bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset,
312                              unsigned Length, bool Prologue) {
313  unsigned Link = (OC[Offset] & 0x20) >> 5;
314  uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))
315                        | ((OC[Offset + 0] & 0x1f) << 8)
316                        | ((OC[Offset + 1] & 0xff) << 0);
317  assert((~RegisterMask & (1 << 13)) && "sp must not be set");
318  assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");
319
320  SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",
321                           OC[Offset + 0], OC[Offset + 1],
322                           Prologue ? "push" : "pop");
323  printRegisters(std::make_pair(RegisterMask, 0));
324  OS << '\n';
325
326  Offset += 2;
327  return false;
328}
329
330bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset,
331                              unsigned Length, bool Prologue) {
332  if (Prologue)
333    SW.startLine() << format("0x%02x                ; mov r%u, sp\n",
334                             OC[Offset], OC[Offset] & 0xf);
335  else
336    SW.startLine() << format("0x%02x                ; mov sp, r%u\n",
337                             OC[Offset], OC[Offset] & 0xf);
338  ++Offset;
339  return false;
340}
341
342bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset,
343                              unsigned Length, bool Prologue) {
344  unsigned Link = (OC[Offset] & 0x4) >> 3;
345  unsigned Count = (OC[Offset] & 0x3);
346
347  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
348                   | (((1 << (Count + 1)) - 1) << 4);
349
350  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
351                           Prologue ? "push" : "pop");
352  printRegisters(std::make_pair(GPRMask, 0));
353  OS << '\n';
354
355  ++Offset;
356  return false;
357}
358
359bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset,
360                              unsigned Length, bool Prologue) {
361  unsigned Link = (OC[Offset] & 0x4) >> 2;
362  unsigned Count = (OC[Offset] & 0x3) + 4;
363
364  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
365                   | (((1 << (Count + 1)) - 1) << 4);
366
367  SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],
368                           Prologue ? "push" : "pop");
369  printRegisters(std::make_pair(GPRMask, 0));
370  OS << '\n';
371
372  ++Offset;
373  return false;
374}
375
376bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset,
377                              unsigned Length, bool Prologue) {
378  unsigned High = (OC[Offset] & 0x7);
379  uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);
380
381  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
382                           Prologue ? "vpush" : "vpop");
383  printRegisters(std::make_pair(0, VFPMask));
384  OS << '\n';
385
386  ++Offset;
387  return false;
388}
389
390bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset,
391                              unsigned Length, bool Prologue) {
392  uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);
393
394  SW.startLine() << format("0x%02x 0x%02x           ; %s.w sp, #(%u * 4)\n",
395                           OC[Offset + 0], OC[Offset + 1],
396                           static_cast<const char *>(Prologue ? "sub" : "add"),
397                           Imm);
398
399  Offset += 2;
400  return false;
401}
402
403bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset,
404                              unsigned Length, bool Prologue) {
405  uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))
406                  | ((OC[Offset + 1] & 0xff) << 0);
407
408  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
409                           OC[Offset + 1], Prologue ? "push" : "pop");
410  printRegisters(std::make_pair(GPRMask, 0));
411  OS << '\n';
412
413  Offset += 2;
414  return false;
415}
416
417bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset,
418                              unsigned Length, bool Prologue) {
419  assert(!Prologue && "may not be used in prologue");
420
421  if (OC[Offset + 1] & 0xf0)
422    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
423                             OC[Offset + 0], OC[Offset +  1]);
424  else
425    SW.startLine()
426      << format("0x%02x 0x%02x           ; microsoft-specific (type: %u)\n",
427                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);
428
429  Offset += 2;
430  return false;
431}
432
433bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset,
434                              unsigned Length, bool Prologue) {
435  assert(!Prologue && "may not be used in prologue");
436
437  if (OC[Offset + 1] & 0xf0)
438    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
439                             OC[Offset + 0], OC[Offset +  1]);
440  else
441    SW.startLine()
442      << format("0x%02x 0x%02x           ; ldr.w lr, [sp], #%u\n",
443                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
444
445  Offset += 2;
446  return false;
447}
448
449bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset,
450                              unsigned Length, bool Prologue) {
451  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
452  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
453  uint32_t VFPMask = ((1 << (End - Start)) - 1) << Start;
454
455  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
456                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
457  printRegisters(std::make_pair(0, VFPMask));
458  OS << '\n';
459
460  Offset += 2;
461  return false;
462}
463
464bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset,
465                              unsigned Length, bool Prologue) {
466  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
467  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
468  uint32_t VFPMask = ((1 << (End - Start)) - 1) << 16;
469
470  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
471                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
472  printRegisters(std::make_pair(0, VFPMask));
473  OS << '\n';
474
475  Offset += 2;
476  return false;
477}
478
479bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset,
480                              unsigned Length, bool Prologue) {
481  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
482
483  SW.startLine() << format("0x%02x 0x%02x 0x%02x      ; %s sp, sp, #(%u * 4)\n",
484                           OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
485                           static_cast<const char *>(Prologue ? "sub" : "add"),
486                           Imm);
487
488  Offset += 3;
489  return false;
490}
491
492bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset,
493                              unsigned Length, bool Prologue) {
494  uint32_t Imm = (OC[Offset + 1] << 16)
495               | (OC[Offset + 2] << 8)
496               | (OC[Offset + 3] << 0);
497
498  SW.startLine()
499    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
500              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
501              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
502
503  Offset += 4;
504  return false;
505}
506
507bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset,
508                              unsigned Length, bool Prologue) {
509  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
510
511  SW.startLine()
512    << format("0x%02x 0x%02x 0x%02x      ; %s.w sp, sp, #(%u * 4)\n",
513              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
514              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
515
516  Offset += 3;
517  return false;
518}
519
520bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset,
521                              unsigned Length, bool Prologue) {
522  uint32_t Imm = (OC[Offset + 1] << 16)
523               | (OC[Offset + 2] << 8)
524               | (OC[Offset + 3] << 0);
525
526  SW.startLine()
527    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
528              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
529              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
530
531  Offset += 4;
532  return false;
533}
534
535bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset,
536                              unsigned Length, bool Prologue) {
537  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
538  ++Offset;
539  return false;
540}
541
542bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset,
543                              unsigned Length, bool Prologue) {
544  SW.startLine() << format("0x%02x                ; nop.w\n", OC[Offset]);
545  ++Offset;
546  return false;
547}
548
549bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset,
550                              unsigned Length, bool Prologue) {
551  SW.startLine() << format("0x%02x                ; b\n", OC[Offset]);
552  ++Offset;
553  return true;
554}
555
556bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset,
557                              unsigned Length, bool Prologue) {
558  SW.startLine() << format("0x%02x                ; b.w\n", OC[Offset]);
559  ++Offset;
560  return true;
561}
562
563bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset,
564                              unsigned Length, bool Prologue) {
565  ++Offset;
566  return true;
567}
568
569// ARM64 unwind codes start here.
570bool Decoder::opcode_alloc_s(const uint8_t *OC, unsigned &Offset,
571                             unsigned Length, bool Prologue) {
572  uint32_t NumBytes = (OC[Offset] & 0x1F) << 4;
573  SW.startLine() << format("0x%02x                ; %s sp, #%u\n", OC[Offset],
574                           static_cast<const char *>(Prologue ? "sub" : "add"),
575                           NumBytes);
576  ++Offset;
577  return false;
578}
579
580bool Decoder::opcode_save_r19r20_x(const uint8_t *OC, unsigned &Offset,
581                                   unsigned Length, bool Prologue) {
582  uint32_t Off = (OC[Offset] & 0x1F) << 3;
583  if (Prologue)
584    SW.startLine() << format(
585        "0x%02x                ; stp x19, x20, [sp, #-%u]!\n", OC[Offset], Off);
586  else
587    SW.startLine() << format(
588        "0x%02x                ; ldp x19, x20, [sp], #%u\n", OC[Offset], Off);
589  ++Offset;
590  return false;
591}
592
593bool Decoder::opcode_save_fplr(const uint8_t *OC, unsigned &Offset,
594                               unsigned Length, bool Prologue) {
595  uint32_t Off = (OC[Offset] & 0x3F) << 3;
596  SW.startLine() << format(
597      "0x%02x                ; %s x29, x30, [sp, #%u]\n", OC[Offset],
598      static_cast<const char *>(Prologue ? "stp" : "ldp"), Off);
599  ++Offset;
600  return false;
601}
602
603bool Decoder::opcode_save_fplr_x(const uint8_t *OC, unsigned &Offset,
604                                 unsigned Length, bool Prologue) {
605  uint32_t Off = ((OC[Offset] & 0x3F) + 1) << 3;
606  if (Prologue)
607    SW.startLine() << format(
608        "0x%02x                ; stp x29, x30, [sp, #-%u]!\n", OC[Offset], Off);
609  else
610    SW.startLine() << format(
611        "0x%02x                ; ldp x29, x30, [sp], #%u\n", OC[Offset], Off);
612  ++Offset;
613  return false;
614}
615
616bool Decoder::opcode_alloc_m(const uint8_t *OC, unsigned &Offset,
617                             unsigned Length, bool Prologue) {
618  uint32_t NumBytes = ((OC[Offset] & 0x07) << 8);
619  NumBytes |= (OC[Offset + 1] & 0xFF);
620  NumBytes <<= 4;
621  SW.startLine() << format("0x%02x%02x              ; %s sp, #%u\n",
622                           OC[Offset], OC[Offset + 1],
623                           static_cast<const char *>(Prologue ? "sub" : "add"),
624                           NumBytes);
625  Offset += 2;
626  return false;
627}
628
629bool Decoder::opcode_save_regp(const uint8_t *OC, unsigned &Offset,
630                               unsigned Length, bool Prologue) {
631  uint32_t Reg = ((OC[Offset] & 0x03) << 8);
632  Reg |= (OC[Offset + 1] & 0xC0);
633  Reg >>= 6;
634  Reg += 19;
635  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
636  SW.startLine() << format(
637      "0x%02x%02x              ; %s x%u, x%u, [sp, #%u]\n",
638      OC[Offset], OC[Offset + 1],
639      static_cast<const char *>(Prologue ? "stp" : "ldp"), Reg, Reg + 1, Off);
640  Offset += 2;
641  return false;
642}
643
644bool Decoder::opcode_save_regp_x(const uint8_t *OC, unsigned &Offset,
645                                 unsigned Length, bool Prologue) {
646  uint32_t Reg = ((OC[Offset] & 0x03) << 8);
647  Reg |= (OC[Offset + 1] & 0xC0);
648  Reg >>= 6;
649  Reg += 19;
650  uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;
651  if (Prologue)
652    SW.startLine() << format(
653        "0x%02x%02x              ; stp x%u, x%u, [sp, #-%u]!\n",
654        OC[Offset], OC[Offset + 1], Reg,
655        Reg + 1, Off);
656  else
657    SW.startLine() << format(
658        "0x%02x%02x              ; ldp x%u, x%u, [sp], #%u\n",
659        OC[Offset], OC[Offset + 1], Reg,
660        Reg + 1, Off);
661  Offset += 2;
662  return false;
663}
664
665bool Decoder::opcode_save_reg(const uint8_t *OC, unsigned &Offset,
666                              unsigned Length, bool Prologue) {
667  uint32_t Reg = (OC[Offset] & 0x03) << 8;
668  Reg |= (OC[Offset + 1] & 0xC0);
669  Reg >>= 6;
670  Reg += 19;
671  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
672  SW.startLine() << format("0x%02x%02x              ; %s x%u, [sp, #%u]\n",
673                           OC[Offset], OC[Offset + 1],
674                           static_cast<const char *>(Prologue ? "str" : "ldr"),
675                           Reg, Off);
676  Offset += 2;
677  return false;
678}
679
680bool Decoder::opcode_save_reg_x(const uint8_t *OC, unsigned &Offset,
681                                unsigned Length, bool Prologue) {
682  uint32_t Reg = (OC[Offset] & 0x01) << 8;
683  Reg |= (OC[Offset + 1] & 0xE0);
684  Reg >>= 5;
685  Reg += 19;
686  uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;
687  if (Prologue)
688    SW.startLine() << format("0x%02x%02x              ; str x%u, [sp, #-%u]!\n",
689                             OC[Offset], OC[Offset + 1], Reg, Off);
690  else
691    SW.startLine() << format("0x%02x%02x              ; ldr x%u, [sp], #%u\n",
692                             OC[Offset], OC[Offset + 1], Reg, Off);
693  Offset += 2;
694  return false;
695}
696
697bool Decoder::opcode_save_lrpair(const uint8_t *OC, unsigned &Offset,
698                                 unsigned Length, bool Prologue) {
699  uint32_t Reg = (OC[Offset] & 0x01) << 8;
700  Reg |= (OC[Offset + 1] & 0xC0);
701  Reg >>= 6;
702  Reg *= 2;
703  Reg += 19;
704  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
705  SW.startLine() << format("0x%02x%02x              ; %s x%u, lr, [sp, #%u]\n",
706                           OC[Offset], OC[Offset + 1],
707                           static_cast<const char *>(Prologue ? "stp" : "ldp"),
708                           Reg, Off);
709  Offset += 2;
710  return false;
711}
712
713bool Decoder::opcode_save_fregp(const uint8_t *OC, unsigned &Offset,
714                                unsigned Length, bool Prologue) {
715  uint32_t Reg = (OC[Offset] & 0x01) << 8;
716  Reg |= (OC[Offset + 1] & 0xC0);
717  Reg >>= 6;
718  Reg += 8;
719  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
720  SW.startLine() << format("0x%02x%02x              ; %s d%u, d%u, [sp, #%u]\n",
721                           OC[Offset], OC[Offset + 1],
722                           static_cast<const char *>(Prologue ? "stp" : "ldp"),
723                           Reg, Reg + 1, Off);
724  Offset += 2;
725  return false;
726}
727
728bool Decoder::opcode_save_fregp_x(const uint8_t *OC, unsigned &Offset,
729                                  unsigned Length, bool Prologue) {
730  uint32_t Reg = (OC[Offset] & 0x01) << 8;
731  Reg |= (OC[Offset + 1] & 0xC0);
732  Reg >>= 6;
733  Reg += 8;
734  uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;
735  if (Prologue)
736    SW.startLine() << format(
737        "0x%02x%02x              ; stp d%u, d%u, [sp, #-%u]!\n", OC[Offset],
738        OC[Offset + 1], Reg, Reg + 1, Off);
739  else
740    SW.startLine() << format(
741        "0x%02x%02x              ; ldp d%u, d%u, [sp], #%u\n", OC[Offset],
742        OC[Offset + 1], Reg, Reg + 1, Off);
743  Offset += 2;
744  return false;
745}
746
747bool Decoder::opcode_save_freg(const uint8_t *OC, unsigned &Offset,
748                               unsigned Length, bool Prologue) {
749  uint32_t Reg = (OC[Offset] & 0x01) << 8;
750  Reg |= (OC[Offset + 1] & 0xC0);
751  Reg >>= 6;
752  Reg += 8;
753  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
754  SW.startLine() << format("0x%02x%02x              ; %s d%u, [sp, #%u]\n",
755                           OC[Offset], OC[Offset + 1],
756                           static_cast<const char *>(Prologue ? "str" : "ldr"),
757                           Reg, Off);
758  Offset += 2;
759  return false;
760}
761
762bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset,
763                                 unsigned Length, bool Prologue) {
764  uint32_t Reg = ((OC[Offset + 1] & 0xE0) >> 5) + 8;
765  uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;
766  if (Prologue)
767    SW.startLine() << format(
768        "0x%02x%02x              ; str d%u, [sp, #-%u]!\n", OC[Offset],
769        OC[Offset + 1], Reg, Off);
770  else
771    SW.startLine() << format(
772        "0x%02x%02x              ; ldr d%u, [sp], #%u\n", OC[Offset],
773        OC[Offset + 1], Reg, Off);
774  Offset += 2;
775  return false;
776}
777
778bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset,
779                             unsigned Length, bool Prologue) {
780  unsigned Off =
781      (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) | (OC[Offset + 3] << 0);
782  Off <<= 4;
783  SW.startLine() << format(
784      "0x%02x%02x%02x%02x          ; %s sp, #%u\n", OC[Offset], OC[Offset + 1],
785      OC[Offset + 2], OC[Offset + 3],
786      static_cast<const char *>(Prologue ? "sub" : "add"), Off);
787  Offset += 4;
788  return false;
789}
790
791bool Decoder::opcode_setfp(const uint8_t *OC, unsigned &Offset, unsigned Length,
792                           bool Prologue) {
793  SW.startLine() << format("0x%02x                ; mov %s, %s\n", OC[Offset],
794                           static_cast<const char *>(Prologue ? "fp" : "sp"),
795                           static_cast<const char *>(Prologue ? "sp" : "fp"));
796  ++Offset;
797  return false;
798}
799
800bool Decoder::opcode_addfp(const uint8_t *OC, unsigned &Offset, unsigned Length,
801                           bool Prologue) {
802  unsigned NumBytes = OC[Offset + 1] << 3;
803  SW.startLine() << format(
804      "0x%02x%02x              ; %s %s, %s, #%u\n", OC[Offset], OC[Offset + 1],
805      static_cast<const char *>(Prologue ? "add" : "sub"),
806      static_cast<const char *>(Prologue ? "fp" : "sp"),
807      static_cast<const char *>(Prologue ? "sp" : "fp"), NumBytes);
808  Offset += 2;
809  return false;
810}
811
812bool Decoder::opcode_nop(const uint8_t *OC, unsigned &Offset, unsigned Length,
813                         bool Prologue) {
814  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
815  ++Offset;
816  return false;
817}
818
819bool Decoder::opcode_end(const uint8_t *OC, unsigned &Offset, unsigned Length,
820                         bool Prologue) {
821  SW.startLine() << format("0x%02x                ; end\n", OC[Offset]);
822  ++Offset;
823  return true;
824}
825
826bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length,
827                           bool Prologue) {
828  SW.startLine() << format("0x%02x                ; end_c\n", OC[Offset]);
829  ++Offset;
830  return true;
831}
832
833bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,
834                               unsigned Length, bool Prologue) {
835  if (Prologue)
836    SW.startLine() << format("0x%02x                ; save next\n", OC[Offset]);
837  else
838    SW.startLine() << format("0x%02x                ; restore next\n",
839                             OC[Offset]);
840  ++Offset;
841  return false;
842}
843
844bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset,
845                                unsigned Length, bool Prologue) {
846  SW.startLine() << format("0x%02x                ; trap frame\n", OC[Offset]);
847  ++Offset;
848  return false;
849}
850
851bool Decoder::opcode_machine_frame(const uint8_t *OC, unsigned &Offset,
852                                   unsigned Length, bool Prologue) {
853  SW.startLine() << format("0x%02x                ; machine frame\n",
854                           OC[Offset]);
855  ++Offset;
856  return false;
857}
858
859bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset,
860                             unsigned Length, bool Prologue) {
861  SW.startLine() << format("0x%02x                ; context\n", OC[Offset]);
862  ++Offset;
863  return false;
864}
865
866bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset,
867                                           unsigned Length, bool Prologue) {
868  SW.startLine() << format("0x%02x                ; clear unwound to call\n",
869                           OC[Offset]);
870  ++Offset;
871  return false;
872}
873
874void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
875                            bool Prologue) {
876  assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
877  const RingEntry* DecodeRing = isAArch64 ? Ring64 : Ring;
878  bool Terminated = false;
879  for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
880    for (unsigned DI = 0;; ++DI) {
881      if ((isAArch64 && (DI >= array_lengthof(Ring64))) ||
882          (!isAArch64 && (DI >= array_lengthof(Ring)))) {
883        SW.startLine() << format("0x%02x                ; Bad opcode!\n",
884                                 Opcodes.data()[OI]);
885        ++OI;
886        break;
887      }
888
889      if ((Opcodes[OI] & DecodeRing[DI].Mask) == DecodeRing[DI].Value) {
890        if (OI + DecodeRing[DI].Length > OE) {
891          SW.startLine() << format("Opcode 0x%02x goes past the unwind data\n",
892                                    Opcodes[OI]);
893          OI += DecodeRing[DI].Length;
894          break;
895        }
896        Terminated =
897            (this->*DecodeRing[DI].Routine)(Opcodes.data(), OI, 0, Prologue);
898        break;
899      }
900    }
901  }
902}
903
904bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
905                              const SectionRef &Section,
906                              uint64_t FunctionAddress, uint64_t VA) {
907  ArrayRef<uint8_t> Contents;
908  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
909    return false;
910
911  uint64_t SectionVA = Section.getAddress();
912  uint64_t Offset = VA - SectionVA;
913  const ulittle32_t *Data =
914    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
915
916  // Sanity check to ensure that the .xdata header is present.
917  // A header is one or two words, followed by at least one word to describe
918  // the unwind codes. Applicable to both ARM and AArch64.
919  if (Contents.size() - Offset < 8)
920    report_fatal_error(".xdata must be at least 8 bytes in size");
921
922  const ExceptionDataRecord XData(Data, isAArch64);
923  DictScope XRS(SW, "ExceptionData");
924  SW.printNumber("FunctionLength",
925                 isAArch64 ? XData.FunctionLengthInBytesAArch64() :
926                 XData.FunctionLengthInBytesARM());
927  SW.printNumber("Version", XData.Vers());
928  SW.printBoolean("ExceptionData", XData.X());
929  SW.printBoolean("EpiloguePacked", XData.E());
930  if (!isAArch64)
931    SW.printBoolean("Fragment", XData.F());
932  SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",
933                 XData.EpilogueCount());
934  uint64_t ByteCodeLength = XData.CodeWords() * sizeof(uint32_t);
935  SW.printNumber("ByteCodeLength", ByteCodeLength);
936
937  if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) -
938                (XData.E() ? 0 : XData.EpilogueCount() * 4) -
939                (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) {
940    SW.flush();
941    report_fatal_error("Malformed unwind data");
942  }
943
944  if (XData.E()) {
945    ArrayRef<uint8_t> UC = XData.UnwindByteCode();
946    if (isAArch64 || !XData.F()) {
947      ListScope PS(SW, "Prologue");
948      decodeOpcodes(UC, 0, /*Prologue=*/true);
949    }
950    if (XData.EpilogueCount()) {
951      ListScope ES(SW, "Epilogue");
952      decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);
953    }
954  } else {
955    {
956      ListScope PS(SW, "Prologue");
957      decodeOpcodes(XData.UnwindByteCode(), 0, /*Prologue=*/true);
958    }
959    ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes();
960    ListScope ESS(SW, "EpilogueScopes");
961    for (const EpilogueScope ES : EpilogueScopes) {
962      DictScope ESES(SW, "EpilogueScope");
963      SW.printNumber("StartOffset", ES.EpilogueStartOffset());
964      if (!isAArch64)
965        SW.printNumber("Condition", ES.Condition());
966      SW.printNumber("EpilogueStartIndex",
967                     isAArch64 ? ES.EpilogueStartIndexAArch64()
968                               : ES.EpilogueStartIndexARM());
969      if (ES.ES & ~0xffc3ffff)
970        SW.printNumber("ReservedBits", (ES.ES >> 18) & 0xF);
971
972      ListScope Opcodes(SW, "Opcodes");
973      decodeOpcodes(XData.UnwindByteCode(),
974                    isAArch64 ? ES.EpilogueStartIndexAArch64()
975                              : ES.EpilogueStartIndexARM(),
976                    /*Prologue=*/false);
977    }
978  }
979
980  if (XData.X()) {
981    const uint32_t Parameter = XData.ExceptionHandlerParameter();
982    const size_t HandlerOffset = HeaderWords(XData) +
983                                 (XData.E() ? 0 : XData.EpilogueCount()) +
984                                 XData.CodeWords();
985
986    uint64_t Address, SymbolOffset;
987    ErrorOr<SymbolRef> Symbol = getSymbolForLocation(
988        COFF, Section, Offset + HandlerOffset * sizeof(uint32_t),
989        XData.ExceptionHandlerRVA(), Address, SymbolOffset,
990        /*FunctionOnly=*/true);
991    if (!Symbol) {
992      ListScope EHS(SW, "ExceptionHandler");
993      SW.printHex("Routine", Address);
994      SW.printHex("Parameter", Parameter);
995      return true;
996    }
997
998    Expected<StringRef> Name = Symbol->getName();
999    if (!Name) {
1000      std::string Buf;
1001      llvm::raw_string_ostream OS(Buf);
1002      logAllUnhandledErrors(Name.takeError(), OS);
1003      OS.flush();
1004      report_fatal_error(Buf);
1005    }
1006
1007    ListScope EHS(SW, "ExceptionHandler");
1008    SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset));
1009    SW.printHex("Parameter", Parameter);
1010  }
1011
1012  return true;
1013}
1014
1015bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
1016                                const SectionRef Section, uint64_t Offset,
1017                                unsigned Index, const RuntimeFunction &RF) {
1018  assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
1019         "packed entry cannot be treated as an unpacked entry");
1020
1021  uint64_t FunctionAddress, FunctionOffset;
1022  ErrorOr<SymbolRef> Function = getSymbolForLocation(
1023      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1024      /*FunctionOnly=*/true);
1025
1026  uint64_t XDataAddress, XDataOffset;
1027  ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation(
1028      COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress,
1029      XDataOffset);
1030
1031  if (!RF.BeginAddress && !Function)
1032    return false;
1033  if (!RF.UnwindData && !XDataRecord)
1034    return false;
1035
1036  StringRef FunctionName;
1037  if (Function) {
1038    Expected<StringRef> FunctionNameOrErr = Function->getName();
1039    if (!FunctionNameOrErr) {
1040      std::string Buf;
1041      llvm::raw_string_ostream OS(Buf);
1042      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1043      OS.flush();
1044      report_fatal_error(Buf);
1045    }
1046    FunctionName = *FunctionNameOrErr;
1047  }
1048
1049  SW.printString("Function",
1050                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1051
1052  if (XDataRecord) {
1053    Expected<StringRef> Name = XDataRecord->getName();
1054    if (!Name) {
1055      std::string Buf;
1056      llvm::raw_string_ostream OS(Buf);
1057      logAllUnhandledErrors(Name.takeError(), OS);
1058      OS.flush();
1059      report_fatal_error(Buf);
1060    }
1061
1062    SW.printString("ExceptionRecord",
1063                   formatSymbol(*Name, XDataAddress, XDataOffset));
1064
1065    Expected<section_iterator> SIOrErr = XDataRecord->getSection();
1066    if (!SIOrErr) {
1067      // TODO: Actually report errors helpfully.
1068      consumeError(SIOrErr.takeError());
1069      return false;
1070    }
1071    section_iterator SI = *SIOrErr;
1072
1073    return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress);
1074  } else {
1075    SW.printString("ExceptionRecord", formatSymbol("", XDataAddress));
1076
1077    ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress);
1078    if (!Section)
1079      return false;
1080
1081    return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress);
1082  }
1083}
1084
1085bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
1086                              const SectionRef Section, uint64_t Offset,
1087                              unsigned Index, const RuntimeFunction &RF) {
1088  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
1089          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
1090         "unpacked entry cannot be treated as a packed entry");
1091
1092  uint64_t FunctionAddress, FunctionOffset;
1093  ErrorOr<SymbolRef> Function = getSymbolForLocation(
1094      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1095      /*FunctionOnly=*/true);
1096
1097  StringRef FunctionName;
1098  if (Function) {
1099    Expected<StringRef> FunctionNameOrErr = Function->getName();
1100    if (!FunctionNameOrErr) {
1101      std::string Buf;
1102      llvm::raw_string_ostream OS(Buf);
1103      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1104      OS.flush();
1105      report_fatal_error(Buf);
1106    }
1107    FunctionName = *FunctionNameOrErr;
1108  }
1109
1110  SW.printString("Function",
1111                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1112  if (!isAArch64)
1113    SW.printBoolean("Fragment",
1114                    RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
1115  SW.printNumber("FunctionLength", RF.FunctionLength());
1116  SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
1117  SW.printBoolean("HomedParameters", RF.H());
1118  SW.startLine() << "SavedRegisters: ";
1119                 printRegisters(SavedRegisterMask(RF));
1120  OS << '\n';
1121  SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
1122
1123  return true;
1124}
1125
1126bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
1127                                   const SectionRef Section, uint64_t Offset,
1128                                   unsigned Index,
1129                                   const RuntimeFunctionARM64 &RF) {
1130  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
1131          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
1132         "unpacked entry cannot be treated as a packed entry");
1133
1134  uint64_t FunctionAddress, FunctionOffset;
1135  ErrorOr<SymbolRef> Function = getSymbolForLocation(
1136      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1137      /*FunctionOnly=*/true);
1138
1139  StringRef FunctionName;
1140  if (Function) {
1141    Expected<StringRef> FunctionNameOrErr = Function->getName();
1142    if (!FunctionNameOrErr) {
1143      std::string Buf;
1144      llvm::raw_string_ostream OS(Buf);
1145      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1146      OS.flush();
1147      report_fatal_error(Buf);
1148    }
1149    FunctionName = *FunctionNameOrErr;
1150  }
1151
1152  SW.printString("Function",
1153                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1154  SW.printBoolean("Fragment",
1155                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
1156  SW.printNumber("FunctionLength", RF.FunctionLength());
1157  SW.printNumber("RegF", RF.RegF());
1158  SW.printNumber("RegI", RF.RegI());
1159  SW.printBoolean("HomedParameters", RF.H());
1160  SW.printNumber("CR", RF.CR());
1161  SW.printNumber("FrameSize", RF.FrameSize() << 4);
1162  ListScope PS(SW, "Prologue");
1163
1164  // Synthesize the equivalent prologue according to the documentation
1165  // at https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling,
1166  // printed in reverse order compared to the docs, to match how prologues
1167  // are printed for the non-packed case.
1168  int IntSZ = 8 * RF.RegI();
1169  if (RF.CR() == 1)
1170    IntSZ += 8;
1171  int FpSZ = 8 * RF.RegF();
1172  if (RF.RegF())
1173    FpSZ += 8;
1174  int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf;
1175  int LocSZ = (RF.FrameSize() << 4) - SavSZ;
1176
1177  if (RF.CR() == 3) {
1178    SW.startLine() << "mov x29, sp\n";
1179    if (LocSZ <= 512) {
1180      SW.startLine() << format("stp x29, lr, [sp, #-%d]!\n", LocSZ);
1181    } else {
1182      SW.startLine() << "stp x29, lr, [sp, #0]\n";
1183    }
1184  }
1185  if (LocSZ > 4080) {
1186    SW.startLine() << format("sub sp, sp, #%d\n", LocSZ - 4080);
1187    SW.startLine() << "sub sp, sp, #4080\n";
1188  } else if ((RF.CR() != 3 && LocSZ > 0) || LocSZ > 512) {
1189    SW.startLine() << format("sub sp, sp, #%d\n", LocSZ);
1190  }
1191  if (RF.H()) {
1192    SW.startLine() << format("stp x6, x7, [sp, #%d]\n", IntSZ + FpSZ + 48);
1193    SW.startLine() << format("stp x4, x5, [sp, #%d]\n", IntSZ + FpSZ + 32);
1194    SW.startLine() << format("stp x2, x3, [sp, #%d]\n", IntSZ + FpSZ + 16);
1195    if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) {
1196      SW.startLine() << format("stp x0, x1, [sp, #%d]\n", IntSZ + FpSZ);
1197    } else {
1198      // This case isn't documented; if neither RegI nor RegF nor CR=1
1199      // have decremented the stack pointer by SavSZ, we need to do it here
1200      // (as the final stack adjustment of LocSZ excludes SavSZ).
1201      SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ);
1202    }
1203  }
1204  int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0;
1205  for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) {
1206    if (I == (FloatRegs + 1) / 2 - 1 && FloatRegs % 2 == 1) {
1207      // The last register, an odd register without a pair
1208      SW.startLine() << format("str d%d, [sp, #%d]\n", 8 + 2 * I,
1209                               IntSZ + 16 * I);
1210    } else if (I == 0 && RF.RegI() == 0 && RF.CR() != 1) {
1211      SW.startLine() << format("stp d%d, d%d, [sp, #-%d]!\n", 8 + 2 * I,
1212                               8 + 2 * I + 1, SavSZ);
1213    } else {
1214      SW.startLine() << format("stp d%d, d%d, [sp, #%d]\n", 8 + 2 * I,
1215                               8 + 2 * I + 1, IntSZ + 16 * I);
1216    }
1217  }
1218  if (RF.CR() == 1 && (RF.RegI() % 2) == 0) {
1219    if (RF.RegI() == 0)
1220      SW.startLine() << format("str lr, [sp, #-%d]!\n", SavSZ);
1221    else
1222      SW.startLine() << format("str lr, [sp, #%d]\n", IntSZ - 8);
1223  }
1224  for (int I = (RF.RegI() + 1) / 2 - 1; I >= 0; I--) {
1225    if (I == (RF.RegI() + 1) / 2 - 1 && RF.RegI() % 2 == 1) {
1226      // The last register, an odd register without a pair
1227      if (RF.CR() == 1) {
1228        if (I == 0) { // If this is the only register pair
1229          // CR=1 combined with RegI=1 doesn't map to a documented case;
1230          // it doesn't map to any regular unwind info opcode, and the
1231          // actual unwinder doesn't support it.
1232          SW.startLine() << "INVALID!\n";
1233        } else
1234          SW.startLine() << format("stp x%d, lr, [sp, #%d]\n", 19 + 2 * I,
1235                                   16 * I);
1236      } else {
1237        if (I == 0)
1238          SW.startLine() << format("str x%d, [sp, #-%d]!\n", 19 + 2 * I, SavSZ);
1239        else
1240          SW.startLine() << format("str x%d, [sp, #%d]\n", 19 + 2 * I, 16 * I);
1241      }
1242    } else if (I == 0) {
1243      // The first register pair
1244      SW.startLine() << format("stp x19, x20, [sp, #-%d]!\n", SavSZ);
1245    } else {
1246      SW.startLine() << format("stp x%d, x%d, [sp, #%d]\n", 19 + 2 * I,
1247                               19 + 2 * I + 1, 16 * I);
1248    }
1249  }
1250  SW.startLine() << "end\n";
1251
1252  return true;
1253}
1254
1255bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,
1256                                     const SectionRef Section, unsigned Index,
1257                                     ArrayRef<uint8_t> Contents) {
1258  uint64_t Offset = PDataEntrySize * Index;
1259  const ulittle32_t *Data =
1260    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
1261
1262  const RuntimeFunction Entry(Data);
1263  DictScope RFS(SW, "RuntimeFunction");
1264  if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)
1265    return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);
1266  if (isAArch64) {
1267    const RuntimeFunctionARM64 EntryARM64(Data);
1268    return dumpPackedARM64Entry(COFF, Section, Offset, Index, EntryARM64);
1269  }
1270  return dumpPackedEntry(COFF, Section, Offset, Index, Entry);
1271}
1272
1273void Decoder::dumpProcedureData(const COFFObjectFile &COFF,
1274                                const SectionRef Section) {
1275  ArrayRef<uint8_t> Contents;
1276  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
1277    return;
1278
1279  if (Contents.size() % PDataEntrySize) {
1280    errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n";
1281    return;
1282  }
1283
1284  for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI)
1285    if (!dumpProcedureDataEntry(COFF, Section, EI, Contents))
1286      break;
1287}
1288
1289Error Decoder::dumpProcedureData(const COFFObjectFile &COFF) {
1290  for (const auto &Section : COFF.sections()) {
1291    Expected<StringRef> NameOrErr =
1292        COFF.getSectionName(COFF.getCOFFSection(Section));
1293    if (!NameOrErr)
1294      return NameOrErr.takeError();
1295
1296    if (NameOrErr->startswith(".pdata"))
1297      dumpProcedureData(COFF, Section);
1298  }
1299  return Error::success();
1300}
1301}
1302}
1303}
1304