xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp (revision 38a52bd3b5cac3da6f7f6eef3dd050e6aa08ebb3)
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 
70 using namespace llvm;
71 using namespace llvm::object;
72 using namespace llvm::support;
73 
74 namespace llvm {
75 raw_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 
94 static 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 
112 namespace llvm {
113 namespace ARM {
114 namespace WinEH {
115 const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);
116 
117 // TODO name the uops more appropriately
118 const 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
149 const 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 
177 void 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 
200 ErrorOr<object::SectionRef>
201 Decoder::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 
212 ErrorOr<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 
230 ErrorOr<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 
241 SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF, SymbolRef Sym,
242                                       uint64_t &SymbolOffset) {
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       CoffSym.getSectionDefinition() == nullptr)
248     return Sym;
249   for (const auto &S : COFF.symbols()) {
250     COFFSymbolRef CS = COFF.getCOFFSymbol(S);
251     if (CS.getSectionNumber() == CoffSym.getSectionNumber() &&
252         CS.getValue() <= CoffSym.getValue() + SymbolOffset &&
253         CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL &&
254         CS.getSectionDefinition() == nullptr) {
255       uint32_t Offset = CoffSym.getValue() + SymbolOffset - CS.getValue();
256       if (Offset <= SymbolOffset) {
257         SymbolOffset = Offset;
258         Sym = S;
259         CoffSym = CS;
260         if (CS.isExternal() && SymbolOffset == 0)
261           return Sym;
262       }
263     }
264   }
265   return Sym;
266 }
267 
268 ErrorOr<SymbolRef> Decoder::getSymbolForLocation(
269     const COFFObjectFile &COFF, const SectionRef &Section,
270     uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress,
271     uint64_t &SymbolOffset, bool FunctionOnly) {
272   // Try to locate a relocation that points at the offset in the section
273   ErrorOr<SymbolRef> SymOrErr =
274       getRelocatedSymbol(COFF, Section, OffsetInSection);
275   if (SymOrErr) {
276     // We found a relocation symbol; the immediate offset needs to be added
277     // to the symbol address.
278     SymbolOffset = ImmediateOffset;
279 
280     Expected<uint64_t> AddressOrErr = SymOrErr->getAddress();
281     if (!AddressOrErr) {
282       std::string Buf;
283       llvm::raw_string_ostream OS(Buf);
284       logAllUnhandledErrors(AddressOrErr.takeError(), OS);
285       report_fatal_error(Twine(OS.str()));
286     }
287     // We apply SymbolOffset here directly. We return it separately to allow
288     // the caller to print it as an offset on the symbol name.
289     SymbolAddress = *AddressOrErr + SymbolOffset;
290 
291     if (FunctionOnly) // Resolve label/section symbols into function names.
292       SymOrErr = getPreferredSymbol(COFF, *SymOrErr, SymbolOffset);
293   } else {
294     // No matching relocation found; operating on a linked image. Try to
295     // find a descriptive symbol if possible. The immediate offset contains
296     // the image relative address, and we shouldn't add any offset to the
297     // symbol.
298     SymbolAddress = COFF.getImageBase() + ImmediateOffset;
299     SymbolOffset = 0;
300     SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly);
301   }
302   return SymOrErr;
303 }
304 
305 bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset,
306                               unsigned Length, bool Prologue) {
307   uint8_t Imm = OC[Offset] & 0x7f;
308   SW.startLine() << format("0x%02x                ; %s sp, #(%u * 4)\n",
309                            OC[Offset],
310                            static_cast<const char *>(Prologue ? "sub" : "add"),
311                            Imm);
312   ++Offset;
313   return false;
314 }
315 
316 bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset,
317                               unsigned Length, bool Prologue) {
318   unsigned Link = (OC[Offset] & 0x20) >> 5;
319   uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))
320                         | ((OC[Offset + 0] & 0x1f) << 8)
321                         | ((OC[Offset + 1] & 0xff) << 0);
322   assert((~RegisterMask & (1 << 13)) && "sp must not be set");
323   assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");
324 
325   SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",
326                            OC[Offset + 0], OC[Offset + 1],
327                            Prologue ? "push" : "pop");
328   printRegisters(std::make_pair(RegisterMask, 0));
329   OS << '\n';
330 
331   Offset += 2;
332   return false;
333 }
334 
335 bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset,
336                               unsigned Length, bool Prologue) {
337   if (Prologue)
338     SW.startLine() << format("0x%02x                ; mov r%u, sp\n",
339                              OC[Offset], OC[Offset] & 0xf);
340   else
341     SW.startLine() << format("0x%02x                ; mov sp, r%u\n",
342                              OC[Offset], OC[Offset] & 0xf);
343   ++Offset;
344   return false;
345 }
346 
347 bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset,
348                               unsigned Length, bool Prologue) {
349   unsigned Link = (OC[Offset] & 0x4) >> 3;
350   unsigned Count = (OC[Offset] & 0x3);
351 
352   uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
353                    | (((1 << (Count + 1)) - 1) << 4);
354 
355   SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
356                            Prologue ? "push" : "pop");
357   printRegisters(std::make_pair(GPRMask, 0));
358   OS << '\n';
359 
360   ++Offset;
361   return false;
362 }
363 
364 bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset,
365                               unsigned Length, bool Prologue) {
366   unsigned Link = (OC[Offset] & 0x4) >> 2;
367   unsigned Count = (OC[Offset] & 0x3) + 4;
368 
369   uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
370                    | (((1 << (Count + 1)) - 1) << 4);
371 
372   SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],
373                            Prologue ? "push" : "pop");
374   printRegisters(std::make_pair(GPRMask, 0));
375   OS << '\n';
376 
377   ++Offset;
378   return false;
379 }
380 
381 bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset,
382                               unsigned Length, bool Prologue) {
383   unsigned High = (OC[Offset] & 0x7);
384   uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);
385 
386   SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
387                            Prologue ? "vpush" : "vpop");
388   printRegisters(std::make_pair(0, VFPMask));
389   OS << '\n';
390 
391   ++Offset;
392   return false;
393 }
394 
395 bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset,
396                               unsigned Length, bool Prologue) {
397   uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);
398 
399   SW.startLine() << format("0x%02x 0x%02x           ; %s.w sp, #(%u * 4)\n",
400                            OC[Offset + 0], OC[Offset + 1],
401                            static_cast<const char *>(Prologue ? "sub" : "add"),
402                            Imm);
403 
404   Offset += 2;
405   return false;
406 }
407 
408 bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset,
409                               unsigned Length, bool Prologue) {
410   uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))
411                   | ((OC[Offset + 1] & 0xff) << 0);
412 
413   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
414                            OC[Offset + 1], Prologue ? "push" : "pop");
415   printRegisters(std::make_pair(GPRMask, 0));
416   OS << '\n';
417 
418   Offset += 2;
419   return false;
420 }
421 
422 bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset,
423                               unsigned Length, bool Prologue) {
424   assert(!Prologue && "may not be used in prologue");
425 
426   if (OC[Offset + 1] & 0xf0)
427     SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
428                              OC[Offset + 0], OC[Offset +  1]);
429   else
430     SW.startLine()
431       << format("0x%02x 0x%02x           ; microsoft-specific (type: %u)\n",
432                 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);
433 
434   Offset += 2;
435   return false;
436 }
437 
438 bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset,
439                               unsigned Length, bool Prologue) {
440   assert(!Prologue && "may not be used in prologue");
441 
442   if (OC[Offset + 1] & 0xf0)
443     SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
444                              OC[Offset + 0], OC[Offset +  1]);
445   else
446     SW.startLine()
447       << format("0x%02x 0x%02x           ; ldr.w lr, [sp], #%u\n",
448                 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
449 
450   Offset += 2;
451   return false;
452 }
453 
454 bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset,
455                               unsigned Length, bool Prologue) {
456   unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
457   unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
458   uint32_t VFPMask = ((1 << (End - Start)) - 1) << Start;
459 
460   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
461                            OC[Offset + 1], Prologue ? "vpush" : "vpop");
462   printRegisters(std::make_pair(0, VFPMask));
463   OS << '\n';
464 
465   Offset += 2;
466   return false;
467 }
468 
469 bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset,
470                               unsigned Length, bool Prologue) {
471   unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
472   unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
473   uint32_t VFPMask = ((1 << (End - Start)) - 1) << 16;
474 
475   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
476                            OC[Offset + 1], Prologue ? "vpush" : "vpop");
477   printRegisters(std::make_pair(0, VFPMask));
478   OS << '\n';
479 
480   Offset += 2;
481   return false;
482 }
483 
484 bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset,
485                               unsigned Length, bool Prologue) {
486   uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
487 
488   SW.startLine() << format("0x%02x 0x%02x 0x%02x      ; %s sp, sp, #(%u * 4)\n",
489                            OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
490                            static_cast<const char *>(Prologue ? "sub" : "add"),
491                            Imm);
492 
493   Offset += 3;
494   return false;
495 }
496 
497 bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset,
498                               unsigned Length, bool Prologue) {
499   uint32_t Imm = (OC[Offset + 1] << 16)
500                | (OC[Offset + 2] << 8)
501                | (OC[Offset + 3] << 0);
502 
503   SW.startLine()
504     << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
505               OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
506               static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
507 
508   Offset += 4;
509   return false;
510 }
511 
512 bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset,
513                               unsigned Length, bool Prologue) {
514   uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
515 
516   SW.startLine()
517     << format("0x%02x 0x%02x 0x%02x      ; %s.w sp, sp, #(%u * 4)\n",
518               OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
519               static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
520 
521   Offset += 3;
522   return false;
523 }
524 
525 bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset,
526                               unsigned Length, bool Prologue) {
527   uint32_t Imm = (OC[Offset + 1] << 16)
528                | (OC[Offset + 2] << 8)
529                | (OC[Offset + 3] << 0);
530 
531   SW.startLine()
532     << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
533               OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
534               static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
535 
536   Offset += 4;
537   return false;
538 }
539 
540 bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset,
541                               unsigned Length, bool Prologue) {
542   SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
543   ++Offset;
544   return false;
545 }
546 
547 bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset,
548                               unsigned Length, bool Prologue) {
549   SW.startLine() << format("0x%02x                ; nop.w\n", OC[Offset]);
550   ++Offset;
551   return false;
552 }
553 
554 bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset,
555                               unsigned Length, bool Prologue) {
556   SW.startLine() << format("0x%02x                ; b\n", OC[Offset]);
557   ++Offset;
558   return true;
559 }
560 
561 bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset,
562                               unsigned Length, bool Prologue) {
563   SW.startLine() << format("0x%02x                ; b.w\n", OC[Offset]);
564   ++Offset;
565   return true;
566 }
567 
568 bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset,
569                               unsigned Length, bool Prologue) {
570   ++Offset;
571   return true;
572 }
573 
574 // ARM64 unwind codes start here.
575 bool Decoder::opcode_alloc_s(const uint8_t *OC, unsigned &Offset,
576                              unsigned Length, bool Prologue) {
577   uint32_t NumBytes = (OC[Offset] & 0x1F) << 4;
578   SW.startLine() << format("0x%02x                ; %s sp, #%u\n", OC[Offset],
579                            static_cast<const char *>(Prologue ? "sub" : "add"),
580                            NumBytes);
581   ++Offset;
582   return false;
583 }
584 
585 bool Decoder::opcode_save_r19r20_x(const uint8_t *OC, unsigned &Offset,
586                                    unsigned Length, bool Prologue) {
587   uint32_t Off = (OC[Offset] & 0x1F) << 3;
588   if (Prologue)
589     SW.startLine() << format(
590         "0x%02x                ; stp x19, x20, [sp, #-%u]!\n", OC[Offset], Off);
591   else
592     SW.startLine() << format(
593         "0x%02x                ; ldp x19, x20, [sp], #%u\n", OC[Offset], Off);
594   ++Offset;
595   return false;
596 }
597 
598 bool Decoder::opcode_save_fplr(const uint8_t *OC, unsigned &Offset,
599                                unsigned Length, bool Prologue) {
600   uint32_t Off = (OC[Offset] & 0x3F) << 3;
601   SW.startLine() << format(
602       "0x%02x                ; %s x29, x30, [sp, #%u]\n", OC[Offset],
603       static_cast<const char *>(Prologue ? "stp" : "ldp"), Off);
604   ++Offset;
605   return false;
606 }
607 
608 bool Decoder::opcode_save_fplr_x(const uint8_t *OC, unsigned &Offset,
609                                  unsigned Length, bool Prologue) {
610   uint32_t Off = ((OC[Offset] & 0x3F) + 1) << 3;
611   if (Prologue)
612     SW.startLine() << format(
613         "0x%02x                ; stp x29, x30, [sp, #-%u]!\n", OC[Offset], Off);
614   else
615     SW.startLine() << format(
616         "0x%02x                ; ldp x29, x30, [sp], #%u\n", OC[Offset], Off);
617   ++Offset;
618   return false;
619 }
620 
621 bool Decoder::opcode_alloc_m(const uint8_t *OC, unsigned &Offset,
622                              unsigned Length, bool Prologue) {
623   uint32_t NumBytes = ((OC[Offset] & 0x07) << 8);
624   NumBytes |= (OC[Offset + 1] & 0xFF);
625   NumBytes <<= 4;
626   SW.startLine() << format("0x%02x%02x              ; %s sp, #%u\n",
627                            OC[Offset], OC[Offset + 1],
628                            static_cast<const char *>(Prologue ? "sub" : "add"),
629                            NumBytes);
630   Offset += 2;
631   return false;
632 }
633 
634 bool Decoder::opcode_save_regp(const uint8_t *OC, unsigned &Offset,
635                                unsigned Length, bool Prologue) {
636   uint32_t Reg = ((OC[Offset] & 0x03) << 8);
637   Reg |= (OC[Offset + 1] & 0xC0);
638   Reg >>= 6;
639   Reg += 19;
640   uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
641   SW.startLine() << format(
642       "0x%02x%02x              ; %s x%u, x%u, [sp, #%u]\n",
643       OC[Offset], OC[Offset + 1],
644       static_cast<const char *>(Prologue ? "stp" : "ldp"), Reg, Reg + 1, Off);
645   Offset += 2;
646   return false;
647 }
648 
649 bool Decoder::opcode_save_regp_x(const uint8_t *OC, unsigned &Offset,
650                                  unsigned Length, bool Prologue) {
651   uint32_t Reg = ((OC[Offset] & 0x03) << 8);
652   Reg |= (OC[Offset + 1] & 0xC0);
653   Reg >>= 6;
654   Reg += 19;
655   uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;
656   if (Prologue)
657     SW.startLine() << format(
658         "0x%02x%02x              ; stp x%u, x%u, [sp, #-%u]!\n",
659         OC[Offset], OC[Offset + 1], Reg,
660         Reg + 1, Off);
661   else
662     SW.startLine() << format(
663         "0x%02x%02x              ; ldp x%u, x%u, [sp], #%u\n",
664         OC[Offset], OC[Offset + 1], Reg,
665         Reg + 1, Off);
666   Offset += 2;
667   return false;
668 }
669 
670 bool Decoder::opcode_save_reg(const uint8_t *OC, unsigned &Offset,
671                               unsigned Length, bool Prologue) {
672   uint32_t Reg = (OC[Offset] & 0x03) << 8;
673   Reg |= (OC[Offset + 1] & 0xC0);
674   Reg >>= 6;
675   Reg += 19;
676   uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
677   SW.startLine() << format("0x%02x%02x              ; %s x%u, [sp, #%u]\n",
678                            OC[Offset], OC[Offset + 1],
679                            static_cast<const char *>(Prologue ? "str" : "ldr"),
680                            Reg, Off);
681   Offset += 2;
682   return false;
683 }
684 
685 bool Decoder::opcode_save_reg_x(const uint8_t *OC, unsigned &Offset,
686                                 unsigned Length, bool Prologue) {
687   uint32_t Reg = (OC[Offset] & 0x01) << 8;
688   Reg |= (OC[Offset + 1] & 0xE0);
689   Reg >>= 5;
690   Reg += 19;
691   uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;
692   if (Prologue)
693     SW.startLine() << format("0x%02x%02x              ; str x%u, [sp, #-%u]!\n",
694                              OC[Offset], OC[Offset + 1], Reg, Off);
695   else
696     SW.startLine() << format("0x%02x%02x              ; ldr x%u, [sp], #%u\n",
697                              OC[Offset], OC[Offset + 1], Reg, Off);
698   Offset += 2;
699   return false;
700 }
701 
702 bool Decoder::opcode_save_lrpair(const uint8_t *OC, unsigned &Offset,
703                                  unsigned Length, bool Prologue) {
704   uint32_t Reg = (OC[Offset] & 0x01) << 8;
705   Reg |= (OC[Offset + 1] & 0xC0);
706   Reg >>= 6;
707   Reg *= 2;
708   Reg += 19;
709   uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
710   SW.startLine() << format("0x%02x%02x              ; %s x%u, lr, [sp, #%u]\n",
711                            OC[Offset], OC[Offset + 1],
712                            static_cast<const char *>(Prologue ? "stp" : "ldp"),
713                            Reg, Off);
714   Offset += 2;
715   return false;
716 }
717 
718 bool Decoder::opcode_save_fregp(const uint8_t *OC, unsigned &Offset,
719                                 unsigned Length, bool Prologue) {
720   uint32_t Reg = (OC[Offset] & 0x01) << 8;
721   Reg |= (OC[Offset + 1] & 0xC0);
722   Reg >>= 6;
723   Reg += 8;
724   uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
725   SW.startLine() << format("0x%02x%02x              ; %s d%u, d%u, [sp, #%u]\n",
726                            OC[Offset], OC[Offset + 1],
727                            static_cast<const char *>(Prologue ? "stp" : "ldp"),
728                            Reg, Reg + 1, Off);
729   Offset += 2;
730   return false;
731 }
732 
733 bool Decoder::opcode_save_fregp_x(const uint8_t *OC, unsigned &Offset,
734                                   unsigned Length, bool Prologue) {
735   uint32_t Reg = (OC[Offset] & 0x01) << 8;
736   Reg |= (OC[Offset + 1] & 0xC0);
737   Reg >>= 6;
738   Reg += 8;
739   uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;
740   if (Prologue)
741     SW.startLine() << format(
742         "0x%02x%02x              ; stp d%u, d%u, [sp, #-%u]!\n", OC[Offset],
743         OC[Offset + 1], Reg, Reg + 1, Off);
744   else
745     SW.startLine() << format(
746         "0x%02x%02x              ; ldp d%u, d%u, [sp], #%u\n", OC[Offset],
747         OC[Offset + 1], Reg, Reg + 1, Off);
748   Offset += 2;
749   return false;
750 }
751 
752 bool Decoder::opcode_save_freg(const uint8_t *OC, unsigned &Offset,
753                                unsigned Length, bool Prologue) {
754   uint32_t Reg = (OC[Offset] & 0x01) << 8;
755   Reg |= (OC[Offset + 1] & 0xC0);
756   Reg >>= 6;
757   Reg += 8;
758   uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;
759   SW.startLine() << format("0x%02x%02x              ; %s d%u, [sp, #%u]\n",
760                            OC[Offset], OC[Offset + 1],
761                            static_cast<const char *>(Prologue ? "str" : "ldr"),
762                            Reg, Off);
763   Offset += 2;
764   return false;
765 }
766 
767 bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset,
768                                  unsigned Length, bool Prologue) {
769   uint32_t Reg = ((OC[Offset + 1] & 0xE0) >> 5) + 8;
770   uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;
771   if (Prologue)
772     SW.startLine() << format(
773         "0x%02x%02x              ; str d%u, [sp, #-%u]!\n", OC[Offset],
774         OC[Offset + 1], Reg, Off);
775   else
776     SW.startLine() << format(
777         "0x%02x%02x              ; ldr d%u, [sp], #%u\n", OC[Offset],
778         OC[Offset + 1], Reg, Off);
779   Offset += 2;
780   return false;
781 }
782 
783 bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset,
784                              unsigned Length, bool Prologue) {
785   unsigned Off =
786       (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) | (OC[Offset + 3] << 0);
787   Off <<= 4;
788   SW.startLine() << format(
789       "0x%02x%02x%02x%02x          ; %s sp, #%u\n", OC[Offset], OC[Offset + 1],
790       OC[Offset + 2], OC[Offset + 3],
791       static_cast<const char *>(Prologue ? "sub" : "add"), Off);
792   Offset += 4;
793   return false;
794 }
795 
796 bool Decoder::opcode_setfp(const uint8_t *OC, unsigned &Offset, unsigned Length,
797                            bool Prologue) {
798   SW.startLine() << format("0x%02x                ; mov %s, %s\n", OC[Offset],
799                            static_cast<const char *>(Prologue ? "fp" : "sp"),
800                            static_cast<const char *>(Prologue ? "sp" : "fp"));
801   ++Offset;
802   return false;
803 }
804 
805 bool Decoder::opcode_addfp(const uint8_t *OC, unsigned &Offset, unsigned Length,
806                            bool Prologue) {
807   unsigned NumBytes = OC[Offset + 1] << 3;
808   SW.startLine() << format(
809       "0x%02x%02x              ; %s %s, %s, #%u\n", OC[Offset], OC[Offset + 1],
810       static_cast<const char *>(Prologue ? "add" : "sub"),
811       static_cast<const char *>(Prologue ? "fp" : "sp"),
812       static_cast<const char *>(Prologue ? "sp" : "fp"), NumBytes);
813   Offset += 2;
814   return false;
815 }
816 
817 bool Decoder::opcode_nop(const uint8_t *OC, unsigned &Offset, unsigned Length,
818                          bool Prologue) {
819   SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
820   ++Offset;
821   return false;
822 }
823 
824 bool Decoder::opcode_end(const uint8_t *OC, unsigned &Offset, unsigned Length,
825                          bool Prologue) {
826   SW.startLine() << format("0x%02x                ; end\n", OC[Offset]);
827   ++Offset;
828   return true;
829 }
830 
831 bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length,
832                            bool Prologue) {
833   SW.startLine() << format("0x%02x                ; end_c\n", OC[Offset]);
834   ++Offset;
835   return true;
836 }
837 
838 bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,
839                                unsigned Length, bool Prologue) {
840   if (Prologue)
841     SW.startLine() << format("0x%02x                ; save next\n", OC[Offset]);
842   else
843     SW.startLine() << format("0x%02x                ; restore next\n",
844                              OC[Offset]);
845   ++Offset;
846   return false;
847 }
848 
849 bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset,
850                                 unsigned Length, bool Prologue) {
851   SW.startLine() << format("0x%02x                ; trap frame\n", OC[Offset]);
852   ++Offset;
853   return false;
854 }
855 
856 bool Decoder::opcode_machine_frame(const uint8_t *OC, unsigned &Offset,
857                                    unsigned Length, bool Prologue) {
858   SW.startLine() << format("0x%02x                ; machine frame\n",
859                            OC[Offset]);
860   ++Offset;
861   return false;
862 }
863 
864 bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset,
865                              unsigned Length, bool Prologue) {
866   SW.startLine() << format("0x%02x                ; context\n", OC[Offset]);
867   ++Offset;
868   return false;
869 }
870 
871 bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset,
872                                            unsigned Length, bool Prologue) {
873   SW.startLine() << format("0x%02x                ; clear unwound to call\n",
874                            OC[Offset]);
875   ++Offset;
876   return false;
877 }
878 
879 void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
880                             bool Prologue) {
881   assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
882   const RingEntry* DecodeRing = isAArch64 ? Ring64 : Ring;
883   bool Terminated = false;
884   for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
885     for (unsigned DI = 0;; ++DI) {
886       if ((isAArch64 && (DI >= array_lengthof(Ring64))) ||
887           (!isAArch64 && (DI >= array_lengthof(Ring)))) {
888         SW.startLine() << format("0x%02x                ; Bad opcode!\n",
889                                  Opcodes.data()[OI]);
890         ++OI;
891         break;
892       }
893 
894       if ((Opcodes[OI] & DecodeRing[DI].Mask) == DecodeRing[DI].Value) {
895         if (OI + DecodeRing[DI].Length > OE) {
896           SW.startLine() << format("Opcode 0x%02x goes past the unwind data\n",
897                                     Opcodes[OI]);
898           OI += DecodeRing[DI].Length;
899           break;
900         }
901         Terminated =
902             (this->*DecodeRing[DI].Routine)(Opcodes.data(), OI, 0, Prologue);
903         break;
904       }
905     }
906   }
907 }
908 
909 bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
910                               const SectionRef &Section,
911                               uint64_t FunctionAddress, uint64_t VA) {
912   ArrayRef<uint8_t> Contents;
913   if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
914     return false;
915 
916   uint64_t SectionVA = Section.getAddress();
917   uint64_t Offset = VA - SectionVA;
918   const ulittle32_t *Data =
919     reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
920 
921   // Sanity check to ensure that the .xdata header is present.
922   // A header is one or two words, followed by at least one word to describe
923   // the unwind codes. Applicable to both ARM and AArch64.
924   if (Contents.size() - Offset < 8)
925     report_fatal_error(".xdata must be at least 8 bytes in size");
926 
927   const ExceptionDataRecord XData(Data, isAArch64);
928   DictScope XRS(SW, "ExceptionData");
929   SW.printNumber("FunctionLength",
930                  isAArch64 ? XData.FunctionLengthInBytesAArch64() :
931                  XData.FunctionLengthInBytesARM());
932   SW.printNumber("Version", XData.Vers());
933   SW.printBoolean("ExceptionData", XData.X());
934   SW.printBoolean("EpiloguePacked", XData.E());
935   if (!isAArch64)
936     SW.printBoolean("Fragment", XData.F());
937   SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",
938                  XData.EpilogueCount());
939   uint64_t ByteCodeLength = XData.CodeWords() * sizeof(uint32_t);
940   SW.printNumber("ByteCodeLength", ByteCodeLength);
941 
942   if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) -
943                 (XData.E() ? 0 : XData.EpilogueCount() * 4) -
944                 (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) {
945     SW.flush();
946     report_fatal_error("Malformed unwind data");
947   }
948 
949   if (XData.E()) {
950     ArrayRef<uint8_t> UC = XData.UnwindByteCode();
951     if (isAArch64 || !XData.F()) {
952       ListScope PS(SW, "Prologue");
953       decodeOpcodes(UC, 0, /*Prologue=*/true);
954     }
955     if (XData.EpilogueCount()) {
956       ListScope ES(SW, "Epilogue");
957       decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);
958     }
959   } else {
960     {
961       ListScope PS(SW, "Prologue");
962       decodeOpcodes(XData.UnwindByteCode(), 0, /*Prologue=*/true);
963     }
964     ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes();
965     ListScope ESS(SW, "EpilogueScopes");
966     for (const EpilogueScope ES : EpilogueScopes) {
967       DictScope ESES(SW, "EpilogueScope");
968       SW.printNumber("StartOffset", ES.EpilogueStartOffset());
969       if (!isAArch64)
970         SW.printNumber("Condition", ES.Condition());
971       SW.printNumber("EpilogueStartIndex",
972                      isAArch64 ? ES.EpilogueStartIndexAArch64()
973                                : ES.EpilogueStartIndexARM());
974       if (ES.ES & ~0xffc3ffff)
975         SW.printNumber("ReservedBits", (ES.ES >> 18) & 0xF);
976 
977       ListScope Opcodes(SW, "Opcodes");
978       decodeOpcodes(XData.UnwindByteCode(),
979                     isAArch64 ? ES.EpilogueStartIndexAArch64()
980                               : ES.EpilogueStartIndexARM(),
981                     /*Prologue=*/false);
982     }
983   }
984 
985   if (XData.X()) {
986     const uint32_t Parameter = XData.ExceptionHandlerParameter();
987     const size_t HandlerOffset = HeaderWords(XData) +
988                                  (XData.E() ? 0 : XData.EpilogueCount()) +
989                                  XData.CodeWords();
990 
991     uint64_t Address, SymbolOffset;
992     ErrorOr<SymbolRef> Symbol = getSymbolForLocation(
993         COFF, Section, Offset + HandlerOffset * sizeof(uint32_t),
994         XData.ExceptionHandlerRVA(), Address, SymbolOffset,
995         /*FunctionOnly=*/true);
996     if (!Symbol) {
997       ListScope EHS(SW, "ExceptionHandler");
998       SW.printHex("Routine", Address);
999       SW.printHex("Parameter", Parameter);
1000       return true;
1001     }
1002 
1003     Expected<StringRef> Name = Symbol->getName();
1004     if (!Name) {
1005       std::string Buf;
1006       llvm::raw_string_ostream OS(Buf);
1007       logAllUnhandledErrors(Name.takeError(), OS);
1008       report_fatal_error(Twine(OS.str()));
1009     }
1010 
1011     ListScope EHS(SW, "ExceptionHandler");
1012     SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset));
1013     SW.printHex("Parameter", Parameter);
1014   }
1015 
1016   return true;
1017 }
1018 
1019 bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
1020                                 const SectionRef Section, uint64_t Offset,
1021                                 unsigned Index, const RuntimeFunction &RF) {
1022   assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
1023          "packed entry cannot be treated as an unpacked entry");
1024 
1025   uint64_t FunctionAddress, FunctionOffset;
1026   ErrorOr<SymbolRef> Function = getSymbolForLocation(
1027       COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1028       /*FunctionOnly=*/true);
1029 
1030   uint64_t XDataAddress, XDataOffset;
1031   ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation(
1032       COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress,
1033       XDataOffset);
1034 
1035   if (!RF.BeginAddress && !Function)
1036     return false;
1037   if (!RF.UnwindData && !XDataRecord)
1038     return false;
1039 
1040   StringRef FunctionName;
1041   if (Function) {
1042     Expected<StringRef> FunctionNameOrErr = Function->getName();
1043     if (!FunctionNameOrErr) {
1044       std::string Buf;
1045       llvm::raw_string_ostream OS(Buf);
1046       logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1047       report_fatal_error(Twine(OS.str()));
1048     }
1049     FunctionName = *FunctionNameOrErr;
1050   }
1051 
1052   SW.printString("Function",
1053                  formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1054 
1055   if (XDataRecord) {
1056     Expected<StringRef> Name = XDataRecord->getName();
1057     if (!Name) {
1058       std::string Buf;
1059       llvm::raw_string_ostream OS(Buf);
1060       logAllUnhandledErrors(Name.takeError(), OS);
1061       report_fatal_error(Twine(OS.str()));
1062     }
1063 
1064     SW.printString("ExceptionRecord",
1065                    formatSymbol(*Name, XDataAddress, XDataOffset));
1066 
1067     Expected<section_iterator> SIOrErr = XDataRecord->getSection();
1068     if (!SIOrErr) {
1069       // TODO: Actually report errors helpfully.
1070       consumeError(SIOrErr.takeError());
1071       return false;
1072     }
1073     section_iterator SI = *SIOrErr;
1074 
1075     return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress);
1076   } else {
1077     SW.printString("ExceptionRecord", formatSymbol("", XDataAddress));
1078 
1079     ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress);
1080     if (!Section)
1081       return false;
1082 
1083     return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress);
1084   }
1085 }
1086 
1087 bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
1088                               const SectionRef Section, uint64_t Offset,
1089                               unsigned Index, const RuntimeFunction &RF) {
1090   assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
1091           RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
1092          "unpacked entry cannot be treated as a packed entry");
1093 
1094   uint64_t FunctionAddress, FunctionOffset;
1095   ErrorOr<SymbolRef> Function = getSymbolForLocation(
1096       COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1097       /*FunctionOnly=*/true);
1098 
1099   StringRef FunctionName;
1100   if (Function) {
1101     Expected<StringRef> FunctionNameOrErr = Function->getName();
1102     if (!FunctionNameOrErr) {
1103       std::string Buf;
1104       llvm::raw_string_ostream OS(Buf);
1105       logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1106       report_fatal_error(Twine(OS.str()));
1107     }
1108     FunctionName = *FunctionNameOrErr;
1109   }
1110 
1111   SW.printString("Function",
1112                  formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
1113   if (!isAArch64)
1114     SW.printBoolean("Fragment",
1115                     RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
1116   SW.printNumber("FunctionLength", RF.FunctionLength());
1117   SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
1118   SW.printBoolean("HomedParameters", RF.H());
1119   SW.startLine() << "SavedRegisters: ";
1120                  printRegisters(SavedRegisterMask(RF));
1121   OS << '\n';
1122   SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
1123 
1124   return true;
1125 }
1126 
1127 bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
1128                                    const SectionRef Section, uint64_t Offset,
1129                                    unsigned Index,
1130                                    const RuntimeFunctionARM64 &RF) {
1131   assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
1132           RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
1133          "unpacked entry cannot be treated as a packed entry");
1134 
1135   uint64_t FunctionAddress, FunctionOffset;
1136   ErrorOr<SymbolRef> Function = getSymbolForLocation(
1137       COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
1138       /*FunctionOnly=*/true);
1139 
1140   StringRef FunctionName;
1141   if (Function) {
1142     Expected<StringRef> FunctionNameOrErr = Function->getName();
1143     if (!FunctionNameOrErr) {
1144       std::string Buf;
1145       llvm::raw_string_ostream OS(Buf);
1146       logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);
1147       report_fatal_error(Twine(OS.str()));
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 
1255 bool 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 
1273 void 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 
1289 Error 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