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