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