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 << "bx <reg>";
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// Unwind opcodes for ARM64.
147// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
148const Decoder::RingEntry Decoder::Ring64[] = {
149    {0xe0, 0x00, 1, &Decoder::opcode_alloc_s},
150    {0xe0, 0x20, 1, &Decoder::opcode_save_r19r20_x},
151    {0xc0, 0x40, 1, &Decoder::opcode_save_fplr},
152    {0xc0, 0x80, 1, &Decoder::opcode_save_fplr_x},
153    {0xf8, 0xc0, 2, &Decoder::opcode_alloc_m},
154    {0xfc, 0xc8, 2, &Decoder::opcode_save_regp},
155    {0xfc, 0xcc, 2, &Decoder::opcode_save_regp_x},
156    {0xfc, 0xd0, 2, &Decoder::opcode_save_reg},
157    {0xfe, 0xd4, 2, &Decoder::opcode_save_reg_x},
158    {0xfe, 0xd6, 2, &Decoder::opcode_save_lrpair},
159    {0xfe, 0xd8, 2, &Decoder::opcode_save_fregp},
160    {0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x},
161    {0xfe, 0xdc, 2, &Decoder::opcode_save_freg},
162    {0xff, 0xde, 2, &Decoder::opcode_save_freg_x},
163    {0xff, 0xe0, 4, &Decoder::opcode_alloc_l},
164    {0xff, 0xe1, 1, &Decoder::opcode_setfp},
165    {0xff, 0xe2, 2, &Decoder::opcode_addfp},
166    {0xff, 0xe3, 1, &Decoder::opcode_nop},
167    {0xff, 0xe4, 1, &Decoder::opcode_end},
168    {0xff, 0xe5, 1, &Decoder::opcode_end_c},
169    {0xff, 0xe6, 1, &Decoder::opcode_save_next},
170    {0xff, 0xe7, 3, &Decoder::opcode_save_any_reg},
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, 0xeb, 1, &Decoder::opcode_ec_context},
175    {0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call},
176    {0xff, 0xfc, 1, &Decoder::opcode_pac_sign_lr},
177};
178
179static void printRange(raw_ostream &OS, ListSeparator &LS, unsigned First,
180                       unsigned Last, char Letter) {
181  if (First == Last)
182    OS << LS << Letter << First;
183  else
184    OS << LS << Letter << First << "-" << Letter << Last;
185}
186
187static void printRange(raw_ostream &OS, uint32_t Mask, ListSeparator &LS,
188                       unsigned Start, unsigned End, char Letter) {
189  int First = -1;
190  for (unsigned RI = Start; RI <= End; ++RI) {
191    if (Mask & (1 << RI)) {
192      if (First < 0)
193        First = RI;
194    } else {
195      if (First >= 0) {
196        printRange(OS, LS, First, RI - 1, Letter);
197        First = -1;
198      }
199    }
200  }
201  if (First >= 0)
202    printRange(OS, LS, First, End, Letter);
203}
204
205void Decoder::printGPRMask(uint16_t GPRMask) {
206  OS << '{';
207  ListSeparator LS;
208  printRange(OS, GPRMask, LS, 0, 12, 'r');
209  if (GPRMask & (1 << 14))
210    OS << LS << "lr";
211  if (GPRMask & (1 << 15))
212    OS << LS << "pc";
213  OS << '}';
214}
215
216void Decoder::printVFPMask(uint32_t VFPMask) {
217  OS << '{';
218  ListSeparator LS;
219  printRange(OS, VFPMask, LS, 0, 31, 'd');
220  OS << '}';
221}
222
223ErrorOr<object::SectionRef>
224Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {
225  for (const auto &Section : COFF.sections()) {
226    uint64_t Address = Section.getAddress();
227    uint64_t Size = Section.getSize();
228
229    if (VA >= Address && (VA - Address) <= Size)
230      return Section;
231  }
232  return inconvertibleErrorCode();
233}
234
235ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF,
236                                              uint64_t VA, bool FunctionOnly) {
237  for (const auto &Symbol : COFF.symbols()) {
238    Expected<SymbolRef::Type> Type = Symbol.getType();
239    if (!Type)
240      return errorToErrorCode(Type.takeError());
241    if (FunctionOnly && *Type != SymbolRef::ST_Function)
242      continue;
243
244    Expected<uint64_t> Address = Symbol.getAddress();
245    if (!Address)
246      return errorToErrorCode(Address.takeError());
247    if (*Address == VA)
248      return Symbol;
249  }
250  return inconvertibleErrorCode();
251}
252
253ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,
254                                               const SectionRef &Section,
255                                               uint64_t Offset) {
256  for (const auto &Relocation : Section.relocations()) {
257    uint64_t RelocationOffset = Relocation.getOffset();
258    if (RelocationOffset == Offset)
259      return *Relocation.getSymbol();
260  }
261  return inconvertibleErrorCode();
262}
263
264SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF, SymbolRef Sym,
265                                      uint64_t &SymbolOffset) {
266  // The symbol resolved by getRelocatedSymbol can be any internal
267  // nondescriptive symbol; try to resolve a more descriptive one.
268  COFFSymbolRef CoffSym = COFF.getCOFFSymbol(Sym);
269  if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL &&
270      CoffSym.getSectionDefinition() == nullptr)
271    return Sym;
272  for (const auto &S : COFF.symbols()) {
273    COFFSymbolRef CS = COFF.getCOFFSymbol(S);
274    if (CS.getSectionNumber() == CoffSym.getSectionNumber() &&
275        CS.getValue() <= CoffSym.getValue() + SymbolOffset &&
276        CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL &&
277        CS.getSectionDefinition() == nullptr) {
278      uint32_t Offset = CoffSym.getValue() + SymbolOffset - CS.getValue();
279      if (Offset <= SymbolOffset) {
280        SymbolOffset = Offset;
281        Sym = S;
282        CoffSym = CS;
283        if (CS.isExternal() && SymbolOffset == 0)
284          return Sym;
285      }
286    }
287  }
288  return Sym;
289}
290
291ErrorOr<SymbolRef> Decoder::getSymbolForLocation(
292    const COFFObjectFile &COFF, const SectionRef &Section,
293    uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress,
294    uint64_t &SymbolOffset, bool FunctionOnly) {
295  // Try to locate a relocation that points at the offset in the section
296  ErrorOr<SymbolRef> SymOrErr =
297      getRelocatedSymbol(COFF, Section, OffsetInSection);
298  if (SymOrErr) {
299    // We found a relocation symbol; the immediate offset needs to be added
300    // to the symbol address.
301    SymbolOffset = ImmediateOffset;
302
303    Expected<uint64_t> AddressOrErr = SymOrErr->getAddress();
304    if (!AddressOrErr) {
305      std::string Buf;
306      llvm::raw_string_ostream OS(Buf);
307      logAllUnhandledErrors(AddressOrErr.takeError(), OS);
308      report_fatal_error(Twine(OS.str()));
309    }
310    // We apply SymbolOffset here directly. We return it separately to allow
311    // the caller to print it as an offset on the symbol name.
312    SymbolAddress = *AddressOrErr + SymbolOffset;
313
314    if (FunctionOnly) // Resolve label/section symbols into function names.
315      SymOrErr = getPreferredSymbol(COFF, *SymOrErr, SymbolOffset);
316  } else {
317    // No matching relocation found; operating on a linked image. Try to
318    // find a descriptive symbol if possible. The immediate offset contains
319    // the image relative address, and we shouldn't add any offset to the
320    // symbol.
321    SymbolAddress = COFF.getImageBase() + ImmediateOffset;
322    SymbolOffset = 0;
323    SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly);
324  }
325  return SymOrErr;
326}
327
328bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset,
329                              unsigned Length, bool Prologue) {
330  uint8_t Imm = OC[Offset] & 0x7f;
331  SW.startLine() << format("0x%02x                ; %s sp, #(%u * 4)\n",
332                           OC[Offset],
333                           static_cast<const char *>(Prologue ? "sub" : "add"),
334                           Imm);
335  ++Offset;
336  return false;
337}
338
339bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset,
340                              unsigned Length, bool Prologue) {
341  unsigned Link = (OC[Offset] & 0x20) >> 5;
342  uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))
343                        | ((OC[Offset + 0] & 0x1f) << 8)
344                        | ((OC[Offset + 1] & 0xff) << 0);
345  assert((~RegisterMask & (1 << 13)) && "sp must not be set");
346  assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");
347
348  SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",
349                           OC[Offset + 0], OC[Offset + 1],
350                           Prologue ? "push" : "pop");
351  printGPRMask(RegisterMask);
352  OS << '\n';
353
354  Offset += 2;
355  return false;
356}
357
358bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset,
359                              unsigned Length, bool Prologue) {
360  if (Prologue)
361    SW.startLine() << format("0x%02x                ; mov r%u, sp\n",
362                             OC[Offset], OC[Offset] & 0xf);
363  else
364    SW.startLine() << format("0x%02x                ; mov sp, r%u\n",
365                             OC[Offset], OC[Offset] & 0xf);
366  ++Offset;
367  return false;
368}
369
370bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset,
371                              unsigned Length, bool Prologue) {
372  unsigned Link = (OC[Offset] & 0x4) >> 2;
373  unsigned Count = (OC[Offset] & 0x3);
374
375  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
376                   | (((1 << (Count + 1)) - 1) << 4);
377
378  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
379                           Prologue ? "push" : "pop");
380  printGPRMask(GPRMask);
381  OS << '\n';
382
383  ++Offset;
384  return false;
385}
386
387bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset,
388                              unsigned Length, bool Prologue) {
389  unsigned Link = (OC[Offset] & 0x4) >> 2;
390  unsigned Count = (OC[Offset] & 0x3) + 4;
391
392  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
393                   | (((1 << (Count + 1)) - 1) << 4);
394
395  SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],
396                           Prologue ? "push" : "pop");
397  printGPRMask(GPRMask);
398  OS << '\n';
399
400  ++Offset;
401  return false;
402}
403
404bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset,
405                              unsigned Length, bool Prologue) {
406  unsigned High = (OC[Offset] & 0x7);
407  uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);
408
409  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
410                           Prologue ? "vpush" : "vpop");
411  printVFPMask(VFPMask);
412  OS << '\n';
413
414  ++Offset;
415  return false;
416}
417
418bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset,
419                              unsigned Length, bool Prologue) {
420  uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);
421
422  SW.startLine() << format("0x%02x 0x%02x           ; %s.w sp, #(%u * 4)\n",
423                           OC[Offset + 0], OC[Offset + 1],
424                           static_cast<const char *>(Prologue ? "sub" : "add"),
425                           Imm);
426
427  Offset += 2;
428  return false;
429}
430
431bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset,
432                              unsigned Length, bool Prologue) {
433  uint16_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))
434                   | ((OC[Offset + 1] & 0xff) << 0);
435
436  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
437                           OC[Offset + 1], Prologue ? "push" : "pop");
438  printGPRMask(GPRMask);
439  OS << '\n';
440
441  Offset += 2;
442  return false;
443}
444
445bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset,
446                              unsigned Length, bool Prologue) {
447  assert(!Prologue && "may not be used in prologue");
448
449  if (OC[Offset + 1] & 0xf0)
450    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
451                             OC[Offset + 0], OC[Offset +  1]);
452  else
453    SW.startLine()
454      << format("0x%02x 0x%02x           ; microsoft-specific (type: %u)\n",
455                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);
456
457  Offset += 2;
458  return false;
459}
460
461bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset,
462                              unsigned Length, bool Prologue) {
463  if (OC[Offset + 1] & 0xf0)
464    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
465                             OC[Offset + 0], OC[Offset +  1]);
466  else if (Prologue)
467    SW.startLine()
468      << format("0x%02x 0x%02x           ; str.w lr, [sp, #-%u]!\n",
469                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
470  else
471    SW.startLine()
472      << format("0x%02x 0x%02x           ; ldr.w lr, [sp], #%u\n",
473                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
474
475  Offset += 2;
476  return false;
477}
478
479bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset,
480                              unsigned Length, bool Prologue) {
481  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
482  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
483  uint32_t VFPMask = ((1 << (End + 1 - Start)) - 1) << Start;
484
485  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
486                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
487  printVFPMask(VFPMask);
488  OS << '\n';
489
490  Offset += 2;
491  return false;
492}
493
494bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset,
495                              unsigned Length, bool Prologue) {
496  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
497  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
498  uint32_t VFPMask = ((1 << (End + 1 - Start)) - 1) << (16 + Start);
499
500  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
501                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
502  printVFPMask(VFPMask);
503  OS << '\n';
504
505  Offset += 2;
506  return false;
507}
508
509bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset,
510                              unsigned Length, bool Prologue) {
511  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
512
513  SW.startLine() << format("0x%02x 0x%02x 0x%02x      ; %s sp, sp, #(%u * 4)\n",
514                           OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
515                           static_cast<const char *>(Prologue ? "sub" : "add"),
516                           Imm);
517
518  Offset += 3;
519  return false;
520}
521
522bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset,
523                              unsigned Length, bool Prologue) {
524  uint32_t Imm = (OC[Offset + 1] << 16)
525               | (OC[Offset + 2] << 8)
526               | (OC[Offset + 3] << 0);
527
528  SW.startLine()
529    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
530              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
531              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
532
533  Offset += 4;
534  return false;
535}
536
537bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset,
538                              unsigned Length, bool Prologue) {
539  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
540
541  SW.startLine()
542    << format("0x%02x 0x%02x 0x%02x      ; %s.w sp, sp, #(%u * 4)\n",
543              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
544              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
545
546  Offset += 3;
547  return false;
548}
549
550bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset,
551                              unsigned Length, bool Prologue) {
552  uint32_t Imm = (OC[Offset + 1] << 16)
553               | (OC[Offset + 2] << 8)
554               | (OC[Offset + 3] << 0);
555
556  SW.startLine()
557    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
558              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
559              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
560
561  Offset += 4;
562  return false;
563}
564
565bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset,
566                              unsigned Length, bool Prologue) {
567  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
568  ++Offset;
569  return false;
570}
571
572bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset,
573                              unsigned Length, bool Prologue) {
574  SW.startLine() << format("0x%02x                ; nop.w\n", OC[Offset]);
575  ++Offset;
576  return false;
577}
578
579bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset,
580                              unsigned Length, bool Prologue) {
581  SW.startLine() << format("0x%02x                ; bx <reg>\n", OC[Offset]);
582  ++Offset;
583  return true;
584}
585
586bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset,
587                              unsigned Length, bool Prologue) {
588  SW.startLine() << format("0x%02x                ; b.w <target>\n", OC[Offset]);
589  ++Offset;
590  return true;
591}
592
593bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset,
594                              unsigned Length, bool Prologue) {
595  ++Offset;
596  return true;
597}
598
599// ARM64 unwind codes start here.
600bool Decoder::opcode_alloc_s(const uint8_t *OC, unsigned &Offset,
601                             unsigned Length, bool Prologue) {
602  uint32_t NumBytes = (OC[Offset] & 0x1F) << 4;
603  SW.startLine() << format("0x%02x                ; %s sp, #%u\n", OC[Offset],
604                           static_cast<const char *>(Prologue ? "sub" : "add"),
605                           NumBytes);
606  ++Offset;
607  return false;
608}
609
610bool Decoder::opcode_save_r19r20_x(const uint8_t *OC, unsigned &Offset,
611                                   unsigned Length, bool Prologue) {
612  uint32_t Off = (OC[Offset] & 0x1F) << 3;
613  if (Prologue)
614    SW.startLine() << format(
615        "0x%02x                ; stp x19, x20, [sp, #-%u]!\n", OC[Offset], Off);
616  else
617    SW.startLine() << format(
618        "0x%02x                ; ldp x19, x20, [sp], #%u\n", OC[Offset], Off);
619  ++Offset;
620  return false;
621}
622
623bool Decoder::opcode_save_fplr(const uint8_t *OC, unsigned &Offset,
624                               unsigned Length, bool Prologue) {
625  uint32_t Off = (OC[Offset] & 0x3F) << 3;
626  SW.startLine() << format(
627      "0x%02x                ; %s x29, x30, [sp, #%u]\n", OC[Offset],
628      static_cast<const char *>(Prologue ? "stp" : "ldp"), Off);
629  ++Offset;
630  return false;
631}
632
633bool Decoder::opcode_save_fplr_x(const uint8_t *OC, unsigned &Offset,
634                                 unsigned Length, bool Prologue) {
635  uint32_t Off = ((OC[Offset] & 0x3F) + 1) << 3;
636  if (Prologue)
637    SW.startLine() << format(
638        "0x%02x                ; stp x29, x30, [sp, #-%u]!\n", OC[Offset], Off);
639  else
640    SW.startLine() << format(
641        "0x%02x                ; ldp x29, x30, [sp], #%u\n", OC[Offset], Off);
642  ++Offset;
643  return false;
644}
645
646bool Decoder::opcode_alloc_m(const uint8_t *OC, unsigned &Offset,
647                             unsigned Length, bool Prologue) {
648  uint32_t NumBytes = ((OC[Offset] & 0x07) << 8);
649  NumBytes |= (OC[Offset + 1] & 0xFF);
650  NumBytes <<= 4;
651  SW.startLine() << format("0x%02x%02x              ; %s sp, #%u\n",
652                           OC[Offset], OC[Offset + 1],
653                           static_cast<const char *>(Prologue ? "sub" : "add"),
654                           NumBytes);
655  Offset += 2;
656  return false;
657}
658
659bool Decoder::opcode_save_regp(const uint8_t *OC, unsigned &Offset,
660                               unsigned Length, bool Prologue) {
661  uint32_t Reg = ((OC[Offset] & 0x03) << 8);
662  Reg |= (OC[Offset + 1] & 0xC0);
663  Reg >>= 6;
664  Reg += 19;
665  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
666  SW.startLine() << format(
667      "0x%02x%02x              ; %s x%u, x%u, [sp, #%u]\n",
668      OC[Offset], OC[Offset + 1],
669      static_cast<const char *>(Prologue ? "stp" : "ldp"), Reg, Reg + 1, Off);
670  Offset += 2;
671  return false;
672}
673
674bool Decoder::opcode_save_regp_x(const uint8_t *OC, unsigned &Offset,
675                                 unsigned Length, bool Prologue) {
676  uint32_t Reg = ((OC[Offset] & 0x03) << 8);
677  Reg |= (OC[Offset + 1] & 0xC0);
678  Reg >>= 6;
679  Reg += 19;
680  uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;
681  if (Prologue)
682    SW.startLine() << format(
683        "0x%02x%02x              ; stp x%u, x%u, [sp, #-%u]!\n",
684        OC[Offset], OC[Offset + 1], Reg,
685        Reg + 1, Off);
686  else
687    SW.startLine() << format(
688        "0x%02x%02x              ; ldp x%u, x%u, [sp], #%u\n",
689        OC[Offset], OC[Offset + 1], Reg,
690        Reg + 1, Off);
691  Offset += 2;
692  return false;
693}
694
695bool Decoder::opcode_save_reg(const uint8_t *OC, unsigned &Offset,
696                              unsigned Length, bool Prologue) {
697  uint32_t Reg = (OC[Offset] & 0x03) << 8;
698  Reg |= (OC[Offset + 1] & 0xC0);
699  Reg >>= 6;
700  Reg += 19;
701  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
702  SW.startLine() << format("0x%02x%02x              ; %s x%u, [sp, #%u]\n",
703                           OC[Offset], OC[Offset + 1],
704                           static_cast<const char *>(Prologue ? "str" : "ldr"),
705                           Reg, Off);
706  Offset += 2;
707  return false;
708}
709
710bool Decoder::opcode_save_reg_x(const uint8_t *OC, unsigned &Offset,
711                                unsigned Length, bool Prologue) {
712  uint32_t Reg = (OC[Offset] & 0x01) << 8;
713  Reg |= (OC[Offset + 1] & 0xE0);
714  Reg >>= 5;
715  Reg += 19;
716  uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;
717  if (Prologue)
718    SW.startLine() << format("0x%02x%02x              ; str x%u, [sp, #-%u]!\n",
719                             OC[Offset], OC[Offset + 1], Reg, Off);
720  else
721    SW.startLine() << format("0x%02x%02x              ; ldr x%u, [sp], #%u\n",
722                             OC[Offset], OC[Offset + 1], Reg, Off);
723  Offset += 2;
724  return false;
725}
726
727bool Decoder::opcode_save_lrpair(const uint8_t *OC, unsigned &Offset,
728                                 unsigned Length, bool Prologue) {
729  uint32_t Reg = (OC[Offset] & 0x01) << 8;
730  Reg |= (OC[Offset + 1] & 0xC0);
731  Reg >>= 6;
732  Reg *= 2;
733  Reg += 19;
734  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
735  SW.startLine() << format("0x%02x%02x              ; %s x%u, lr, [sp, #%u]\n",
736                           OC[Offset], OC[Offset + 1],
737                           static_cast<const char *>(Prologue ? "stp" : "ldp"),
738                           Reg, Off);
739  Offset += 2;
740  return false;
741}
742
743bool Decoder::opcode_save_fregp(const uint8_t *OC, unsigned &Offset,
744                                unsigned Length, bool Prologue) {
745  uint32_t Reg = (OC[Offset] & 0x01) << 8;
746  Reg |= (OC[Offset + 1] & 0xC0);
747  Reg >>= 6;
748  Reg += 8;
749  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
750  SW.startLine() << format("0x%02x%02x              ; %s d%u, d%u, [sp, #%u]\n",
751                           OC[Offset], OC[Offset + 1],
752                           static_cast<const char *>(Prologue ? "stp" : "ldp"),
753                           Reg, Reg + 1, Off);
754  Offset += 2;
755  return false;
756}
757
758bool Decoder::opcode_save_fregp_x(const uint8_t *OC, unsigned &Offset,
759                                  unsigned Length, bool Prologue) {
760  uint32_t Reg = (OC[Offset] & 0x01) << 8;
761  Reg |= (OC[Offset + 1] & 0xC0);
762  Reg >>= 6;
763  Reg += 8;
764  uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;
765  if (Prologue)
766    SW.startLine() << format(
767        "0x%02x%02x              ; stp d%u, d%u, [sp, #-%u]!\n", OC[Offset],
768        OC[Offset + 1], Reg, Reg + 1, Off);
769  else
770    SW.startLine() << format(
771        "0x%02x%02x              ; ldp d%u, d%u, [sp], #%u\n", OC[Offset],
772        OC[Offset + 1], Reg, Reg + 1, Off);
773  Offset += 2;
774  return false;
775}
776
777bool Decoder::opcode_save_freg(const uint8_t *OC, unsigned &Offset,
778                               unsigned Length, bool Prologue) {
779  uint32_t Reg = (OC[Offset] & 0x01) << 8;
780  Reg |= (OC[Offset + 1] & 0xC0);
781  Reg >>= 6;
782  Reg += 8;
783  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
784  SW.startLine() << format("0x%02x%02x              ; %s d%u, [sp, #%u]\n",
785                           OC[Offset], OC[Offset + 1],
786                           static_cast<const char *>(Prologue ? "str" : "ldr"),
787                           Reg, Off);
788  Offset += 2;
789  return false;
790}
791
792bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset,
793                                 unsigned Length, bool Prologue) {
794  uint32_t Reg = ((OC[Offset + 1] & 0xE0) >> 5) + 8;
795  uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;
796  if (Prologue)
797    SW.startLine() << format(
798        "0x%02x%02x              ; str d%u, [sp, #-%u]!\n", OC[Offset],
799        OC[Offset + 1], Reg, Off);
800  else
801    SW.startLine() << format(
802        "0x%02x%02x              ; ldr d%u, [sp], #%u\n", OC[Offset],
803        OC[Offset + 1], Reg, Off);
804  Offset += 2;
805  return false;
806}
807
808bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset,
809                             unsigned Length, bool Prologue) {
810  unsigned Off =
811      (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) | (OC[Offset + 3] << 0);
812  Off <<= 4;
813  SW.startLine() << format(
814      "0x%02x%02x%02x%02x          ; %s sp, #%u\n", OC[Offset], OC[Offset + 1],
815      OC[Offset + 2], OC[Offset + 3],
816      static_cast<const char *>(Prologue ? "sub" : "add"), Off);
817  Offset += 4;
818  return false;
819}
820
821bool Decoder::opcode_setfp(const uint8_t *OC, unsigned &Offset, unsigned Length,
822                           bool Prologue) {
823  SW.startLine() << format("0x%02x                ; mov %s, %s\n", OC[Offset],
824                           static_cast<const char *>(Prologue ? "fp" : "sp"),
825                           static_cast<const char *>(Prologue ? "sp" : "fp"));
826  ++Offset;
827  return false;
828}
829
830bool Decoder::opcode_addfp(const uint8_t *OC, unsigned &Offset, unsigned Length,
831                           bool Prologue) {
832  unsigned NumBytes = OC[Offset + 1] << 3;
833  SW.startLine() << format(
834      "0x%02x%02x              ; %s %s, %s, #%u\n", OC[Offset], OC[Offset + 1],
835      static_cast<const char *>(Prologue ? "add" : "sub"),
836      static_cast<const char *>(Prologue ? "fp" : "sp"),
837      static_cast<const char *>(Prologue ? "sp" : "fp"), NumBytes);
838  Offset += 2;
839  return false;
840}
841
842bool Decoder::opcode_nop(const uint8_t *OC, unsigned &Offset, unsigned Length,
843                         bool Prologue) {
844  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
845  ++Offset;
846  return false;
847}
848
849bool Decoder::opcode_end(const uint8_t *OC, unsigned &Offset, unsigned Length,
850                         bool Prologue) {
851  SW.startLine() << format("0x%02x                ; end\n", OC[Offset]);
852  ++Offset;
853  return true;
854}
855
856bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length,
857                           bool Prologue) {
858  SW.startLine() << format("0x%02x                ; end_c\n", OC[Offset]);
859  ++Offset;
860  return false;
861}
862
863bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,
864                               unsigned Length, bool Prologue) {
865  if (Prologue)
866    SW.startLine() << format("0x%02x                ; save next\n", OC[Offset]);
867  else
868    SW.startLine() << format("0x%02x                ; restore next\n",
869                             OC[Offset]);
870  ++Offset;
871  return false;
872}
873
874bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset,
875                                  unsigned Length, bool Prologue) {
876  // Whether the instruction has writeback
877  bool Writeback = (OC[Offset + 1] & 0x20) == 0x20;
878  // Whether the instruction is paired.  (Paired instructions are required
879  // to save/restore adjacent registers.)
880  bool Paired = (OC[Offset + 1] & 0x40) == 0x40;
881  // The kind of register saved:
882  // - 0 is an x register
883  // - 1 is the low half of a q register
884  // - 2 is a whole q register
885  int RegKind = (OC[Offset + 2] & 0xC0) >> 6;
886  // Encoded register name (0 -> x0/q0, 1 -> x1/q1, etc.)
887  int Reg = OC[Offset + 1] & 0x1F;
888  // Encoded stack offset of load/store instruction; decoding varies by mode.
889  int StackOffset = OC[Offset + 2] & 0x3F;
890  if (Writeback)
891    StackOffset++;
892  if (!Writeback && !Paired && RegKind != 2)
893    StackOffset *= 8;
894  else
895    StackOffset *= 16;
896
897  SW.startLine() << format("0x%02x%02x%02x            ; ", OC[Offset],
898                           OC[Offset + 1], OC[Offset + 2]);
899
900  // Verify the encoding is in a form we understand.  The high bit of the first
901  // byte, and mode 3 for the register kind are apparently reserved.  The
902  // encoded register must refer to a valid register.
903  int MaxReg = 0x1F;
904  if (Paired)
905    --MaxReg;
906  if (RegKind == 0)
907    --MaxReg;
908  if ((OC[Offset + 1] & 0x80) == 0x80 || RegKind == 3 || Reg > MaxReg) {
909    SW.getOStream() << "invalid save_any_reg encoding\n";
910    Offset += 3;
911    return false;
912  }
913
914  if (Paired) {
915    if (Prologue)
916      SW.getOStream() << "stp ";
917    else
918      SW.getOStream() << "ldp ";
919  } else {
920    if (Prologue)
921      SW.getOStream() << "str ";
922    else
923      SW.getOStream() << "ldr ";
924  }
925
926  char RegChar = 'x';
927  if (RegKind == 1) {
928    RegChar = 'd';
929  } else if (RegKind == 2) {
930    RegChar = 'q';
931  }
932
933  if (Paired)
934    SW.getOStream() << format("%c%d, %c%d, ", RegChar, Reg, RegChar, Reg + 1);
935  else
936    SW.getOStream() << format("%c%d, ", RegChar, Reg);
937
938  if (Writeback) {
939    if (Prologue)
940      SW.getOStream() << format("[sp, #-%d]!\n", StackOffset);
941    else
942      SW.getOStream() << format("[sp], #%d\n", StackOffset);
943  } else {
944    SW.getOStream() << format("[sp, #%d]\n", StackOffset);
945  }
946
947  Offset += 3;
948  return false;
949}
950
951bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset,
952                                unsigned Length, bool Prologue) {
953  SW.startLine() << format("0x%02x                ; trap frame\n", OC[Offset]);
954  ++Offset;
955  return false;
956}
957
958bool Decoder::opcode_machine_frame(const uint8_t *OC, unsigned &Offset,
959                                   unsigned Length, bool Prologue) {
960  SW.startLine() << format("0x%02x                ; machine frame\n",
961                           OC[Offset]);
962  ++Offset;
963  return false;
964}
965
966bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset,
967                             unsigned Length, bool Prologue) {
968  SW.startLine() << format("0x%02x                ; context\n", OC[Offset]);
969  ++Offset;
970  return false;
971}
972
973bool Decoder::opcode_ec_context(const uint8_t *OC, unsigned &Offset,
974                                unsigned Length, bool Prologue) {
975  SW.startLine() << format("0x%02x                ; EC context\n", OC[Offset]);
976  ++Offset;
977  return false;
978}
979
980bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset,
981                                           unsigned Length, bool Prologue) {
982  SW.startLine() << format("0x%02x                ; clear unwound to call\n",
983                           OC[Offset]);
984  ++Offset;
985  return false;
986}
987
988bool Decoder::opcode_pac_sign_lr(const uint8_t *OC, unsigned &Offset,
989                                 unsigned Length, bool Prologue) {
990  if (Prologue)
991    SW.startLine() << format("0x%02x                ; pacibsp\n", OC[Offset]);
992  else
993    SW.startLine() << format("0x%02x                ; autibsp\n", OC[Offset]);
994  ++Offset;
995  return false;
996}
997
998void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
999                            bool Prologue) {
1000  assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
1001  const RingEntry* DecodeRing = isAArch64 ? Ring64 : Ring;
1002  bool Terminated = false;
1003  for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
1004    for (unsigned DI = 0;; ++DI) {
1005      if ((isAArch64 && (DI >= std::size(Ring64))) ||
1006          (!isAArch64 && (DI >= std::size(Ring)))) {
1007        SW.startLine() << format("0x%02x                ; Bad opcode!\n",
1008                                 Opcodes.data()[OI]);
1009        ++OI;
1010        break;
1011      }
1012
1013      if ((Opcodes[OI] & DecodeRing[DI].Mask) == DecodeRing[DI].Value) {
1014        if (OI + DecodeRing[DI].Length > OE) {
1015          SW.startLine() << format("Opcode 0x%02x goes past the unwind data\n",
1016                                    Opcodes[OI]);
1017          OI += DecodeRing[DI].Length;
1018          break;
1019        }
1020        Terminated =
1021            (this->*DecodeRing[DI].Routine)(Opcodes.data(), OI, 0, Prologue);
1022        break;
1023      }
1024    }
1025  }
1026}
1027
1028bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
1029                              const SectionRef &Section,
1030                              uint64_t FunctionAddress, uint64_t VA) {
1031  ArrayRef<uint8_t> Contents;
1032  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
1033    return false;
1034
1035  uint64_t SectionVA = Section.getAddress();
1036  uint64_t Offset = VA - SectionVA;
1037  const ulittle32_t *Data =
1038    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
1039
1040  // Sanity check to ensure that the .xdata header is present.
1041  // A header is one or two words, followed by at least one word to describe
1042  // the unwind codes. Applicable to both ARM and AArch64.
1043  if (Contents.size() - Offset < 8)
1044    report_fatal_error(".xdata must be at least 8 bytes in size");
1045
1046  const ExceptionDataRecord XData(Data, isAArch64);
1047  DictScope XRS(SW, "ExceptionData");
1048  SW.printNumber("FunctionLength",
1049                 isAArch64 ? XData.FunctionLengthInBytesAArch64() :
1050                 XData.FunctionLengthInBytesARM());
1051  SW.printNumber("Version", XData.Vers());
1052  SW.printBoolean("ExceptionData", XData.X());
1053  SW.printBoolean("EpiloguePacked", XData.E());
1054  if (!isAArch64)
1055    SW.printBoolean("Fragment", XData.F());
1056  SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",
1057                 XData.EpilogueCount());
1058  uint64_t ByteCodeLength = XData.CodeWords() * sizeof(uint32_t);
1059  SW.printNumber("ByteCodeLength", ByteCodeLength);
1060
1061  if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) -
1062                (XData.E() ? 0 : XData.EpilogueCount() * 4) -
1063                (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) {
1064    SW.flush();
1065    report_fatal_error("Malformed unwind data");
1066  }
1067
1068  if (XData.E()) {
1069    ArrayRef<uint8_t> UC = XData.UnwindByteCode();
1070    {
1071      ListScope PS(SW, "Prologue");
1072      decodeOpcodes(UC, 0, /*Prologue=*/true);
1073    }
1074    if (XData.EpilogueCount()) {
1075      ListScope ES(SW, "Epilogue");
1076      decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);
1077    }
1078  } else {
1079    {
1080      ListScope PS(SW, "Prologue");
1081      decodeOpcodes(XData.UnwindByteCode(), 0, /*Prologue=*/true);
1082    }
1083    ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes();
1084    ListScope ESS(SW, "EpilogueScopes");
1085    for (const EpilogueScope ES : EpilogueScopes) {
1086      DictScope ESES(SW, "EpilogueScope");
1087      SW.printNumber("StartOffset", ES.EpilogueStartOffset());
1088      if (!isAArch64)
1089        SW.printNumber("Condition", ES.Condition());
1090      SW.printNumber("EpilogueStartIndex",
1091                     isAArch64 ? ES.EpilogueStartIndexAArch64()
1092                               : ES.EpilogueStartIndexARM());
1093      unsigned ReservedMask = isAArch64 ? 0xF : 0x3;
1094      if ((ES.ES >> 18) & ReservedMask)
1095        SW.printNumber("ReservedBits", (ES.ES >> 18) & ReservedMask);
1096
1097      ListScope Opcodes(SW, "Opcodes");
1098      decodeOpcodes(XData.UnwindByteCode(),
1099                    isAArch64 ? ES.EpilogueStartIndexAArch64()
1100                              : ES.EpilogueStartIndexARM(),
1101                    /*Prologue=*/false);
1102    }
1103  }
1104
1105  if (XData.X()) {
1106    const uint32_t Parameter = XData.ExceptionHandlerParameter();
1107    const size_t HandlerOffset = HeaderWords(XData) +
1108                                 (XData.E() ? 0 : XData.EpilogueCount()) +
1109                                 XData.CodeWords();
1110
1111    uint64_t Address, SymbolOffset;
1112    ErrorOr<SymbolRef> Symbol = getSymbolForLocation(
1113        COFF, Section, Offset + HandlerOffset * sizeof(uint32_t),
1114        XData.ExceptionHandlerRVA(), Address, SymbolOffset,
1115        /*FunctionOnly=*/true);
1116    if (!Symbol) {
1117      ListScope EHS(SW, "ExceptionHandler");
1118      SW.printHex("Routine", Address);
1119      SW.printHex("Parameter", Parameter);
1120      return true;
1121    }
1122
1123    Expected<StringRef> Name = Symbol->getName();
1124    if (!Name) {
1125      std::string Buf;
1126      llvm::raw_string_ostream OS(Buf);
1127      logAllUnhandledErrors(Name.takeError(), OS);
1128      report_fatal_error(Twine(OS.str()));
1129    }
1130
1131    ListScope EHS(SW, "ExceptionHandler");
1132    SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset));
1133    SW.printHex("Parameter", Parameter);
1134  }
1135
1136  return true;
1137}
1138
1139bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
1140                                const SectionRef Section, uint64_t Offset,
1141                                unsigned Index, const RuntimeFunction &RF) {
1142  assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
1143         "packed entry cannot be treated as an unpacked entry");
1144
1145  uint64_t FunctionAddress, FunctionOffset;
1146  ErrorOr<SymbolRef> Function = getSymbolForLocation(
1147      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1148      /*FunctionOnly=*/true);
1149
1150  uint64_t XDataAddress, XDataOffset;
1151  ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation(
1152      COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress,
1153      XDataOffset);
1154
1155  if (!RF.BeginAddress && !Function)
1156    return false;
1157  if (!RF.UnwindData && !XDataRecord)
1158    return false;
1159
1160  StringRef FunctionName;
1161  if (Function) {
1162    Expected<StringRef> FunctionNameOrErr = Function->getName();
1163    if (!FunctionNameOrErr) {
1164      std::string Buf;
1165      llvm::raw_string_ostream OS(Buf);
1166      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1167      report_fatal_error(Twine(OS.str()));
1168    }
1169    FunctionName = *FunctionNameOrErr;
1170  }
1171
1172  SW.printString("Function",
1173                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1174
1175  if (XDataRecord) {
1176    Expected<StringRef> Name = XDataRecord->getName();
1177    if (!Name) {
1178      std::string Buf;
1179      llvm::raw_string_ostream OS(Buf);
1180      logAllUnhandledErrors(Name.takeError(), OS);
1181      report_fatal_error(Twine(OS.str()));
1182    }
1183
1184    SW.printString("ExceptionRecord",
1185                   formatSymbol(*Name, XDataAddress, XDataOffset));
1186
1187    Expected<section_iterator> SIOrErr = XDataRecord->getSection();
1188    if (!SIOrErr) {
1189      // TODO: Actually report errors helpfully.
1190      consumeError(SIOrErr.takeError());
1191      return false;
1192    }
1193    section_iterator SI = *SIOrErr;
1194
1195    return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress);
1196  } else {
1197    SW.printString("ExceptionRecord", formatSymbol("", XDataAddress));
1198
1199    ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress);
1200    if (!Section)
1201      return false;
1202
1203    return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress);
1204  }
1205}
1206
1207bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
1208                              const SectionRef Section, uint64_t Offset,
1209                              unsigned Index, const RuntimeFunction &RF) {
1210  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
1211          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
1212         "unpacked entry cannot be treated as a packed entry");
1213
1214  uint64_t FunctionAddress, FunctionOffset;
1215  ErrorOr<SymbolRef> Function = getSymbolForLocation(
1216      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1217      /*FunctionOnly=*/true);
1218
1219  StringRef FunctionName;
1220  if (Function) {
1221    Expected<StringRef> FunctionNameOrErr = Function->getName();
1222    if (!FunctionNameOrErr) {
1223      std::string Buf;
1224      llvm::raw_string_ostream OS(Buf);
1225      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1226      report_fatal_error(Twine(OS.str()));
1227    }
1228    FunctionName = *FunctionNameOrErr;
1229  }
1230
1231  SW.printString("Function",
1232                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1233  SW.printBoolean("Fragment",
1234                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
1235  SW.printNumber("FunctionLength", RF.FunctionLength());
1236  SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
1237  SW.printBoolean("HomedParameters", RF.H());
1238  SW.printNumber("Reg", RF.Reg());
1239  SW.printNumber("R", RF.R());
1240  SW.printBoolean("LinkRegister", RF.L());
1241  SW.printBoolean("Chaining", RF.C());
1242  SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
1243
1244  {
1245    ListScope PS(SW, "Prologue");
1246
1247    uint16_t GPRMask, VFPMask;
1248    std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/true);
1249
1250    if (StackAdjustment(RF) && !PrologueFolding(RF))
1251      SW.startLine() << "sub sp, sp, #" << StackAdjustment(RF) * 4 << "\n";
1252    if (VFPMask) {
1253      SW.startLine() << "vpush ";
1254      printVFPMask(VFPMask);
1255      OS << "\n";
1256    }
1257    if (RF.C()) {
1258      // Count the number of registers pushed below R11
1259      int FpOffset = 4 * llvm::popcount(GPRMask & ((1U << 11) - 1));
1260      if (FpOffset)
1261        SW.startLine() << "add.w r11, sp, #" << FpOffset << "\n";
1262      else
1263        SW.startLine() << "mov r11, sp\n";
1264    }
1265    if (GPRMask) {
1266      SW.startLine() << "push ";
1267      printGPRMask(GPRMask);
1268      OS << "\n";
1269    }
1270    if (RF.H())
1271      SW.startLine() << "push {r0-r3}\n";
1272  }
1273
1274  if (RF.Ret() != ReturnType::RT_NoEpilogue) {
1275    ListScope PS(SW, "Epilogue");
1276
1277    uint16_t GPRMask, VFPMask;
1278    std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/false);
1279
1280    if (StackAdjustment(RF) && !EpilogueFolding(RF))
1281      SW.startLine() << "add sp, sp, #" << StackAdjustment(RF) * 4 << "\n";
1282    if (VFPMask) {
1283      SW.startLine() << "vpop ";
1284      printVFPMask(VFPMask);
1285      OS << "\n";
1286    }
1287    if (GPRMask) {
1288      SW.startLine() << "pop ";
1289      printGPRMask(GPRMask);
1290      OS << "\n";
1291    }
1292    if (RF.H()) {
1293      if (RF.L() == 0 || RF.Ret() != ReturnType::RT_POP)
1294        SW.startLine() << "add sp, sp, #16\n";
1295      else
1296        SW.startLine() << "ldr pc, [sp], #20\n";
1297    }
1298    if (RF.Ret() != ReturnType::RT_POP)
1299      SW.startLine() << RF.Ret() << '\n';
1300  }
1301
1302  return true;
1303}
1304
1305bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
1306                                   const SectionRef Section, uint64_t Offset,
1307                                   unsigned Index,
1308                                   const RuntimeFunctionARM64 &RF) {
1309  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
1310          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
1311         "unpacked entry cannot be treated as a packed entry");
1312
1313  uint64_t FunctionAddress, FunctionOffset;
1314  ErrorOr<SymbolRef> Function = getSymbolForLocation(
1315      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1316      /*FunctionOnly=*/true);
1317
1318  StringRef FunctionName;
1319  if (Function) {
1320    Expected<StringRef> FunctionNameOrErr = Function->getName();
1321    if (!FunctionNameOrErr) {
1322      std::string Buf;
1323      llvm::raw_string_ostream OS(Buf);
1324      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1325      report_fatal_error(Twine(OS.str()));
1326    }
1327    FunctionName = *FunctionNameOrErr;
1328  }
1329
1330  SW.printString("Function",
1331                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1332  SW.printBoolean("Fragment",
1333                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
1334  SW.printNumber("FunctionLength", RF.FunctionLength());
1335  SW.printNumber("RegF", RF.RegF());
1336  SW.printNumber("RegI", RF.RegI());
1337  SW.printBoolean("HomedParameters", RF.H());
1338  SW.printNumber("CR", RF.CR());
1339  SW.printNumber("FrameSize", RF.FrameSize() << 4);
1340  ListScope PS(SW, "Prologue");
1341
1342  // Synthesize the equivalent prologue according to the documentation
1343  // at https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling,
1344  // printed in reverse order compared to the docs, to match how prologues
1345  // are printed for the non-packed case.
1346  int IntSZ = 8 * RF.RegI();
1347  if (RF.CR() == 1)
1348    IntSZ += 8;
1349  int FpSZ = 8 * RF.RegF();
1350  if (RF.RegF())
1351    FpSZ += 8;
1352  int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf;
1353  int LocSZ = (RF.FrameSize() << 4) - SavSZ;
1354
1355  if (RF.CR() == 2 || RF.CR() == 3) {
1356    SW.startLine() << "mov x29, sp\n";
1357    if (LocSZ <= 512) {
1358      SW.startLine() << format("stp x29, lr, [sp, #-%d]!\n", LocSZ);
1359    } else {
1360      SW.startLine() << "stp x29, lr, [sp, #0]\n";
1361    }
1362  }
1363  if (LocSZ > 4080) {
1364    SW.startLine() << format("sub sp, sp, #%d\n", LocSZ - 4080);
1365    SW.startLine() << "sub sp, sp, #4080\n";
1366  } else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) {
1367    SW.startLine() << format("sub sp, sp, #%d\n", LocSZ);
1368  }
1369  if (RF.H()) {
1370    SW.startLine() << format("stp x6, x7, [sp, #%d]\n", SavSZ - 16);
1371    SW.startLine() << format("stp x4, x5, [sp, #%d]\n", SavSZ - 32);
1372    SW.startLine() << format("stp x2, x3, [sp, #%d]\n", SavSZ - 48);
1373    if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) {
1374      SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64);
1375    } else {
1376      // This case isn't documented; if neither RegI nor RegF nor CR=1
1377      // have decremented the stack pointer by SavSZ, we need to do it here
1378      // (as the final stack adjustment of LocSZ excludes SavSZ).
1379      SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ);
1380    }
1381  }
1382  int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0;
1383  for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) {
1384    if (I == (FloatRegs + 1) / 2 - 1 && FloatRegs % 2 == 1) {
1385      // The last register, an odd register without a pair
1386      SW.startLine() << format("str d%d, [sp, #%d]\n", 8 + 2 * I,
1387                               IntSZ + 16 * I);
1388    } else if (I == 0 && RF.RegI() == 0 && RF.CR() != 1) {
1389      SW.startLine() << format("stp d%d, d%d, [sp, #-%d]!\n", 8 + 2 * I,
1390                               8 + 2 * I + 1, SavSZ);
1391    } else {
1392      SW.startLine() << format("stp d%d, d%d, [sp, #%d]\n", 8 + 2 * I,
1393                               8 + 2 * I + 1, IntSZ + 16 * I);
1394    }
1395  }
1396  if (RF.CR() == 1 && (RF.RegI() % 2) == 0) {
1397    if (RF.RegI() == 0)
1398      SW.startLine() << format("str lr, [sp, #-%d]!\n", SavSZ);
1399    else
1400      SW.startLine() << format("str lr, [sp, #%d]\n", IntSZ - 8);
1401  }
1402  for (int I = (RF.RegI() + 1) / 2 - 1; I >= 0; I--) {
1403    if (I == (RF.RegI() + 1) / 2 - 1 && RF.RegI() % 2 == 1) {
1404      // The last register, an odd register without a pair
1405      if (RF.CR() == 1) {
1406        if (I == 0) { // If this is the only register pair
1407          // CR=1 combined with RegI=1 doesn't map to a documented case;
1408          // it doesn't map to any regular unwind info opcode, and the
1409          // actual unwinder doesn't support it.
1410          SW.startLine() << "INVALID!\n";
1411        } else
1412          SW.startLine() << format("stp x%d, lr, [sp, #%d]\n", 19 + 2 * I,
1413                                   16 * I);
1414      } else {
1415        if (I == 0)
1416          SW.startLine() << format("str x%d, [sp, #-%d]!\n", 19 + 2 * I, SavSZ);
1417        else
1418          SW.startLine() << format("str x%d, [sp, #%d]\n", 19 + 2 * I, 16 * I);
1419      }
1420    } else if (I == 0) {
1421      // The first register pair
1422      SW.startLine() << format("stp x19, x20, [sp, #-%d]!\n", SavSZ);
1423    } else {
1424      SW.startLine() << format("stp x%d, x%d, [sp, #%d]\n", 19 + 2 * I,
1425                               19 + 2 * I + 1, 16 * I);
1426    }
1427  }
1428  // CR=2 is yet undocumented, see
1429  // https://github.com/MicrosoftDocs/cpp-docs/pull/4202 for upstream
1430  // progress on getting it documented.
1431  if (RF.CR() == 2)
1432    SW.startLine() << "pacibsp\n";
1433  SW.startLine() << "end\n";
1434
1435  return true;
1436}
1437
1438bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,
1439                                     const SectionRef Section, unsigned Index,
1440                                     ArrayRef<uint8_t> Contents) {
1441  uint64_t Offset = PDataEntrySize * Index;
1442  const ulittle32_t *Data =
1443    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
1444
1445  const RuntimeFunction Entry(Data);
1446  DictScope RFS(SW, "RuntimeFunction");
1447  if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)
1448    return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);
1449  if (isAArch64) {
1450    const RuntimeFunctionARM64 EntryARM64(Data);
1451    return dumpPackedARM64Entry(COFF, Section, Offset, Index, EntryARM64);
1452  }
1453  return dumpPackedEntry(COFF, Section, Offset, Index, Entry);
1454}
1455
1456void Decoder::dumpProcedureData(const COFFObjectFile &COFF,
1457                                const SectionRef Section) {
1458  ArrayRef<uint8_t> Contents;
1459  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
1460    return;
1461
1462  if (Contents.size() % PDataEntrySize) {
1463    errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n";
1464    return;
1465  }
1466
1467  for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI)
1468    if (!dumpProcedureDataEntry(COFF, Section, EI, Contents))
1469      break;
1470}
1471
1472Error Decoder::dumpProcedureData(const COFFObjectFile &COFF) {
1473  for (const auto &Section : COFF.sections()) {
1474    Expected<StringRef> NameOrErr =
1475        COFF.getSectionName(COFF.getCOFFSection(Section));
1476    if (!NameOrErr)
1477      return NameOrErr.takeError();
1478
1479    if (NameOrErr->starts_with(".pdata"))
1480      dumpProcedureData(COFF, Section);
1481  }
1482  return Error::success();
1483}
1484}
1485}
1486}
1487