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