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