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