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