1//===-- ARMWinEHPrinter.cpp - Windows on ARM EH Data Printer ----*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// Windows on ARM uses a series of serialised data structures (RuntimeFunction)
11// to create a table of information for unwinding.  In order to conserve space,
12// there are two different ways that this data is represented.
13//
14// For functions with canonical forms for the prologue and epilogue, the data
15// can be stored in a "packed" form.  In this case, the data is packed into the
16// RuntimeFunction's remaining 30-bits and can fully describe the entire frame.
17//
18//        +---------------------------------------+
19//        |         Function Entry Address        |
20//        +---------------------------------------+
21//        |           Packed Form Data            |
22//        +---------------------------------------+
23//
24// This layout is parsed by Decoder::dumpPackedEntry.  No unwind bytecode is
25// associated with such a frame as they can be derived from the provided data.
26// The decoder does not synthesize this data as it is unnecessary for the
27// purposes of validation, with the synthesis being required only by a proper
28// unwinder.
29//
30// For functions that are large or do not match canonical forms, the data is
31// split up into two portions, with the actual data residing in the "exception
32// data" table (.xdata) with a reference to the entry from the "procedure data"
33// (.pdata) entry.
34//
35// The exception data contains information about the frame setup, all of the
36// epilouge scopes (for functions for which there are multiple exit points) and
37// the associated exception handler.  Additionally, the entry contains byte-code
38// describing how to unwind the function (c.f. Decoder::decodeOpcodes).
39//
40//        +---------------------------------------+
41//        |         Function Entry Address        |
42//        +---------------------------------------+
43//        |      Exception Data Entry Address     |
44//        +---------------------------------------+
45//
46// This layout is parsed by Decoder::dumpUnpackedEntry.  Such an entry must
47// first resolve the exception data entry address.  This structure
48// (ExceptionDataRecord) has a variable sized header
49// (c.f. ARM::WinEH::HeaderWords) and encodes most of the same information as
50// the packed form.  However, because this information is insufficient to
51// synthesize the unwinding, there are associated unwinding bytecode which make
52// up the bulk of the Decoder.
53//
54// The decoder itself is table-driven, using the first byte to determine the
55// opcode and dispatching to the associated printing routine.  The bytecode
56// itself is a variable length instruction encoding that can fully describe the
57// state of the stack and the necessary operations for unwinding to the
58// beginning of the frame.
59//
60// The byte-code maintains a 1-1 instruction mapping, indicating both the width
61// of the instruction (Thumb2 instructions are variable length, 16 or 32 bits
62// wide) allowing the program to unwind from any point in the prologue, body, or
63// epilogue of the function.
64
65#include "ARMWinEHPrinter.h"
66#include "Error.h"
67#include "llvm/ADT/StringExtras.h"
68#include "llvm/ADT/STLExtras.h"
69#include "llvm/Support/ARMWinEH.h"
70#include "llvm/Support/Format.h"
71
72using namespace llvm;
73using namespace llvm::object;
74using namespace llvm::support;
75
76namespace llvm {
77raw_ostream &operator<<(raw_ostream &OS, const ARM::WinEH::ReturnType &RT) {
78  switch (RT) {
79  case ARM::WinEH::ReturnType::RT_POP:
80    OS << "pop {pc}";
81    break;
82  case ARM::WinEH::ReturnType::RT_B:
83    OS << "b target";
84    break;
85  case ARM::WinEH::ReturnType::RT_BW:
86    OS << "b.w target";
87    break;
88  case ARM::WinEH::ReturnType::RT_NoEpilogue:
89    OS << "(no epilogue)";
90    break;
91  }
92  return OS;
93}
94}
95
96static std::string formatSymbol(StringRef Name, uint64_t Address,
97                                uint64_t Offset = 0) {
98  std::string Buffer;
99  raw_string_ostream OS(Buffer);
100
101  if (!Name.empty())
102    OS << Name << " ";
103
104  if (Offset)
105    OS << format("+0x%X (0x%" PRIX64 ")", Offset, Address);
106  else if (!Name.empty())
107    OS << format("(0x%" PRIX64 ")", Address);
108  else
109    OS << format("0x%" PRIX64, Address);
110
111  return OS.str();
112}
113
114namespace llvm {
115namespace ARM {
116namespace WinEH {
117const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);
118
119// TODO name the uops more appropriately
120const Decoder::RingEntry Decoder::Ring[] = {
121  { 0x80, 0x00, &Decoder::opcode_0xxxxxxx },  // UOP_STACK_FREE (16-bit)
122  { 0xc0, 0x80, &Decoder::opcode_10Lxxxxx },  // UOP_POP (32-bit)
123  { 0xf0, 0xc0, &Decoder::opcode_1100xxxx },  // UOP_STACK_SAVE (16-bit)
124  { 0xf8, 0xd0, &Decoder::opcode_11010Lxx },  // UOP_POP (16-bit)
125  { 0xf8, 0xd8, &Decoder::opcode_11011Lxx },  // UOP_POP (32-bit)
126  { 0xf8, 0xe0, &Decoder::opcode_11100xxx },  // UOP_VPOP (32-bit)
127  { 0xfc, 0xe8, &Decoder::opcode_111010xx },  // UOP_STACK_FREE (32-bit)
128  { 0xfe, 0xec, &Decoder::opcode_1110110L },  // UOP_POP (16-bit)
129  { 0xff, 0xee, &Decoder::opcode_11101110 },  // UOP_MICROSOFT_SPECIFIC (16-bit)
130                                              // UOP_PUSH_MACHINE_FRAME
131                                              // UOP_PUSH_CONTEXT
132                                              // UOP_PUSH_TRAP_FRAME
133                                              // UOP_REDZONE_RESTORE_LR
134  { 0xff, 0xef, &Decoder::opcode_11101111 },  // UOP_LDRPC_POSTINC (32-bit)
135  { 0xff, 0xf5, &Decoder::opcode_11110101 },  // UOP_VPOP (32-bit)
136  { 0xff, 0xf6, &Decoder::opcode_11110110 },  // UOP_VPOP (32-bit)
137  { 0xff, 0xf7, &Decoder::opcode_11110111 },  // UOP_STACK_RESTORE (16-bit)
138  { 0xff, 0xf8, &Decoder::opcode_11111000 },  // UOP_STACK_RESTORE (16-bit)
139  { 0xff, 0xf9, &Decoder::opcode_11111001 },  // UOP_STACK_RESTORE (32-bit)
140  { 0xff, 0xfa, &Decoder::opcode_11111010 },  // UOP_STACK_RESTORE (32-bit)
141  { 0xff, 0xfb, &Decoder::opcode_11111011 },  // UOP_NOP (16-bit)
142  { 0xff, 0xfc, &Decoder::opcode_11111100 },  // UOP_NOP (32-bit)
143  { 0xff, 0xfd, &Decoder::opcode_11111101 },  // UOP_NOP (16-bit) / END
144  { 0xff, 0xfe, &Decoder::opcode_11111110 },  // UOP_NOP (32-bit) / END
145  { 0xff, 0xff, &Decoder::opcode_11111111 },  // UOP_END
146};
147
148void Decoder::printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask) {
149  static const char * const GPRRegisterNames[16] = {
150    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
151    "r11", "ip", "sp", "lr", "pc",
152  };
153
154  const uint16_t GPRMask = std::get<0>(RegisterMask);
155  const uint16_t VFPMask = std::get<1>(RegisterMask);
156
157  OS << '{';
158  bool Comma = false;
159  for (unsigned RI = 0, RE = 11; RI < RE; ++RI) {
160    if (GPRMask & (1 << RI)) {
161      if (Comma)
162        OS << ", ";
163      OS << GPRRegisterNames[RI];
164      Comma = true;
165    }
166  }
167  for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
168    if (VFPMask & (1 << RI)) {
169      if (Comma)
170        OS << ", ";
171      OS << "d" << unsigned(RI);
172      Comma = true;
173    }
174  }
175  for (unsigned RI = 11, RE = 16; RI < RE; ++RI) {
176    if (GPRMask & (1 << RI)) {
177      if (Comma)
178        OS << ", ";
179      OS << GPRRegisterNames[RI];
180      Comma = true;
181    }
182  }
183  OS << '}';
184}
185
186ErrorOr<object::SectionRef>
187Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {
188  for (const auto &Section : COFF.sections()) {
189    uint64_t Address;
190    uint64_t Size;
191
192    if (std::error_code EC = Section.getAddress(Address))
193      return EC;
194    if (std::error_code EC = Section.getSize(Size))
195      return EC;
196
197    if (VA >= Address && (VA - Address) <= Size)
198      return Section;
199  }
200  return readobj_error::unknown_symbol;
201}
202
203ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF,
204                                              uint64_t VA, bool FunctionOnly) {
205  for (const auto &Symbol : COFF.symbols()) {
206    if (FunctionOnly) {
207      SymbolRef::Type Type;
208      if (std::error_code EC = Symbol.getType(Type))
209        return EC;
210      if (Type != SymbolRef::ST_Function)
211        continue;
212    }
213
214    uint64_t Address;
215    if (std::error_code EC = Symbol.getAddress(Address))
216      return EC;
217    if (Address == VA)
218      return Symbol;
219  }
220  return readobj_error::unknown_symbol;
221}
222
223ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,
224                                               const SectionRef &Section,
225                                               uint64_t Offset) {
226  for (const auto &Relocation : Section.relocations()) {
227    uint64_t RelocationOffset;
228    if (auto Error = Relocation.getOffset(RelocationOffset))
229      return Error;
230    if (RelocationOffset == Offset)
231      return *Relocation.getSymbol();
232  }
233  return readobj_error::unknown_symbol;
234}
235
236bool Decoder::opcode_0xxxxxxx(const ulittle8_t *OC, unsigned &Offset,
237                              unsigned Length, bool Prologue) {
238  uint8_t Imm = OC[Offset] & 0x7f;
239  SW.startLine() << format("0x%02x                ; %s sp, #(%u * 4)\n",
240                           OC[Offset],
241                           static_cast<const char *>(Prologue ? "sub" : "add"),
242                           Imm);
243  ++Offset;
244  return false;
245}
246
247bool Decoder::opcode_10Lxxxxx(const ulittle8_t *OC, unsigned &Offset,
248                              unsigned Length, bool Prologue) {
249  unsigned Link = (OC[Offset] & 0x20) >> 5;
250  uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))
251                        | ((OC[Offset + 0] & 0x1f) << 8)
252                        | ((OC[Offset + 1] & 0xff) << 0);
253  assert((~RegisterMask & (1 << 13)) && "sp must not be set");
254  assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");
255
256  SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",
257                           OC[Offset + 0], OC[Offset + 1],
258                           Prologue ? "push" : "pop");
259  printRegisters(std::make_pair(RegisterMask, 0));
260  OS << '\n';
261
262  ++Offset, ++Offset;
263  return false;
264}
265
266bool Decoder::opcode_1100xxxx(const ulittle8_t *OC, unsigned &Offset,
267                              unsigned Length, bool Prologue) {
268  if (Prologue)
269    SW.startLine() << format("0x%02x                ; mov r%u, sp\n",
270                             OC[Offset], OC[Offset] & 0xf);
271  else
272    SW.startLine() << format("0x%02x                ; mov sp, r%u\n",
273                             OC[Offset], OC[Offset] & 0xf);
274  ++Offset;
275  return false;
276}
277
278bool Decoder::opcode_11010Lxx(const ulittle8_t *OC, unsigned &Offset,
279                              unsigned Length, bool Prologue) {
280  unsigned Link = (OC[Offset] & 0x4) >> 3;
281  unsigned Count = (OC[Offset] & 0x3);
282
283  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
284                   | (((1 << (Count + 1)) - 1) << 4);
285
286  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
287                           Prologue ? "push" : "pop");
288  printRegisters(std::make_pair(GPRMask, 0));
289  OS << '\n';
290
291  ++Offset;
292  return false;
293}
294
295bool Decoder::opcode_11011Lxx(const ulittle8_t *OC, unsigned &Offset,
296                              unsigned Length, bool Prologue) {
297  unsigned Link = (OC[Offset] & 0x4) >> 2;
298  unsigned Count = (OC[Offset] & 0x3) + 4;
299
300  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
301                   | (((1 << (Count + 1)) - 1) << 4);
302
303  SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],
304                           Prologue ? "push" : "pop");
305  printRegisters(std::make_pair(GPRMask, 0));
306  OS << '\n';
307
308  ++Offset;
309  return false;
310}
311
312bool Decoder::opcode_11100xxx(const ulittle8_t *OC, unsigned &Offset,
313                              unsigned Length, bool Prologue) {
314  unsigned High = (OC[Offset] & 0x7);
315  uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);
316
317  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
318                           Prologue ? "vpush" : "vpop");
319  printRegisters(std::make_pair(0, VFPMask));
320  OS << '\n';
321
322  ++Offset;
323  return false;
324}
325
326bool Decoder::opcode_111010xx(const ulittle8_t *OC, unsigned &Offset,
327                              unsigned Length, bool Prologue) {
328  uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);
329
330  SW.startLine() << format("0x%02x 0x%02x           ; %s.w sp, #(%u * 4)\n",
331                           OC[Offset + 0], OC[Offset + 1],
332                           static_cast<const char *>(Prologue ? "sub" : "add"),
333                           Imm);
334
335  ++Offset, ++Offset;
336  return false;
337}
338
339bool Decoder::opcode_1110110L(const ulittle8_t *OC, unsigned &Offset,
340                              unsigned Length, bool Prologue) {
341  uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))
342                  | ((OC[Offset + 1] & 0xff) << 0);
343
344  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
345                           OC[Offset + 1], Prologue ? "push" : "pop");
346  printRegisters(std::make_pair(GPRMask, 0));
347  OS << '\n';
348
349  ++Offset, ++Offset;
350  return false;
351}
352
353bool Decoder::opcode_11101110(const ulittle8_t *OC, unsigned &Offset,
354                              unsigned Length, bool Prologue) {
355  assert(!Prologue && "may not be used in prologue");
356
357  if (OC[Offset + 1] & 0xf0)
358    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
359                             OC[Offset + 0], OC[Offset +  1]);
360  else
361    SW.startLine()
362      << format("0x%02x 0x%02x           ; microsoft-specific (type: %u)\n",
363                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);
364
365  ++Offset, ++Offset;
366  return false;
367}
368
369bool Decoder::opcode_11101111(const ulittle8_t *OC, unsigned &Offset,
370                              unsigned Length, bool Prologue) {
371  assert(!Prologue && "may not be used in prologue");
372
373  if (OC[Offset + 1] & 0xf0)
374    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
375                             OC[Offset + 0], OC[Offset +  1]);
376  else
377    SW.startLine()
378      << format("0x%02x 0x%02x           ; ldr.w lr, [sp], #%u\n",
379                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
380
381  ++Offset, ++Offset;
382  return false;
383}
384
385bool Decoder::opcode_11110101(const ulittle8_t *OC, unsigned &Offset,
386                              unsigned Length, bool Prologue) {
387  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
388  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
389  uint32_t VFPMask = ((1 << (End - Start)) - 1) << Start;
390
391  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
392                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
393  printRegisters(std::make_pair(0, VFPMask));
394  OS << '\n';
395
396  ++Offset, ++Offset;
397  return false;
398}
399
400bool Decoder::opcode_11110110(const ulittle8_t *OC, unsigned &Offset,
401                              unsigned Length, bool Prologue) {
402  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
403  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
404  uint32_t VFPMask = ((1 << (End - Start)) - 1) << 16;
405
406  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
407                           OC[Offset + 1], Prologue ? "vpush" : "vpop");
408  printRegisters(std::make_pair(0, VFPMask));
409  OS << '\n';
410
411  ++Offset, ++Offset;
412  return false;
413}
414
415bool Decoder::opcode_11110111(const ulittle8_t *OC, unsigned &Offset,
416                              unsigned Length, bool Prologue) {
417  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
418
419  SW.startLine() << format("0x%02x 0x%02x 0x%02x      ; %s sp, sp, #(%u * 4)\n",
420                           OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
421                           static_cast<const char *>(Prologue ? "sub" : "add"),
422                           Imm);
423
424  ++Offset, ++Offset, ++Offset;
425  return false;
426}
427
428bool Decoder::opcode_11111000(const ulittle8_t *OC, unsigned &Offset,
429                              unsigned Length, bool Prologue) {
430  uint32_t Imm = (OC[Offset + 1] << 16)
431               | (OC[Offset + 2] << 8)
432               | (OC[Offset + 3] << 0);
433
434  SW.startLine()
435    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
436              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
437              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
438
439  ++Offset, ++Offset, ++Offset, ++Offset;
440  return false;
441}
442
443bool Decoder::opcode_11111001(const ulittle8_t *OC, unsigned &Offset,
444                              unsigned Length, bool Prologue) {
445  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
446
447  SW.startLine()
448    << format("0x%02x 0x%02x 0x%02x      ; %s.w sp, sp, #(%u * 4)\n",
449              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
450              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
451
452  ++Offset, ++Offset, ++Offset;
453  return false;
454}
455
456bool Decoder::opcode_11111010(const ulittle8_t *OC, unsigned &Offset,
457                              unsigned Length, bool Prologue) {
458  uint32_t Imm = (OC[Offset + 1] << 16)
459               | (OC[Offset + 2] << 8)
460               | (OC[Offset + 3] << 0);
461
462  SW.startLine()
463    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
464              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
465              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
466
467  ++Offset, ++Offset, ++Offset, ++Offset;
468  return false;
469}
470
471bool Decoder::opcode_11111011(const ulittle8_t *OC, unsigned &Offset,
472                              unsigned Length, bool Prologue) {
473  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
474  ++Offset;
475  return false;
476}
477
478bool Decoder::opcode_11111100(const ulittle8_t *OC, unsigned &Offset,
479                              unsigned Length, bool Prologue) {
480  SW.startLine() << format("0x%02x                ; nop.w\n", OC[Offset]);
481  ++Offset;
482  return false;
483}
484
485bool Decoder::opcode_11111101(const ulittle8_t *OC, unsigned &Offset,
486                              unsigned Length, bool Prologue) {
487  SW.startLine() << format("0x%02x                ; b\n", OC[Offset]);
488  ++Offset;
489  return true;
490}
491
492bool Decoder::opcode_11111110(const ulittle8_t *OC, unsigned &Offset,
493                              unsigned Length, bool Prologue) {
494  SW.startLine() << format("0x%02x                ; b.w\n", OC[Offset]);
495  ++Offset;
496  return true;
497}
498
499bool Decoder::opcode_11111111(const ulittle8_t *OC, unsigned &Offset,
500                              unsigned Length, bool Prologue) {
501  ++Offset;
502  return true;
503}
504
505void Decoder::decodeOpcodes(ArrayRef<ulittle8_t> Opcodes, unsigned Offset,
506                            bool Prologue) {
507  assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
508
509  bool Terminated = false;
510  for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
511    for (unsigned DI = 0;; ++DI) {
512      if ((Opcodes[OI] & Ring[DI].Mask) == Ring[DI].Value) {
513        Terminated = (this->*Ring[DI].Routine)(Opcodes.data(), OI, 0, Prologue);
514        break;
515      }
516      assert(DI < array_lengthof(Ring) && "unhandled opcode");
517    }
518  }
519}
520
521bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
522                              const SectionRef &Section,
523                              uint64_t FunctionAddress, uint64_t VA) {
524  ArrayRef<uint8_t> Contents;
525  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
526    return false;
527
528  uint64_t SectionVA;
529  if (Section.getAddress(SectionVA))
530    return false;
531
532  uint64_t Offset = VA - SectionVA;
533  const ulittle32_t *Data =
534    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
535  const ExceptionDataRecord XData(Data);
536
537  DictScope XRS(SW, "ExceptionData");
538  SW.printNumber("FunctionLength", XData.FunctionLength() << 1);
539  SW.printNumber("Version", XData.Vers());
540  SW.printBoolean("ExceptionData", XData.X());
541  SW.printBoolean("EpiloguePacked", XData.E());
542  SW.printBoolean("Fragment", XData.F());
543  SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",
544                 XData.EpilogueCount());
545  SW.printNumber("ByteCodeLength",
546                 static_cast<uint64_t>(XData.CodeWords() * sizeof(uint32_t)));
547
548  if (XData.E()) {
549    ArrayRef<ulittle8_t> UC = XData.UnwindByteCode();
550    if (!XData.F()) {
551      ListScope PS(SW, "Prologue");
552      decodeOpcodes(UC, 0, /*Prologue=*/true);
553    }
554    if (XData.EpilogueCount()) {
555      ListScope ES(SW, "Epilogue");
556      decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);
557    }
558  } else {
559    ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes();
560    ListScope ESS(SW, "EpilogueScopes");
561    for (const EpilogueScope ES : EpilogueScopes) {
562      DictScope ESES(SW, "EpilogueScope");
563      SW.printNumber("StartOffset", ES.EpilogueStartOffset());
564      SW.printNumber("Condition", ES.Condition());
565      SW.printNumber("EpilogueStartIndex", ES.EpilogueStartIndex());
566
567      ListScope Opcodes(SW, "Opcodes");
568      decodeOpcodes(XData.UnwindByteCode(), ES.EpilogueStartIndex(),
569                    /*Prologue=*/false);
570    }
571  }
572
573  if (XData.X()) {
574    const uint32_t Address = XData.ExceptionHandlerRVA();
575    const uint32_t Parameter = XData.ExceptionHandlerParameter();
576    const size_t HandlerOffset = HeaderWords(XData)
577                               + (XData.E() ? 0 : XData.EpilogueCount())
578                               + XData.CodeWords();
579
580    ErrorOr<SymbolRef> Symbol =
581      getRelocatedSymbol(COFF, Section, HandlerOffset * sizeof(uint32_t));
582    if (!Symbol)
583      Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true);
584
585    StringRef Name;
586    if (Symbol)
587      Symbol->getName(Name);
588
589    ListScope EHS(SW, "ExceptionHandler");
590    SW.printString("Routine", formatSymbol(Name, Address));
591    SW.printHex("Parameter", Parameter);
592  }
593
594  return true;
595}
596
597bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
598                                const SectionRef Section, uint64_t Offset,
599                                unsigned Index, const RuntimeFunction &RF) {
600  assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
601         "packed entry cannot be treated as an unpacked entry");
602
603  ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
604  if (!Function)
605    Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
606
607  ErrorOr<SymbolRef> XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4);
608  if (!XDataRecord)
609    XDataRecord = getSymbol(COFF, RF.ExceptionInformationRVA());
610
611  if (!RF.BeginAddress && !Function)
612    return false;
613  if (!RF.UnwindData && !XDataRecord)
614    return false;
615
616  StringRef FunctionName;
617  uint64_t FunctionAddress;
618  if (Function) {
619    Function->getName(FunctionName);
620    Function->getAddress(FunctionAddress);
621  } else {
622    const pe32_header *PEHeader;
623    if (COFF.getPE32Header(PEHeader))
624      return false;
625    FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
626  }
627
628  SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
629
630  if (XDataRecord) {
631    StringRef Name;
632    uint64_t Address;
633
634    XDataRecord->getName(Name);
635    XDataRecord->getAddress(Address);
636
637    SW.printString("ExceptionRecord", formatSymbol(Name, Address));
638
639    section_iterator SI = COFF.section_end();
640    if (XDataRecord->getSection(SI))
641      return false;
642
643    return dumpXDataRecord(COFF, *SI, FunctionAddress, Address);
644  } else {
645    const pe32_header *PEHeader;
646    if (COFF.getPE32Header(PEHeader))
647      return false;
648
649    uint64_t Address = PEHeader->ImageBase + RF.ExceptionInformationRVA();
650    SW.printString("ExceptionRecord", formatSymbol("", Address));
651
652    ErrorOr<SectionRef> Section =
653      getSectionContaining(COFF, RF.ExceptionInformationRVA());
654    if (!Section)
655      return false;
656
657    return dumpXDataRecord(COFF, *Section, FunctionAddress,
658                           RF.ExceptionInformationRVA());
659  }
660}
661
662bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
663                              const SectionRef Section, uint64_t Offset,
664                              unsigned Index, const RuntimeFunction &RF) {
665  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
666          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
667         "unpacked entry cannot be treated as a packed entry");
668
669  ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
670  if (!Function)
671    Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
672
673  StringRef FunctionName;
674  uint64_t FunctionAddress;
675  if (Function) {
676    Function->getName(FunctionName);
677    Function->getAddress(FunctionAddress);
678  } else {
679    const pe32_header *PEHeader;
680    if (COFF.getPE32Header(PEHeader))
681      return false;
682    FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
683  }
684
685  SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
686  SW.printBoolean("Fragment",
687                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
688  SW.printNumber("FunctionLength", RF.FunctionLength());
689  SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
690  SW.printBoolean("HomedParameters", RF.H());
691  SW.startLine() << "SavedRegisters: ";
692                 printRegisters(SavedRegisterMask(RF));
693  OS << '\n';
694  SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
695
696  return true;
697}
698
699bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,
700                                     const SectionRef Section, unsigned Index,
701                                     ArrayRef<uint8_t> Contents) {
702  uint64_t Offset = PDataEntrySize * Index;
703  const ulittle32_t *Data =
704    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
705
706  const RuntimeFunction Entry(Data);
707  DictScope RFS(SW, "RuntimeFunction");
708  if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)
709    return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);
710  return dumpPackedEntry(COFF, Section, Offset, Index, Entry);
711}
712
713void Decoder::dumpProcedureData(const COFFObjectFile &COFF,
714                                const SectionRef Section) {
715  ArrayRef<uint8_t> Contents;
716  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
717    return;
718
719  if (Contents.size() % PDataEntrySize) {
720    errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n";
721    return;
722  }
723
724  for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI)
725    if (!dumpProcedureDataEntry(COFF, Section, EI, Contents))
726      break;
727}
728
729std::error_code Decoder::dumpProcedureData(const COFFObjectFile &COFF) {
730  for (const auto &Section : COFF.sections()) {
731    StringRef SectionName;
732    if (std::error_code EC =
733            COFF.getSectionName(COFF.getCOFFSection(Section), SectionName))
734      return EC;
735
736    if (SectionName.startswith(".pdata"))
737      dumpProcedureData(COFF, Section);
738  }
739  return std::error_code();
740}
741}
742}
743}
744
745