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