Home | History | Annotate | Download | only in llvm-readobj
      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/STLExtras.h"
     68 #include "llvm/ADT/StringExtras.h"
     69 #include "llvm/Support/ARMWinEH.h"
     70 #include "llvm/Support/Format.h"
     71 
     72 using namespace llvm;
     73 using namespace llvm::object;
     74 using namespace llvm::support;
     75 
     76 namespace llvm {
     77 raw_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 
     96 static 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 
    114 namespace llvm {
    115 namespace ARM {
    116 namespace WinEH {
    117 const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);
    118 
    119 // TODO name the uops more appropriately
    120 const 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 
    148 void 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 
    186 ErrorOr<object::SectionRef>
    187 Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {
    188   for (const auto &Section : COFF.sections()) {
    189     uint64_t Address = Section.getAddress();
    190     uint64_t Size = Section.getSize();
    191 
    192     if (VA >= Address && (VA - Address) <= Size)
    193       return Section;
    194   }
    195   return readobj_error::unknown_symbol;
    196 }
    197 
    198 ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF,
    199                                               uint64_t VA, bool FunctionOnly) {
    200   for (const auto &Symbol : COFF.symbols()) {
    201     if (FunctionOnly && Symbol.getType() != SymbolRef::ST_Function)
    202       continue;
    203 
    204     ErrorOr<uint64_t> Address = Symbol.getAddress();
    205     if (std::error_code EC = Address.getError())
    206       return EC;
    207     if (*Address == VA)
    208       return Symbol;
    209   }
    210   return readobj_error::unknown_symbol;
    211 }
    212 
    213 ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,
    214                                                const SectionRef &Section,
    215                                                uint64_t Offset) {
    216   for (const auto &Relocation : Section.relocations()) {
    217     uint64_t RelocationOffset = Relocation.getOffset();
    218     if (RelocationOffset == Offset)
    219       return *Relocation.getSymbol();
    220   }
    221   return readobj_error::unknown_symbol;
    222 }
    223 
    224 bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset,
    225                               unsigned Length, bool Prologue) {
    226   uint8_t Imm = OC[Offset] & 0x7f;
    227   SW.startLine() << format("0x%02x                ; %s sp, #(%u * 4)\n",
    228                            OC[Offset],
    229                            static_cast<const char *>(Prologue ? "sub" : "add"),
    230                            Imm);
    231   ++Offset;
    232   return false;
    233 }
    234 
    235 bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset,
    236                               unsigned Length, bool Prologue) {
    237   unsigned Link = (OC[Offset] & 0x20) >> 5;
    238   uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))
    239                         | ((OC[Offset + 0] & 0x1f) << 8)
    240                         | ((OC[Offset + 1] & 0xff) << 0);
    241   assert((~RegisterMask & (1 << 13)) && "sp must not be set");
    242   assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");
    243 
    244   SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",
    245                            OC[Offset + 0], OC[Offset + 1],
    246                            Prologue ? "push" : "pop");
    247   printRegisters(std::make_pair(RegisterMask, 0));
    248   OS << '\n';
    249 
    250   ++Offset, ++Offset;
    251   return false;
    252 }
    253 
    254 bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset,
    255                               unsigned Length, bool Prologue) {
    256   if (Prologue)
    257     SW.startLine() << format("0x%02x                ; mov r%u, sp\n",
    258                              OC[Offset], OC[Offset] & 0xf);
    259   else
    260     SW.startLine() << format("0x%02x                ; mov sp, r%u\n",
    261                              OC[Offset], OC[Offset] & 0xf);
    262   ++Offset;
    263   return false;
    264 }
    265 
    266 bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset,
    267                               unsigned Length, bool Prologue) {
    268   unsigned Link = (OC[Offset] & 0x4) >> 3;
    269   unsigned Count = (OC[Offset] & 0x3);
    270 
    271   uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
    272                    | (((1 << (Count + 1)) - 1) << 4);
    273 
    274   SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
    275                            Prologue ? "push" : "pop");
    276   printRegisters(std::make_pair(GPRMask, 0));
    277   OS << '\n';
    278 
    279   ++Offset;
    280   return false;
    281 }
    282 
    283 bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset,
    284                               unsigned Length, bool Prologue) {
    285   unsigned Link = (OC[Offset] & 0x4) >> 2;
    286   unsigned Count = (OC[Offset] & 0x3) + 4;
    287 
    288   uint16_t GPRMask = (Link << (Prologue ? 14 : 15))
    289                    | (((1 << (Count + 1)) - 1) << 4);
    290 
    291   SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],
    292                            Prologue ? "push" : "pop");
    293   printRegisters(std::make_pair(GPRMask, 0));
    294   OS << '\n';
    295 
    296   ++Offset;
    297   return false;
    298 }
    299 
    300 bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset,
    301                               unsigned Length, bool Prologue) {
    302   unsigned High = (OC[Offset] & 0x7);
    303   uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);
    304 
    305   SW.startLine() << format("0x%02x                ; %s ", OC[Offset],
    306                            Prologue ? "vpush" : "vpop");
    307   printRegisters(std::make_pair(0, VFPMask));
    308   OS << '\n';
    309 
    310   ++Offset;
    311   return false;
    312 }
    313 
    314 bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset,
    315                               unsigned Length, bool Prologue) {
    316   uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);
    317 
    318   SW.startLine() << format("0x%02x 0x%02x           ; %s.w sp, #(%u * 4)\n",
    319                            OC[Offset + 0], OC[Offset + 1],
    320                            static_cast<const char *>(Prologue ? "sub" : "add"),
    321                            Imm);
    322 
    323   ++Offset, ++Offset;
    324   return false;
    325 }
    326 
    327 bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset,
    328                               unsigned Length, bool Prologue) {
    329   uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))
    330                   | ((OC[Offset + 1] & 0xff) << 0);
    331 
    332   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
    333                            OC[Offset + 1], Prologue ? "push" : "pop");
    334   printRegisters(std::make_pair(GPRMask, 0));
    335   OS << '\n';
    336 
    337   ++Offset, ++Offset;
    338   return false;
    339 }
    340 
    341 bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset,
    342                               unsigned Length, bool Prologue) {
    343   assert(!Prologue && "may not be used in prologue");
    344 
    345   if (OC[Offset + 1] & 0xf0)
    346     SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
    347                              OC[Offset + 0], OC[Offset +  1]);
    348   else
    349     SW.startLine()
    350       << format("0x%02x 0x%02x           ; microsoft-specific (type: %u)\n",
    351                 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);
    352 
    353   ++Offset, ++Offset;
    354   return false;
    355 }
    356 
    357 bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset,
    358                               unsigned Length, bool Prologue) {
    359   assert(!Prologue && "may not be used in prologue");
    360 
    361   if (OC[Offset + 1] & 0xf0)
    362     SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",
    363                              OC[Offset + 0], OC[Offset +  1]);
    364   else
    365     SW.startLine()
    366       << format("0x%02x 0x%02x           ; ldr.w lr, [sp], #%u\n",
    367                 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);
    368 
    369   ++Offset, ++Offset;
    370   return false;
    371 }
    372 
    373 bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset,
    374                               unsigned Length, bool Prologue) {
    375   unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
    376   unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
    377   uint32_t VFPMask = ((1 << (End - Start)) - 1) << Start;
    378 
    379   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
    380                            OC[Offset + 1], Prologue ? "vpush" : "vpop");
    381   printRegisters(std::make_pair(0, VFPMask));
    382   OS << '\n';
    383 
    384   ++Offset, ++Offset;
    385   return false;
    386 }
    387 
    388 bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset,
    389                               unsigned Length, bool Prologue) {
    390   unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;
    391   unsigned End = (OC[Offset + 1] & 0x0f) >> 0;
    392   uint32_t VFPMask = ((1 << (End - Start)) - 1) << 16;
    393 
    394   SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],
    395                            OC[Offset + 1], Prologue ? "vpush" : "vpop");
    396   printRegisters(std::make_pair(0, VFPMask));
    397   OS << '\n';
    398 
    399   ++Offset, ++Offset;
    400   return false;
    401 }
    402 
    403 bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset,
    404                               unsigned Length, bool Prologue) {
    405   uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
    406 
    407   SW.startLine() << format("0x%02x 0x%02x 0x%02x      ; %s sp, sp, #(%u * 4)\n",
    408                            OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
    409                            static_cast<const char *>(Prologue ? "sub" : "add"),
    410                            Imm);
    411 
    412   ++Offset, ++Offset, ++Offset;
    413   return false;
    414 }
    415 
    416 bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset,
    417                               unsigned Length, bool Prologue) {
    418   uint32_t Imm = (OC[Offset + 1] << 16)
    419                | (OC[Offset + 2] << 8)
    420                | (OC[Offset + 3] << 0);
    421 
    422   SW.startLine()
    423     << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",
    424               OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
    425               static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
    426 
    427   ++Offset, ++Offset, ++Offset, ++Offset;
    428   return false;
    429 }
    430 
    431 bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset,
    432                               unsigned Length, bool Prologue) {
    433   uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);
    434 
    435   SW.startLine()
    436     << format("0x%02x 0x%02x 0x%02x      ; %s.w sp, sp, #(%u * 4)\n",
    437               OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],
    438               static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
    439 
    440   ++Offset, ++Offset, ++Offset;
    441   return false;
    442 }
    443 
    444 bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset,
    445                               unsigned Length, bool Prologue) {
    446   uint32_t Imm = (OC[Offset + 1] << 16)
    447                | (OC[Offset + 2] << 8)
    448                | (OC[Offset + 3] << 0);
    449 
    450   SW.startLine()
    451     << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",
    452               OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],
    453               static_cast<const char *>(Prologue ? "sub" : "add"), Imm);
    454 
    455   ++Offset, ++Offset, ++Offset, ++Offset;
    456   return false;
    457 }
    458 
    459 bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset,
    460                               unsigned Length, bool Prologue) {
    461   SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);
    462   ++Offset;
    463   return false;
    464 }
    465 
    466 bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset,
    467                               unsigned Length, bool Prologue) {
    468   SW.startLine() << format("0x%02x                ; nop.w\n", OC[Offset]);
    469   ++Offset;
    470   return false;
    471 }
    472 
    473 bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset,
    474                               unsigned Length, bool Prologue) {
    475   SW.startLine() << format("0x%02x                ; b\n", OC[Offset]);
    476   ++Offset;
    477   return true;
    478 }
    479 
    480 bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset,
    481                               unsigned Length, bool Prologue) {
    482   SW.startLine() << format("0x%02x                ; b.w\n", OC[Offset]);
    483   ++Offset;
    484   return true;
    485 }
    486 
    487 bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset,
    488                               unsigned Length, bool Prologue) {
    489   ++Offset;
    490   return true;
    491 }
    492 
    493 void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
    494                             bool Prologue) {
    495   assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
    496 
    497   bool Terminated = false;
    498   for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
    499     for (unsigned DI = 0;; ++DI) {
    500       if ((Opcodes[OI] & Ring[DI].Mask) == Ring[DI].Value) {
    501         Terminated = (this->*Ring[DI].Routine)(Opcodes.data(), OI, 0, Prologue);
    502         break;
    503       }
    504       assert(DI < array_lengthof(Ring) && "unhandled opcode");
    505     }
    506   }
    507 }
    508 
    509 bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,
    510                               const SectionRef &Section,
    511                               uint64_t FunctionAddress, uint64_t VA) {
    512   ArrayRef<uint8_t> Contents;
    513   if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
    514     return false;
    515 
    516   uint64_t SectionVA = Section.getAddress();
    517   uint64_t Offset = VA - SectionVA;
    518   const ulittle32_t *Data =
    519     reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
    520   const ExceptionDataRecord XData(Data);
    521 
    522   DictScope XRS(SW, "ExceptionData");
    523   SW.printNumber("FunctionLength", XData.FunctionLength() << 1);
    524   SW.printNumber("Version", XData.Vers());
    525   SW.printBoolean("ExceptionData", XData.X());
    526   SW.printBoolean("EpiloguePacked", XData.E());
    527   SW.printBoolean("Fragment", XData.F());
    528   SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",
    529                  XData.EpilogueCount());
    530   SW.printNumber("ByteCodeLength",
    531                  static_cast<uint64_t>(XData.CodeWords() * sizeof(uint32_t)));
    532 
    533   if (XData.E()) {
    534     ArrayRef<uint8_t> UC = XData.UnwindByteCode();
    535     if (!XData.F()) {
    536       ListScope PS(SW, "Prologue");
    537       decodeOpcodes(UC, 0, /*Prologue=*/true);
    538     }
    539     if (XData.EpilogueCount()) {
    540       ListScope ES(SW, "Epilogue");
    541       decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);
    542     }
    543   } else {
    544     ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes();
    545     ListScope ESS(SW, "EpilogueScopes");
    546     for (const EpilogueScope ES : EpilogueScopes) {
    547       DictScope ESES(SW, "EpilogueScope");
    548       SW.printNumber("StartOffset", ES.EpilogueStartOffset());
    549       SW.printNumber("Condition", ES.Condition());
    550       SW.printNumber("EpilogueStartIndex", ES.EpilogueStartIndex());
    551 
    552       ListScope Opcodes(SW, "Opcodes");
    553       decodeOpcodes(XData.UnwindByteCode(), ES.EpilogueStartIndex(),
    554                     /*Prologue=*/false);
    555     }
    556   }
    557 
    558   if (XData.X()) {
    559     const uint32_t Address = XData.ExceptionHandlerRVA();
    560     const uint32_t Parameter = XData.ExceptionHandlerParameter();
    561     const size_t HandlerOffset = HeaderWords(XData)
    562                                + (XData.E() ? 0 : XData.EpilogueCount())
    563                                + XData.CodeWords();
    564 
    565     ErrorOr<SymbolRef> Symbol =
    566       getRelocatedSymbol(COFF, Section, HandlerOffset * sizeof(uint32_t));
    567     if (!Symbol)
    568       Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true);
    569 
    570     ErrorOr<StringRef> Name = Symbol->getName();
    571     if (std::error_code EC = Name.getError())
    572       report_fatal_error(EC.message());
    573 
    574     ListScope EHS(SW, "ExceptionHandler");
    575     SW.printString("Routine", formatSymbol(*Name, Address));
    576     SW.printHex("Parameter", Parameter);
    577   }
    578 
    579   return true;
    580 }
    581 
    582 bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
    583                                 const SectionRef Section, uint64_t Offset,
    584                                 unsigned Index, const RuntimeFunction &RF) {
    585   assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
    586          "packed entry cannot be treated as an unpacked entry");
    587 
    588   ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
    589   if (!Function)
    590     Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
    591 
    592   ErrorOr<SymbolRef> XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4);
    593   if (!XDataRecord)
    594     XDataRecord = getSymbol(COFF, RF.ExceptionInformationRVA());
    595 
    596   if (!RF.BeginAddress && !Function)
    597     return false;
    598   if (!RF.UnwindData && !XDataRecord)
    599     return false;
    600 
    601   StringRef FunctionName;
    602   uint64_t FunctionAddress;
    603   if (Function) {
    604     ErrorOr<StringRef> FunctionNameOrErr = Function->getName();
    605     if (std::error_code EC = FunctionNameOrErr.getError())
    606       report_fatal_error(EC.message());
    607     FunctionName = *FunctionNameOrErr;
    608     ErrorOr<uint64_t> FunctionAddressOrErr = Function->getAddress();
    609     if (std::error_code EC = FunctionAddressOrErr.getError())
    610       report_fatal_error(EC.message());
    611     FunctionAddress = *FunctionAddressOrErr;
    612   } else {
    613     const pe32_header *PEHeader;
    614     if (COFF.getPE32Header(PEHeader))
    615       return false;
    616     FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
    617   }
    618 
    619   SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
    620 
    621   if (XDataRecord) {
    622     ErrorOr<StringRef> Name = XDataRecord->getName();
    623     if (std::error_code EC = Name.getError())
    624       report_fatal_error(EC.message());
    625 
    626     ErrorOr<uint64_t> AddressOrErr = XDataRecord->getAddress();
    627     if (std::error_code EC = AddressOrErr.getError())
    628       report_fatal_error(EC.message());
    629     uint64_t Address = *AddressOrErr;
    630 
    631     SW.printString("ExceptionRecord", formatSymbol(*Name, Address));
    632 
    633     ErrorOr<section_iterator> SIOrErr = XDataRecord->getSection();
    634     if (!SIOrErr)
    635       return false;
    636     section_iterator SI = *SIOrErr;
    637 
    638     return dumpXDataRecord(COFF, *SI, FunctionAddress, Address);
    639   } else {
    640     const pe32_header *PEHeader;
    641     if (COFF.getPE32Header(PEHeader))
    642       return false;
    643 
    644     uint64_t Address = PEHeader->ImageBase + RF.ExceptionInformationRVA();
    645     SW.printString("ExceptionRecord", formatSymbol("", Address));
    646 
    647     ErrorOr<SectionRef> Section =
    648       getSectionContaining(COFF, RF.ExceptionInformationRVA());
    649     if (!Section)
    650       return false;
    651 
    652     return dumpXDataRecord(COFF, *Section, FunctionAddress,
    653                            RF.ExceptionInformationRVA());
    654   }
    655 }
    656 
    657 bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
    658                               const SectionRef Section, uint64_t Offset,
    659                               unsigned Index, const RuntimeFunction &RF) {
    660   assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||
    661           RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
    662          "unpacked entry cannot be treated as a packed entry");
    663 
    664   ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
    665   if (!Function)
    666     Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
    667 
    668   StringRef FunctionName;
    669   uint64_t FunctionAddress;
    670   if (Function) {
    671     ErrorOr<StringRef> FunctionNameOrErr = Function->getName();
    672     if (std::error_code EC = FunctionNameOrErr.getError())
    673       report_fatal_error(EC.message());
    674     FunctionName = *FunctionNameOrErr;
    675     ErrorOr<uint64_t> FunctionAddressOrErr = Function->getAddress();
    676     FunctionAddress = *FunctionAddressOrErr;
    677   } else {
    678     const pe32_header *PEHeader;
    679     if (COFF.getPE32Header(PEHeader))
    680       return false;
    681     FunctionAddress = PEHeader->ImageBase + RF.BeginAddress;
    682   }
    683 
    684   SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
    685   SW.printBoolean("Fragment",
    686                   RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
    687   SW.printNumber("FunctionLength", RF.FunctionLength());
    688   SW.startLine() << "ReturnType: " << RF.Ret() << '\n';
    689   SW.printBoolean("HomedParameters", RF.H());
    690   SW.startLine() << "SavedRegisters: ";
    691                  printRegisters(SavedRegisterMask(RF));
    692   OS << '\n';
    693   SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);
    694 
    695   return true;
    696 }
    697 
    698 bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,
    699                                      const SectionRef Section, unsigned Index,
    700                                      ArrayRef<uint8_t> Contents) {
    701   uint64_t Offset = PDataEntrySize * Index;
    702   const ulittle32_t *Data =
    703     reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);
    704 
    705   const RuntimeFunction Entry(Data);
    706   DictScope RFS(SW, "RuntimeFunction");
    707   if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)
    708     return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);
    709   return dumpPackedEntry(COFF, Section, Offset, Index, Entry);
    710 }
    711 
    712 void Decoder::dumpProcedureData(const COFFObjectFile &COFF,
    713                                 const SectionRef Section) {
    714   ArrayRef<uint8_t> Contents;
    715   if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))
    716     return;
    717 
    718   if (Contents.size() % PDataEntrySize) {
    719     errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n";
    720     return;
    721   }
    722 
    723   for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI)
    724     if (!dumpProcedureDataEntry(COFF, Section, EI, Contents))
    725       break;
    726 }
    727 
    728 std::error_code Decoder::dumpProcedureData(const COFFObjectFile &COFF) {
    729   for (const auto &Section : COFF.sections()) {
    730     StringRef SectionName;
    731     if (std::error_code EC =
    732             COFF.getSectionName(COFF.getCOFFSection(Section), SectionName))
    733       return EC;
    734 
    735     if (SectionName.startswith(".pdata"))
    736       dumpProcedureData(COFF, Section);
    737   }
    738   return std::error_code();
    739 }
    740 }
    741 }
    742 }
    743