brintos

brintos / llvm-project-archived public Read only

0
0
Text · 55.0 KiB · b21a550 Raw
1537 lines · cpp
1//===-- ARMWinEHPrinter.cpp - Windows on ARM EH Data Printer ----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// Windows on ARM uses a series of serialised data structures (RuntimeFunction)10// to create a table of information for unwinding.  In order to conserve space,11// there are two different ways that this data is represented.12//13// For functions with canonical forms for the prologue and epilogue, the data14// can be stored in a "packed" form.  In this case, the data is packed into the15// RuntimeFunction's remaining 30-bits and can fully describe the entire frame.16//17//        +---------------------------------------+18//        |         Function Entry Address        |19//        +---------------------------------------+20//        |           Packed Form Data            |21//        +---------------------------------------+22//23// This layout is parsed by Decoder::dumpPackedEntry.  No unwind bytecode is24// associated with such a frame as they can be derived from the provided data.25// The decoder does not synthesize this data as it is unnecessary for the26// purposes of validation, with the synthesis being required only by a proper27// unwinder.28//29// For functions that are large or do not match canonical forms, the data is30// split up into two portions, with the actual data residing in the "exception31// data" table (.xdata) with a reference to the entry from the "procedure data"32// (.pdata) entry.33//34// The exception data contains information about the frame setup, all of the35// epilogue scopes (for functions for which there are multiple exit points) and36// the associated exception handler.  Additionally, the entry contains byte-code37// describing how to unwind the function (c.f. Decoder::decodeOpcodes).38//39//        +---------------------------------------+40//        |         Function Entry Address        |41//        +---------------------------------------+42//        |      Exception Data Entry Address     |43//        +---------------------------------------+44//45// This layout is parsed by Decoder::dumpUnpackedEntry.  Such an entry must46// first resolve the exception data entry address.  This structure47// (ExceptionDataRecord) has a variable sized header48// (c.f. ARM::WinEH::HeaderWords) and encodes most of the same information as49// the packed form.  However, because this information is insufficient to50// synthesize the unwinding, there are associated unwinding bytecode which make51// up the bulk of the Decoder.52//53// The decoder itself is table-driven, using the first byte to determine the54// opcode and dispatching to the associated printing routine.  The bytecode55// itself is a variable length instruction encoding that can fully describe the56// state of the stack and the necessary operations for unwinding to the57// beginning of the frame.58//59// The byte-code maintains a 1-1 instruction mapping, indicating both the width60// of the instruction (Thumb2 instructions are variable length, 16 or 32 bits61// wide) allowing the program to unwind from any point in the prologue, body, or62// epilogue of the function.63 64#include "ARMWinEHPrinter.h"65#include "llvm/ADT/STLExtras.h"66#include "llvm/ADT/StringExtras.h"67#include "llvm/Support/ARMWinEH.h"68#include "llvm/Support/Format.h"69 70using namespace llvm;71using namespace llvm::object;72using namespace llvm::support;73 74namespace llvm {75raw_ostream &operator<<(raw_ostream &OS, const ARM::WinEH::ReturnType &RT) {76  switch (RT) {77  case ARM::WinEH::ReturnType::RT_POP:78    OS << "pop {pc}";79    break;80  case ARM::WinEH::ReturnType::RT_B:81    OS << "bx <reg>";82    break;83  case ARM::WinEH::ReturnType::RT_BW:84    OS << "b.w <target>";85    break;86  case ARM::WinEH::ReturnType::RT_NoEpilogue:87    OS << "(no epilogue)";88    break;89  }90  return OS;91}92}93 94static std::string formatSymbol(StringRef Name, uint64_t Address,95                                uint64_t Offset = 0) {96  std::string Buffer;97  raw_string_ostream OS(Buffer);98 99  if (!Name.empty())100    OS << Name << " ";101 102  if (Offset)103    OS << format("+0x%" PRIX64 " (0x%" PRIX64 ")", Offset, Address);104  else if (!Name.empty())105    OS << format("(0x%" PRIX64 ")", Address);106  else107    OS << format("0x%" PRIX64, Address);108 109  return Buffer;110}111 112namespace llvm {113namespace ARM {114namespace WinEH {115const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction);116 117// TODO name the uops more appropriately118const Decoder::RingEntry Decoder::Ring[] = {119  { 0x80, 0x00, 1, &Decoder::opcode_0xxxxxxx },  // UOP_STACK_FREE (16-bit)120  { 0xc0, 0x80, 2, &Decoder::opcode_10Lxxxxx },  // UOP_POP (32-bit)121  { 0xf0, 0xc0, 1, &Decoder::opcode_1100xxxx },  // UOP_STACK_SAVE (16-bit)122  { 0xf8, 0xd0, 1, &Decoder::opcode_11010Lxx },  // UOP_POP (16-bit)123  { 0xf8, 0xd8, 1, &Decoder::opcode_11011Lxx },  // UOP_POP (32-bit)124  { 0xf8, 0xe0, 1, &Decoder::opcode_11100xxx },  // UOP_VPOP (32-bit)125  { 0xfc, 0xe8, 2, &Decoder::opcode_111010xx },  // UOP_STACK_FREE (32-bit)126  { 0xfe, 0xec, 2, &Decoder::opcode_1110110L },  // UOP_POP (16-bit)127  { 0xff, 0xee, 2, &Decoder::opcode_11101110 },  // UOP_MICROSOFT_SPECIFIC (16-bit)128                                              // UOP_PUSH_MACHINE_FRAME129                                              // UOP_PUSH_CONTEXT130                                              // UOP_PUSH_TRAP_FRAME131                                              // UOP_REDZONE_RESTORE_LR132  { 0xff, 0xef, 2, &Decoder::opcode_11101111 },  // UOP_LDRPC_POSTINC (32-bit)133  { 0xff, 0xf5, 2, &Decoder::opcode_11110101 },  // UOP_VPOP (32-bit)134  { 0xff, 0xf6, 2, &Decoder::opcode_11110110 },  // UOP_VPOP (32-bit)135  { 0xff, 0xf7, 3, &Decoder::opcode_11110111 },  // UOP_STACK_RESTORE (16-bit)136  { 0xff, 0xf8, 4, &Decoder::opcode_11111000 },  // UOP_STACK_RESTORE (16-bit)137  { 0xff, 0xf9, 3, &Decoder::opcode_11111001 },  // UOP_STACK_RESTORE (32-bit)138  { 0xff, 0xfa, 4, &Decoder::opcode_11111010 },  // UOP_STACK_RESTORE (32-bit)139  { 0xff, 0xfb, 1, &Decoder::opcode_11111011 },  // UOP_NOP (16-bit)140  { 0xff, 0xfc, 1, &Decoder::opcode_11111100 },  // UOP_NOP (32-bit)141  { 0xff, 0xfd, 1, &Decoder::opcode_11111101 },  // UOP_NOP (16-bit) / END142  { 0xff, 0xfe, 1, &Decoder::opcode_11111110 },  // UOP_NOP (32-bit) / END143  { 0xff, 0xff, 1, &Decoder::opcode_11111111 },  // UOP_END144};145 146// Unwind opcodes for ARM64.147// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling148const Decoder::RingEntry Decoder::Ring64[] = {149    {0xe0, 0x00, 1, &Decoder::opcode_alloc_s},150    {0xe0, 0x20, 1, &Decoder::opcode_save_r19r20_x},151    {0xc0, 0x40, 1, &Decoder::opcode_save_fplr},152    {0xc0, 0x80, 1, &Decoder::opcode_save_fplr_x},153    {0xf8, 0xc0, 2, &Decoder::opcode_alloc_m},154    {0xfc, 0xc8, 2, &Decoder::opcode_save_regp},155    {0xfc, 0xcc, 2, &Decoder::opcode_save_regp_x},156    {0xfc, 0xd0, 2, &Decoder::opcode_save_reg},157    {0xfe, 0xd4, 2, &Decoder::opcode_save_reg_x},158    {0xfe, 0xd6, 2, &Decoder::opcode_save_lrpair},159    {0xfe, 0xd8, 2, &Decoder::opcode_save_fregp},160    {0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x},161    {0xfe, 0xdc, 2, &Decoder::opcode_save_freg},162    {0xff, 0xde, 2, &Decoder::opcode_save_freg_x},163    {0xff, 0xdf, 2, &Decoder::opcode_alloc_z},164    {0xff, 0xe0, 4, &Decoder::opcode_alloc_l},165    {0xff, 0xe1, 1, &Decoder::opcode_setfp},166    {0xff, 0xe2, 2, &Decoder::opcode_addfp},167    {0xff, 0xe3, 1, &Decoder::opcode_nop},168    {0xff, 0xe4, 1, &Decoder::opcode_end},169    {0xff, 0xe5, 1, &Decoder::opcode_end_c},170    {0xff, 0xe6, 1, &Decoder::opcode_save_next},171    {0xff, 0xe7, 3, &Decoder::opcode_e7},172    {0xff, 0xe8, 1, &Decoder::opcode_trap_frame},173    {0xff, 0xe9, 1, &Decoder::opcode_machine_frame},174    {0xff, 0xea, 1, &Decoder::opcode_context},175    {0xff, 0xeb, 1, &Decoder::opcode_ec_context},176    {0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call},177    {0xff, 0xfc, 1, &Decoder::opcode_pac_sign_lr},178};179 180static void printRange(raw_ostream &OS, ListSeparator &LS, unsigned First,181                       unsigned Last, char Letter) {182  if (First == Last)183    OS << LS << Letter << First;184  else185    OS << LS << Letter << First << "-" << Letter << Last;186}187 188static void printRange(raw_ostream &OS, uint32_t Mask, ListSeparator &LS,189                       unsigned Start, unsigned End, char Letter) {190  int First = -1;191  for (unsigned RI = Start; RI <= End; ++RI) {192    if (Mask & (1 << RI)) {193      if (First < 0)194        First = RI;195    } else {196      if (First >= 0) {197        printRange(OS, LS, First, RI - 1, Letter);198        First = -1;199      }200    }201  }202  if (First >= 0)203    printRange(OS, LS, First, End, Letter);204}205 206void Decoder::printGPRMask(uint16_t GPRMask) {207  OS << '{';208  ListSeparator LS;209  printRange(OS, GPRMask, LS, 0, 12, 'r');210  if (GPRMask & (1 << 14))211    OS << LS << "lr";212  if (GPRMask & (1 << 15))213    OS << LS << "pc";214  OS << '}';215}216 217void Decoder::printVFPMask(uint32_t VFPMask) {218  OS << '{';219  ListSeparator LS;220  printRange(OS, VFPMask, LS, 0, 31, 'd');221  OS << '}';222}223 224ErrorOr<object::SectionRef>225Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) {226  for (const auto &Section : COFF.sections()) {227    uint64_t Address = Section.getAddress();228    uint64_t Size = Section.getSize();229 230    if (VA >= Address && (VA - Address) <= Size)231      return Section;232  }233  return inconvertibleErrorCode();234}235 236ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF,237                                              uint64_t VA, bool FunctionOnly) {238  for (const auto &Symbol : COFF.symbols()) {239    Expected<SymbolRef::Type> Type = Symbol.getType();240    if (!Type)241      return errorToErrorCode(Type.takeError());242    if (FunctionOnly && *Type != SymbolRef::ST_Function)243      continue;244 245    Expected<uint64_t> Address = Symbol.getAddress();246    if (!Address)247      return errorToErrorCode(Address.takeError());248    if (*Address == VA)249      return Symbol;250  }251  return inconvertibleErrorCode();252}253 254ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &,255                                               const SectionRef &Section,256                                               uint64_t Offset) {257  for (const auto &Relocation : Section.relocations()) {258    uint64_t RelocationOffset = Relocation.getOffset();259    if (RelocationOffset == Offset)260      return *Relocation.getSymbol();261  }262  return inconvertibleErrorCode();263}264 265SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF, SymbolRef Sym,266                                      uint64_t &SymbolOffset) {267  // The symbol resolved by getRelocatedSymbol can be any internal268  // nondescriptive symbol; try to resolve a more descriptive one.269  COFFSymbolRef CoffSym = COFF.getCOFFSymbol(Sym);270  if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL &&271      CoffSym.getSectionDefinition() == nullptr)272    return Sym;273  for (const auto &S : COFF.symbols()) {274    COFFSymbolRef CS = COFF.getCOFFSymbol(S);275    if (CS.getSectionNumber() == CoffSym.getSectionNumber() &&276        CS.getValue() <= CoffSym.getValue() + SymbolOffset &&277        CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL &&278        CS.getSectionDefinition() == nullptr) {279      uint32_t Offset = CoffSym.getValue() + SymbolOffset - CS.getValue();280      if (Offset <= SymbolOffset) {281        SymbolOffset = Offset;282        Sym = S;283        CoffSym = CS;284        if (CS.isExternal() && SymbolOffset == 0)285          return Sym;286      }287    }288  }289  return Sym;290}291 292ErrorOr<SymbolRef> Decoder::getSymbolForLocation(293    const COFFObjectFile &COFF, const SectionRef &Section,294    uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress,295    uint64_t &SymbolOffset, bool FunctionOnly) {296  // Try to locate a relocation that points at the offset in the section297  ErrorOr<SymbolRef> SymOrErr =298      getRelocatedSymbol(COFF, Section, OffsetInSection);299  if (SymOrErr) {300    // We found a relocation symbol; the immediate offset needs to be added301    // to the symbol address.302    SymbolOffset = ImmediateOffset;303 304    Expected<uint64_t> AddressOrErr = SymOrErr->getAddress();305    if (!AddressOrErr) {306      std::string Buf;307      llvm::raw_string_ostream OS(Buf);308      logAllUnhandledErrors(AddressOrErr.takeError(), OS);309      reportFatalUsageError(Twine(Buf));310    }311    // We apply SymbolOffset here directly. We return it separately to allow312    // the caller to print it as an offset on the symbol name.313    SymbolAddress = *AddressOrErr + SymbolOffset;314 315    if (FunctionOnly) // Resolve label/section symbols into function names.316      SymOrErr = getPreferredSymbol(COFF, *SymOrErr, SymbolOffset);317  } else {318    // No matching relocation found; operating on a linked image. Try to319    // find a descriptive symbol if possible. The immediate offset contains320    // the image relative address, and we shouldn't add any offset to the321    // symbol.322    SymbolAddress = COFF.getImageBase() + ImmediateOffset;323    SymbolOffset = 0;324    SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly);325  }326  return SymOrErr;327}328 329bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset,330                              unsigned Length, bool Prologue) {331  uint8_t Imm = OC[Offset] & 0x7f;332  SW.startLine() << format("0x%02x                ; %s sp, #(%u * 4)\n",333                           OC[Offset],334                           static_cast<const char *>(Prologue ? "sub" : "add"),335                           Imm);336  ++Offset;337  return false;338}339 340bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset,341                              unsigned Length, bool Prologue) {342  unsigned Link = (OC[Offset] & 0x20) >> 5;343  uint16_t RegisterMask = (Link << (Prologue ? 14 : 15))344                        | ((OC[Offset + 0] & 0x1f) << 8)345                        | ((OC[Offset + 1] & 0xff) << 0);346  assert((~RegisterMask & (1 << 13)) && "sp must not be set");347  assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set");348 349  SW.startLine() << format("0x%02x 0x%02x           ; %s.w ",350                           OC[Offset + 0], OC[Offset + 1],351                           Prologue ? "push" : "pop");352  printGPRMask(RegisterMask);353  OS << '\n';354 355  Offset += 2;356  return false;357}358 359bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset,360                              unsigned Length, bool Prologue) {361  if (Prologue)362    SW.startLine() << format("0x%02x                ; mov r%u, sp\n",363                             OC[Offset], OC[Offset] & 0xf);364  else365    SW.startLine() << format("0x%02x                ; mov sp, r%u\n",366                             OC[Offset], OC[Offset] & 0xf);367  ++Offset;368  return false;369}370 371bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset,372                              unsigned Length, bool Prologue) {373  unsigned Link = (OC[Offset] & 0x4) >> 2;374  unsigned Count = (OC[Offset] & 0x3);375 376  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))377                   | (((1 << (Count + 1)) - 1) << 4);378 379  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],380                           Prologue ? "push" : "pop");381  printGPRMask(GPRMask);382  OS << '\n';383 384  ++Offset;385  return false;386}387 388bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset,389                              unsigned Length, bool Prologue) {390  unsigned Link = (OC[Offset] & 0x4) >> 2;391  unsigned Count = (OC[Offset] & 0x3) + 4;392 393  uint16_t GPRMask = (Link << (Prologue ? 14 : 15))394                   | (((1 << (Count + 1)) - 1) << 4);395 396  SW.startLine() << format("0x%02x                ; %s.w ", OC[Offset],397                           Prologue ? "push" : "pop");398  printGPRMask(GPRMask);399  OS << '\n';400 401  ++Offset;402  return false;403}404 405bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset,406                              unsigned Length, bool Prologue) {407  unsigned High = (OC[Offset] & 0x7);408  uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8);409 410  SW.startLine() << format("0x%02x                ; %s ", OC[Offset],411                           Prologue ? "vpush" : "vpop");412  printVFPMask(VFPMask);413  OS << '\n';414 415  ++Offset;416  return false;417}418 419bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset,420                              unsigned Length, bool Prologue) {421  uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0);422 423  SW.startLine() << format("0x%02x 0x%02x           ; %s.w sp, #(%u * 4)\n",424                           OC[Offset + 0], OC[Offset + 1],425                           static_cast<const char *>(Prologue ? "sub" : "add"),426                           Imm);427 428  Offset += 2;429  return false;430}431 432bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset,433                              unsigned Length, bool Prologue) {434  uint16_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15))435                   | ((OC[Offset + 1] & 0xff) << 0);436 437  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],438                           OC[Offset + 1], Prologue ? "push" : "pop");439  printGPRMask(GPRMask);440  OS << '\n';441 442  Offset += 2;443  return false;444}445 446bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset,447                              unsigned Length, bool Prologue) {448  assert(!Prologue && "may not be used in prologue");449 450  if (OC[Offset + 1] & 0xf0)451    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",452                             OC[Offset + 0], OC[Offset +  1]);453  else454    SW.startLine()455      << format("0x%02x 0x%02x           ; microsoft-specific (type: %u)\n",456                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f);457 458  Offset += 2;459  return false;460}461 462bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset,463                              unsigned Length, bool Prologue) {464  if (OC[Offset + 1] & 0xf0)465    SW.startLine() << format("0x%02x 0x%02x           ; reserved\n",466                             OC[Offset + 0], OC[Offset +  1]);467  else if (Prologue)468    SW.startLine()469      << format("0x%02x 0x%02x           ; str.w lr, [sp, #-%u]!\n",470                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);471  else472    SW.startLine()473      << format("0x%02x 0x%02x           ; ldr.w lr, [sp], #%u\n",474                OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2);475 476  Offset += 2;477  return false;478}479 480bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset,481                              unsigned Length, bool Prologue) {482  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;483  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;484  uint32_t VFPMask = ((1 << (End + 1 - Start)) - 1) << Start;485 486  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],487                           OC[Offset + 1], Prologue ? "vpush" : "vpop");488  printVFPMask(VFPMask);489  OS << '\n';490 491  Offset += 2;492  return false;493}494 495bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset,496                              unsigned Length, bool Prologue) {497  unsigned Start = (OC[Offset + 1] & 0xf0) >> 4;498  unsigned End = (OC[Offset + 1] & 0x0f) >> 0;499  uint32_t VFPMask = ((1 << (End + 1 - Start)) - 1) << (16 + Start);500 501  SW.startLine() << format("0x%02x 0x%02x           ; %s ", OC[Offset + 0],502                           OC[Offset + 1], Prologue ? "vpush" : "vpop");503  printVFPMask(VFPMask);504  OS << '\n';505 506  Offset += 2;507  return false;508}509 510bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset,511                              unsigned Length, bool Prologue) {512  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);513 514  SW.startLine() << format("0x%02x 0x%02x 0x%02x      ; %s sp, sp, #(%u * 4)\n",515                           OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],516                           static_cast<const char *>(Prologue ? "sub" : "add"),517                           Imm);518 519  Offset += 3;520  return false;521}522 523bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset,524                              unsigned Length, bool Prologue) {525  uint32_t Imm = (OC[Offset + 1] << 16)526               | (OC[Offset + 2] << 8)527               | (OC[Offset + 3] << 0);528 529  SW.startLine()530    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n",531              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],532              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);533 534  Offset += 4;535  return false;536}537 538bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset,539                              unsigned Length, bool Prologue) {540  uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0);541 542  SW.startLine()543    << format("0x%02x 0x%02x 0x%02x      ; %s.w sp, sp, #(%u * 4)\n",544              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2],545              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);546 547  Offset += 3;548  return false;549}550 551bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset,552                              unsigned Length, bool Prologue) {553  uint32_t Imm = (OC[Offset + 1] << 16)554               | (OC[Offset + 2] << 8)555               | (OC[Offset + 3] << 0);556 557  SW.startLine()558    << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n",559              OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3],560              static_cast<const char *>(Prologue ? "sub" : "add"), Imm);561 562  Offset += 4;563  return false;564}565 566bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset,567                              unsigned Length, bool Prologue) {568  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);569  ++Offset;570  return false;571}572 573bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset,574                              unsigned Length, bool Prologue) {575  SW.startLine() << format("0x%02x                ; nop.w\n", OC[Offset]);576  ++Offset;577  return false;578}579 580bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset,581                              unsigned Length, bool Prologue) {582  SW.startLine() << format("0x%02x                ; bx <reg>\n", OC[Offset]);583  ++Offset;584  return true;585}586 587bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset,588                              unsigned Length, bool Prologue) {589  SW.startLine() << format("0x%02x                ; b.w <target>\n", OC[Offset]);590  ++Offset;591  return true;592}593 594bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset,595                              unsigned Length, bool Prologue) {596  ++Offset;597  return true;598}599 600// ARM64 unwind codes start here.601bool Decoder::opcode_alloc_s(const uint8_t *OC, unsigned &Offset,602                             unsigned Length, bool Prologue) {603  uint32_t NumBytes = (OC[Offset] & 0x1F) << 4;604  SW.startLine() << format("0x%02x                ; %s sp, #%u\n", OC[Offset],605                           static_cast<const char *>(Prologue ? "sub" : "add"),606                           NumBytes);607  ++Offset;608  return false;609}610 611bool Decoder::opcode_save_r19r20_x(const uint8_t *OC, unsigned &Offset,612                                   unsigned Length, bool Prologue) {613  uint32_t Off = (OC[Offset] & 0x1F) << 3;614  if (Prologue)615    SW.startLine() << format(616        "0x%02x                ; stp x19, x20, [sp, #-%u]!\n", OC[Offset], Off);617  else618    SW.startLine() << format(619        "0x%02x                ; ldp x19, x20, [sp], #%u\n", OC[Offset], Off);620  ++Offset;621  return false;622}623 624bool Decoder::opcode_save_fplr(const uint8_t *OC, unsigned &Offset,625                               unsigned Length, bool Prologue) {626  uint32_t Off = (OC[Offset] & 0x3F) << 3;627  SW.startLine() << format(628      "0x%02x                ; %s x29, x30, [sp, #%u]\n", OC[Offset],629      static_cast<const char *>(Prologue ? "stp" : "ldp"), Off);630  ++Offset;631  return false;632}633 634bool Decoder::opcode_save_fplr_x(const uint8_t *OC, unsigned &Offset,635                                 unsigned Length, bool Prologue) {636  uint32_t Off = ((OC[Offset] & 0x3F) + 1) << 3;637  if (Prologue)638    SW.startLine() << format(639        "0x%02x                ; stp x29, x30, [sp, #-%u]!\n", OC[Offset], Off);640  else641    SW.startLine() << format(642        "0x%02x                ; ldp x29, x30, [sp], #%u\n", OC[Offset], Off);643  ++Offset;644  return false;645}646 647bool Decoder::opcode_alloc_m(const uint8_t *OC, unsigned &Offset,648                             unsigned Length, bool Prologue) {649  uint32_t NumBytes = ((OC[Offset] & 0x07) << 8);650  NumBytes |= (OC[Offset + 1] & 0xFF);651  NumBytes <<= 4;652  SW.startLine() << format("0x%02x%02x              ; %s sp, #%u\n",653                           OC[Offset], OC[Offset + 1],654                           static_cast<const char *>(Prologue ? "sub" : "add"),655                           NumBytes);656  Offset += 2;657  return false;658}659 660bool Decoder::opcode_save_regp(const uint8_t *OC, unsigned &Offset,661                               unsigned Length, bool Prologue) {662  uint32_t Reg = ((OC[Offset] & 0x03) << 8);663  Reg |= (OC[Offset + 1] & 0xC0);664  Reg >>= 6;665  Reg += 19;666  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;667  SW.startLine() << format(668      "0x%02x%02x              ; %s x%u, x%u, [sp, #%u]\n",669      OC[Offset], OC[Offset + 1],670      static_cast<const char *>(Prologue ? "stp" : "ldp"), Reg, Reg + 1, Off);671  Offset += 2;672  return false;673}674 675bool Decoder::opcode_save_regp_x(const uint8_t *OC, unsigned &Offset,676                                 unsigned Length, bool Prologue) {677  uint32_t Reg = ((OC[Offset] & 0x03) << 8);678  Reg |= (OC[Offset + 1] & 0xC0);679  Reg >>= 6;680  Reg += 19;681  uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;682  if (Prologue)683    SW.startLine() << format(684        "0x%02x%02x              ; stp x%u, x%u, [sp, #-%u]!\n",685        OC[Offset], OC[Offset + 1], Reg,686        Reg + 1, Off);687  else688    SW.startLine() << format(689        "0x%02x%02x              ; ldp x%u, x%u, [sp], #%u\n",690        OC[Offset], OC[Offset + 1], Reg,691        Reg + 1, Off);692  Offset += 2;693  return false;694}695 696bool Decoder::opcode_save_reg(const uint8_t *OC, unsigned &Offset,697                              unsigned Length, bool Prologue) {698  uint32_t Reg = (OC[Offset] & 0x03) << 8;699  Reg |= (OC[Offset + 1] & 0xC0);700  Reg >>= 6;701  Reg += 19;702  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;703  SW.startLine() << format("0x%02x%02x              ; %s x%u, [sp, #%u]\n",704                           OC[Offset], OC[Offset + 1],705                           static_cast<const char *>(Prologue ? "str" : "ldr"),706                           Reg, Off);707  Offset += 2;708  return false;709}710 711bool Decoder::opcode_save_reg_x(const uint8_t *OC, unsigned &Offset,712                                unsigned Length, bool Prologue) {713  uint32_t Reg = (OC[Offset] & 0x01) << 8;714  Reg |= (OC[Offset + 1] & 0xE0);715  Reg >>= 5;716  Reg += 19;717  uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;718  if (Prologue)719    SW.startLine() << format("0x%02x%02x              ; str x%u, [sp, #-%u]!\n",720                             OC[Offset], OC[Offset + 1], Reg, Off);721  else722    SW.startLine() << format("0x%02x%02x              ; ldr x%u, [sp], #%u\n",723                             OC[Offset], OC[Offset + 1], Reg, Off);724  Offset += 2;725  return false;726}727 728bool Decoder::opcode_save_lrpair(const uint8_t *OC, unsigned &Offset,729                                 unsigned Length, bool Prologue) {730  uint32_t Reg = (OC[Offset] & 0x01) << 8;731  Reg |= (OC[Offset + 1] & 0xC0);732  Reg >>= 6;733  Reg *= 2;734  Reg += 19;735  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;736  SW.startLine() << format("0x%02x%02x              ; %s x%u, lr, [sp, #%u]\n",737                           OC[Offset], OC[Offset + 1],738                           static_cast<const char *>(Prologue ? "stp" : "ldp"),739                           Reg, Off);740  Offset += 2;741  return false;742}743 744bool Decoder::opcode_save_fregp(const uint8_t *OC, unsigned &Offset,745                                unsigned Length, bool Prologue) {746  uint32_t Reg = (OC[Offset] & 0x01) << 8;747  Reg |= (OC[Offset + 1] & 0xC0);748  Reg >>= 6;749  Reg += 8;750  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;751  SW.startLine() << format("0x%02x%02x              ; %s d%u, d%u, [sp, #%u]\n",752                           OC[Offset], OC[Offset + 1],753                           static_cast<const char *>(Prologue ? "stp" : "ldp"),754                           Reg, Reg + 1, Off);755  Offset += 2;756  return false;757}758 759bool Decoder::opcode_save_fregp_x(const uint8_t *OC, unsigned &Offset,760                                  unsigned Length, bool Prologue) {761  uint32_t Reg = (OC[Offset] & 0x01) << 8;762  Reg |= (OC[Offset + 1] & 0xC0);763  Reg >>= 6;764  Reg += 8;765  uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3;766  if (Prologue)767    SW.startLine() << format(768        "0x%02x%02x              ; stp d%u, d%u, [sp, #-%u]!\n", OC[Offset],769        OC[Offset + 1], Reg, Reg + 1, Off);770  else771    SW.startLine() << format(772        "0x%02x%02x              ; ldp d%u, d%u, [sp], #%u\n", OC[Offset],773        OC[Offset + 1], Reg, Reg + 1, Off);774  Offset += 2;775  return false;776}777 778bool Decoder::opcode_save_freg(const uint8_t *OC, unsigned &Offset,779                               unsigned Length, bool Prologue) {780  uint32_t Reg = (OC[Offset] & 0x01) << 8;781  Reg |= (OC[Offset + 1] & 0xC0);782  Reg >>= 6;783  Reg += 8;784  uint32_t Off = (OC[Offset + 1] & 0x3F) << 3;785  SW.startLine() << format("0x%02x%02x              ; %s d%u, [sp, #%u]\n",786                           OC[Offset], OC[Offset + 1],787                           static_cast<const char *>(Prologue ? "str" : "ldr"),788                           Reg, Off);789  Offset += 2;790  return false;791}792 793bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset,794                                 unsigned Length, bool Prologue) {795  uint32_t Reg = ((OC[Offset + 1] & 0xE0) >> 5) + 8;796  uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3;797  if (Prologue)798    SW.startLine() << format(799        "0x%02x%02x              ; str d%u, [sp, #-%u]!\n", OC[Offset],800        OC[Offset + 1], Reg, Off);801  else802    SW.startLine() << format(803        "0x%02x%02x              ; ldr d%u, [sp], #%u\n", OC[Offset],804        OC[Offset + 1], Reg, Off);805  Offset += 2;806  return false;807}808 809bool Decoder::opcode_alloc_z(const uint8_t *OC, unsigned &Offset,810                             unsigned Length, bool Prologue) {811  unsigned Off = OC[Offset + 1];812  SW.startLine() << format("0x%02x%02x              ; addvl sp, #%d\n",813                           OC[Offset], OC[Offset + 1],814                           Prologue ? -(int)Off : (int)Off);815  Offset += 2;816  return false;817}818 819bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset,820                             unsigned Length, bool Prologue) {821  unsigned Off =822      (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) | (OC[Offset + 3] << 0);823  Off <<= 4;824  SW.startLine() << format(825      "0x%02x%02x%02x%02x          ; %s sp, #%u\n", OC[Offset], OC[Offset + 1],826      OC[Offset + 2], OC[Offset + 3],827      static_cast<const char *>(Prologue ? "sub" : "add"), Off);828  Offset += 4;829  return false;830}831 832bool Decoder::opcode_setfp(const uint8_t *OC, unsigned &Offset, unsigned Length,833                           bool Prologue) {834  SW.startLine() << format("0x%02x                ; mov %s, %s\n", OC[Offset],835                           static_cast<const char *>(Prologue ? "fp" : "sp"),836                           static_cast<const char *>(Prologue ? "sp" : "fp"));837  ++Offset;838  return false;839}840 841bool Decoder::opcode_addfp(const uint8_t *OC, unsigned &Offset, unsigned Length,842                           bool Prologue) {843  unsigned NumBytes = OC[Offset + 1] << 3;844  SW.startLine() << format(845      "0x%02x%02x              ; %s %s, %s, #%u\n", OC[Offset], OC[Offset + 1],846      static_cast<const char *>(Prologue ? "add" : "sub"),847      static_cast<const char *>(Prologue ? "fp" : "sp"),848      static_cast<const char *>(Prologue ? "sp" : "fp"), NumBytes);849  Offset += 2;850  return false;851}852 853bool Decoder::opcode_nop(const uint8_t *OC, unsigned &Offset, unsigned Length,854                         bool Prologue) {855  SW.startLine() << format("0x%02x                ; nop\n", OC[Offset]);856  ++Offset;857  return false;858}859 860bool Decoder::opcode_end(const uint8_t *OC, unsigned &Offset, unsigned Length,861                         bool Prologue) {862  SW.startLine() << format("0x%02x                ; end\n", OC[Offset]);863  ++Offset;864  return true;865}866 867bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length,868                           bool Prologue) {869  SW.startLine() << format("0x%02x                ; end_c\n", OC[Offset]);870  ++Offset;871  return false;872}873 874bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,875                               unsigned Length, bool Prologue) {876  if (Prologue)877    SW.startLine() << format("0x%02x                ; save next\n", OC[Offset]);878  else879    SW.startLine() << format("0x%02x                ; restore next\n",880                             OC[Offset]);881  ++Offset;882  return false;883}884 885bool Decoder::opcode_e7(const uint8_t *OC, unsigned &Offset, unsigned Length,886                        bool Prologue) {887  // The e7 opcode has unusual decoding rules; write out the logic.888  if ((OC[Offset + 1] & 0x80) == 0x80) {889    SW.getOStream() << "reserved encoding\n";890    Offset += 3;891    return false;892  }893 894  if ((OC[Offset + 2] & 0xC0) == 0xC0) {895    if ((OC[Offset + 1] & 0x10) == 0)896      return opcode_save_zreg(OC, Offset, Length, Prologue);897    return opcode_save_preg(OC, Offset, Length, Prologue);898  }899 900  return opcode_save_any_reg(OC, Offset, Length, Prologue);901}902 903bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset,904                                  unsigned Length, bool Prologue) {905  // Whether the instruction has writeback906  bool Writeback = (OC[Offset + 1] & 0x20) == 0x20;907  // Whether the instruction is paired.  (Paired instructions are required908  // to save/restore adjacent registers.)909  bool Paired = (OC[Offset + 1] & 0x40) == 0x40;910  // The kind of register saved:911  // - 0 is an x register912  // - 1 is the low half of a q register913  // - 2 is a whole q register914  int RegKind = (OC[Offset + 2] & 0xC0) >> 6;915  // Encoded register name (0 -> x0/q0, 1 -> x1/q1, etc.)916  int Reg = OC[Offset + 1] & 0x1F;917  // Encoded stack offset of load/store instruction; decoding varies by mode.918  int StackOffset = OC[Offset + 2] & 0x3F;919  if (Writeback)920    StackOffset++;921  if (!Writeback && !Paired && RegKind != 2)922    StackOffset *= 8;923  else924    StackOffset *= 16;925 926  SW.startLine() << format("0x%02x%02x%02x            ; ", OC[Offset],927                           OC[Offset + 1], OC[Offset + 2]);928 929  // Verify the encoding is in a form we understand.  The high bit of the first930  // byte, and mode 3 for the register kind are apparently reserved.  The931  // encoded register must refer to a valid register.932  int MaxReg = 0x1F;933  if (Paired)934    --MaxReg;935  if (RegKind == 0)936    --MaxReg;937  if ((OC[Offset + 1] & 0x80) == 0x80 || RegKind == 3 || Reg > MaxReg) {938    SW.getOStream() << "invalid save_any_reg encoding\n";939    Offset += 3;940    return false;941  }942 943  if (Paired) {944    if (Prologue)945      SW.getOStream() << "stp ";946    else947      SW.getOStream() << "ldp ";948  } else {949    if (Prologue)950      SW.getOStream() << "str ";951    else952      SW.getOStream() << "ldr ";953  }954 955  char RegChar = 'x';956  if (RegKind == 1) {957    RegChar = 'd';958  } else if (RegKind == 2) {959    RegChar = 'q';960  }961 962  if (Paired)963    SW.getOStream() << format("%c%d, %c%d, ", RegChar, Reg, RegChar, Reg + 1);964  else965    SW.getOStream() << format("%c%d, ", RegChar, Reg);966 967  if (Writeback) {968    if (Prologue)969      SW.getOStream() << format("[sp, #-%d]!\n", StackOffset);970    else971      SW.getOStream() << format("[sp], #%d\n", StackOffset);972  } else {973    SW.getOStream() << format("[sp, #%d]\n", StackOffset);974  }975 976  Offset += 3;977  return false;978}979 980bool Decoder::opcode_save_zreg(const uint8_t *OC, unsigned &Offset,981                               unsigned Length, bool Prologue) {982  uint32_t Reg = (OC[Offset + 1] & 0x0F) + 8;983  uint32_t Off = ((OC[Offset + 1] & 0x60) << 1) | (OC[Offset + 2] & 0x3F);984  SW.startLine() << format(985      "0x%02x%02x%02x            ; %s z%u, [sp, #%u, mul vl]\n", OC[Offset],986      OC[Offset + 1], OC[Offset + 2],987      static_cast<const char *>(Prologue ? "str" : "ldr"), Reg, Off);988  Offset += 3;989  return false;990}991 992bool Decoder::opcode_save_preg(const uint8_t *OC, unsigned &Offset,993                               unsigned Length, bool Prologue) {994  uint32_t Reg = (OC[Offset + 1] & 0x0F);995  uint32_t Off = ((OC[Offset + 1] & 0x60) << 1) | (OC[Offset + 2] & 0x3F);996  SW.startLine() << format(997      "0x%02x%02x%02x            ; %s p%u, [sp, #%u, mul vl]\n", OC[Offset],998      OC[Offset + 1], OC[Offset + 2],999      static_cast<const char *>(Prologue ? "str" : "ldr"), Reg, Off);1000  Offset += 3;1001  return false;1002}1003 1004bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset,1005                                unsigned Length, bool Prologue) {1006  SW.startLine() << format("0x%02x                ; trap frame\n", OC[Offset]);1007  ++Offset;1008  return false;1009}1010 1011bool Decoder::opcode_machine_frame(const uint8_t *OC, unsigned &Offset,1012                                   unsigned Length, bool Prologue) {1013  SW.startLine() << format("0x%02x                ; machine frame\n",1014                           OC[Offset]);1015  ++Offset;1016  return false;1017}1018 1019bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset,1020                             unsigned Length, bool Prologue) {1021  SW.startLine() << format("0x%02x                ; context\n", OC[Offset]);1022  ++Offset;1023  return false;1024}1025 1026bool Decoder::opcode_ec_context(const uint8_t *OC, unsigned &Offset,1027                                unsigned Length, bool Prologue) {1028  SW.startLine() << format("0x%02x                ; EC context\n", OC[Offset]);1029  ++Offset;1030  return false;1031}1032 1033bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset,1034                                           unsigned Length, bool Prologue) {1035  SW.startLine() << format("0x%02x                ; clear unwound to call\n",1036                           OC[Offset]);1037  ++Offset;1038  return false;1039}1040 1041bool Decoder::opcode_pac_sign_lr(const uint8_t *OC, unsigned &Offset,1042                                 unsigned Length, bool Prologue) {1043  if (Prologue)1044    SW.startLine() << format("0x%02x                ; pacibsp\n", OC[Offset]);1045  else1046    SW.startLine() << format("0x%02x                ; autibsp\n", OC[Offset]);1047  ++Offset;1048  return false;1049}1050 1051void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,1052                            bool Prologue) {1053  assert((!Prologue || Offset == 0) && "prologue should always use offset 0");1054  const RingEntry* DecodeRing = isAArch64 ? Ring64 : Ring;1055  bool Terminated = false;1056  for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {1057    for (unsigned DI = 0;; ++DI) {1058      if ((isAArch64 && (DI >= std::size(Ring64))) ||1059          (!isAArch64 && (DI >= std::size(Ring)))) {1060        SW.startLine() << format("0x%02x                ; Bad opcode!\n",1061                                 Opcodes.data()[OI]);1062        ++OI;1063        break;1064      }1065 1066      if ((Opcodes[OI] & DecodeRing[DI].Mask) == DecodeRing[DI].Value) {1067        if (OI + DecodeRing[DI].Length > OE) {1068          SW.startLine() << format("Opcode 0x%02x goes past the unwind data\n",1069                                    Opcodes[OI]);1070          OI += DecodeRing[DI].Length;1071          break;1072        }1073        Terminated =1074            (this->*DecodeRing[DI].Routine)(Opcodes.data(), OI, 0, Prologue);1075        break;1076      }1077    }1078  }1079}1080 1081bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF,1082                              const SectionRef &Section,1083                              uint64_t FunctionAddress, uint64_t VA) {1084  ArrayRef<uint8_t> Contents;1085  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))1086    return false;1087 1088  uint64_t SectionVA = Section.getAddress();1089  uint64_t Offset = VA - SectionVA;1090  const ulittle32_t *Data =1091    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);1092 1093  // Sanity check to ensure that the .xdata header is present.1094  // A header is one or two words, followed by at least one word to describe1095  // the unwind codes. Applicable to both ARM and AArch64.1096  if (Contents.size() - Offset < 8)1097    reportFatalUsageError(".xdata must be at least 8 bytes in size");1098 1099  const ExceptionDataRecord XData(Data, isAArch64);1100  DictScope XRS(SW, "ExceptionData");1101  SW.printNumber("FunctionLength",1102                 isAArch64 ? XData.FunctionLengthInBytesAArch64() :1103                 XData.FunctionLengthInBytesARM());1104  SW.printNumber("Version", XData.Vers());1105  SW.printBoolean("ExceptionData", XData.X());1106  SW.printBoolean("EpiloguePacked", XData.E());1107  if (!isAArch64)1108    SW.printBoolean("Fragment", XData.F());1109  SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes",1110                 XData.EpilogueCount());1111  uint64_t ByteCodeLength = XData.CodeWords() * sizeof(uint32_t);1112  SW.printNumber("ByteCodeLength", ByteCodeLength);1113 1114  if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) -1115                (XData.E() ? 0 : XData.EpilogueCount() * 4) -1116                (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) {1117    SW.flush();1118    reportFatalUsageError("Malformed unwind data");1119  }1120 1121  if (XData.E()) {1122    ArrayRef<uint8_t> UC = XData.UnwindByteCode();1123    {1124      ListScope PS(SW, "Prologue");1125      decodeOpcodes(UC, 0, /*Prologue=*/true);1126    }1127    if (XData.EpilogueCount()) {1128      ListScope ES(SW, "Epilogue");1129      decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false);1130    }1131  } else {1132    {1133      ListScope PS(SW, "Prologue");1134      decodeOpcodes(XData.UnwindByteCode(), 0, /*Prologue=*/true);1135    }1136    ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes();1137    ListScope ESS(SW, "EpilogueScopes");1138    for (const EpilogueScope ES : EpilogueScopes) {1139      DictScope ESES(SW, "EpilogueScope");1140      SW.printNumber("StartOffset", ES.EpilogueStartOffset());1141      if (!isAArch64)1142        SW.printNumber("Condition", ES.Condition());1143      SW.printNumber("EpilogueStartIndex",1144                     isAArch64 ? ES.EpilogueStartIndexAArch64()1145                               : ES.EpilogueStartIndexARM());1146      unsigned ReservedMask = isAArch64 ? 0xF : 0x3;1147      if ((ES.ES >> 18) & ReservedMask)1148        SW.printNumber("ReservedBits", (ES.ES >> 18) & ReservedMask);1149 1150      ListScope Opcodes(SW, "Opcodes");1151      decodeOpcodes(XData.UnwindByteCode(),1152                    isAArch64 ? ES.EpilogueStartIndexAArch64()1153                              : ES.EpilogueStartIndexARM(),1154                    /*Prologue=*/false);1155    }1156  }1157 1158  if (XData.X()) {1159    const uint32_t Parameter = XData.ExceptionHandlerParameter();1160    const size_t HandlerOffset = HeaderWords(XData) +1161                                 (XData.E() ? 0 : XData.EpilogueCount()) +1162                                 XData.CodeWords();1163 1164    uint64_t Address, SymbolOffset;1165    ErrorOr<SymbolRef> Symbol = getSymbolForLocation(1166        COFF, Section, Offset + HandlerOffset * sizeof(uint32_t),1167        XData.ExceptionHandlerRVA(), Address, SymbolOffset,1168        /*FunctionOnly=*/true);1169    if (!Symbol) {1170      ListScope EHS(SW, "ExceptionHandler");1171      SW.printHex("Routine", Address);1172      SW.printHex("Parameter", Parameter);1173      return true;1174    }1175 1176    Expected<StringRef> Name = Symbol->getName();1177    if (!Name) {1178      std::string Buf;1179      llvm::raw_string_ostream OS(Buf);1180      logAllUnhandledErrors(Name.takeError(), OS);1181      reportFatalUsageError(Twine(Buf));1182    }1183 1184    ListScope EHS(SW, "ExceptionHandler");1185    SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset));1186    SW.printHex("Parameter", Parameter);1187  }1188 1189  return true;1190}1191 1192bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,1193                                const SectionRef Section, uint64_t Offset,1194                                unsigned Index, const RuntimeFunction &RF) {1195  assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&1196         "packed entry cannot be treated as an unpacked entry");1197 1198  uint64_t FunctionAddress, FunctionOffset;1199  ErrorOr<SymbolRef> Function = getSymbolForLocation(1200      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,1201      /*FunctionOnly=*/true);1202 1203  uint64_t XDataAddress, XDataOffset;1204  ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation(1205      COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress,1206      XDataOffset);1207 1208  if (!RF.BeginAddress && !Function)1209    return false;1210  if (!RF.UnwindData && !XDataRecord)1211    return false;1212 1213  StringRef FunctionName;1214  if (Function) {1215    Expected<StringRef> FunctionNameOrErr = Function->getName();1216    if (!FunctionNameOrErr) {1217      std::string Buf;1218      llvm::raw_string_ostream OS(Buf);1219      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);1220      reportFatalUsageError(Twine(Buf));1221    }1222    FunctionName = *FunctionNameOrErr;1223  }1224 1225  SW.printString("Function",1226                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));1227 1228  if (XDataRecord) {1229    Expected<StringRef> Name = XDataRecord->getName();1230    if (!Name) {1231      std::string Buf;1232      llvm::raw_string_ostream OS(Buf);1233      logAllUnhandledErrors(Name.takeError(), OS);1234      reportFatalUsageError(Twine(Buf));1235    }1236 1237    SW.printString("ExceptionRecord",1238                   formatSymbol(*Name, XDataAddress, XDataOffset));1239 1240    Expected<section_iterator> SIOrErr = XDataRecord->getSection();1241    if (!SIOrErr) {1242      // TODO: Actually report errors helpfully.1243      consumeError(SIOrErr.takeError());1244      return false;1245    }1246    section_iterator SI = *SIOrErr;1247 1248    return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress);1249  } else {1250    SW.printString("ExceptionRecord", formatSymbol("", XDataAddress));1251 1252    ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress);1253    if (!Section)1254      return false;1255 1256    return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress);1257  }1258}1259 1260bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,1261                              const SectionRef Section, uint64_t Offset,1262                              unsigned Index, const RuntimeFunction &RF) {1263  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||1264          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&1265         "unpacked entry cannot be treated as a packed entry");1266 1267  uint64_t FunctionAddress, FunctionOffset;1268  ErrorOr<SymbolRef> Function = getSymbolForLocation(1269      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,1270      /*FunctionOnly=*/true);1271 1272  StringRef FunctionName;1273  if (Function) {1274    Expected<StringRef> FunctionNameOrErr = Function->getName();1275    if (!FunctionNameOrErr) {1276      std::string Buf;1277      llvm::raw_string_ostream OS(Buf);1278      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);1279      reportFatalUsageError(Twine(Buf));1280    }1281    FunctionName = *FunctionNameOrErr;1282  }1283 1284  SW.printString("Function",1285                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));1286  SW.printBoolean("Fragment",1287                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);1288  SW.printNumber("FunctionLength", RF.FunctionLength());1289  SW.startLine() << "ReturnType: " << RF.Ret() << '\n';1290  SW.printBoolean("HomedParameters", RF.H());1291  SW.printNumber("Reg", RF.Reg());1292  SW.printNumber("R", RF.R());1293  SW.printBoolean("LinkRegister", RF.L());1294  SW.printBoolean("Chaining", RF.C());1295  SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2);1296 1297  {1298    ListScope PS(SW, "Prologue");1299 1300    uint16_t GPRMask, VFPMask;1301    std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/true);1302 1303    if (StackAdjustment(RF) && !PrologueFolding(RF))1304      SW.startLine() << "sub sp, sp, #" << StackAdjustment(RF) * 4 << "\n";1305    if (VFPMask) {1306      SW.startLine() << "vpush ";1307      printVFPMask(VFPMask);1308      OS << "\n";1309    }1310    if (RF.C()) {1311      // Count the number of registers pushed below R111312      int FpOffset = 4 * llvm::popcount(GPRMask & ((1U << 11) - 1));1313      if (FpOffset)1314        SW.startLine() << "add.w r11, sp, #" << FpOffset << "\n";1315      else1316        SW.startLine() << "mov r11, sp\n";1317    }1318    if (GPRMask) {1319      SW.startLine() << "push ";1320      printGPRMask(GPRMask);1321      OS << "\n";1322    }1323    if (RF.H())1324      SW.startLine() << "push {r0-r3}\n";1325  }1326 1327  if (RF.Ret() != ReturnType::RT_NoEpilogue) {1328    ListScope PS(SW, "Epilogue");1329 1330    uint16_t GPRMask, VFPMask;1331    std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/false);1332 1333    if (StackAdjustment(RF) && !EpilogueFolding(RF))1334      SW.startLine() << "add sp, sp, #" << StackAdjustment(RF) * 4 << "\n";1335    if (VFPMask) {1336      SW.startLine() << "vpop ";1337      printVFPMask(VFPMask);1338      OS << "\n";1339    }1340    if (GPRMask) {1341      SW.startLine() << "pop ";1342      printGPRMask(GPRMask);1343      OS << "\n";1344    }1345    if (RF.H()) {1346      if (RF.L() == 0 || RF.Ret() != ReturnType::RT_POP)1347        SW.startLine() << "add sp, sp, #16\n";1348      else1349        SW.startLine() << "ldr pc, [sp], #20\n";1350    }1351    if (RF.Ret() != ReturnType::RT_POP)1352      SW.startLine() << RF.Ret() << '\n';1353  }1354 1355  return true;1356}1357 1358bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,1359                                   const SectionRef Section, uint64_t Offset,1360                                   unsigned Index,1361                                   const RuntimeFunctionARM64 &RF) {1362  assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed ||1363          RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&1364         "unpacked entry cannot be treated as a packed entry");1365 1366  uint64_t FunctionAddress, FunctionOffset;1367  ErrorOr<SymbolRef> Function = getSymbolForLocation(1368      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,1369      /*FunctionOnly=*/true);1370 1371  StringRef FunctionName;1372  if (Function) {1373    Expected<StringRef> FunctionNameOrErr = Function->getName();1374    if (!FunctionNameOrErr) {1375      std::string Buf;1376      llvm::raw_string_ostream OS(Buf);1377      logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS);1378      reportFatalUsageError(Twine(Buf));1379    }1380    FunctionName = *FunctionNameOrErr;1381  }1382 1383  SW.printString("Function",1384                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));1385  SW.printBoolean("Fragment",1386                  RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);1387  SW.printNumber("FunctionLength", RF.FunctionLength());1388  SW.printNumber("RegF", RF.RegF());1389  SW.printNumber("RegI", RF.RegI());1390  SW.printBoolean("HomedParameters", RF.H());1391  SW.printNumber("CR", RF.CR());1392  SW.printNumber("FrameSize", RF.FrameSize() << 4);1393  ListScope PS(SW, "Prologue");1394 1395  // Synthesize the equivalent prologue according to the documentation1396  // at https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling,1397  // printed in reverse order compared to the docs, to match how prologues1398  // are printed for the non-packed case.1399  int IntSZ = 8 * RF.RegI();1400  if (RF.CR() == 1)1401    IntSZ += 8;1402  int FpSZ = 8 * RF.RegF();1403  if (RF.RegF())1404    FpSZ += 8;1405  int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf;1406  int LocSZ = (RF.FrameSize() << 4) - SavSZ;1407 1408  if (RF.CR() == 2 || RF.CR() == 3) {1409    SW.startLine() << "mov x29, sp\n";1410    if (LocSZ <= 512) {1411      SW.startLine() << format("stp x29, lr, [sp, #-%d]!\n", LocSZ);1412    } else {1413      SW.startLine() << "stp x29, lr, [sp, #0]\n";1414    }1415  }1416  if (LocSZ > 4080) {1417    SW.startLine() << format("sub sp, sp, #%d\n", LocSZ - 4080);1418    SW.startLine() << "sub sp, sp, #4080\n";1419  } else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) {1420    SW.startLine() << format("sub sp, sp, #%d\n", LocSZ);1421  }1422  if (RF.H()) {1423    SW.startLine() << format("stp x6, x7, [sp, #%d]\n", SavSZ - 16);1424    SW.startLine() << format("stp x4, x5, [sp, #%d]\n", SavSZ - 32);1425    SW.startLine() << format("stp x2, x3, [sp, #%d]\n", SavSZ - 48);1426    if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) {1427      SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64);1428    } else {1429      // This case isn't documented; if neither RegI nor RegF nor CR=11430      // have decremented the stack pointer by SavSZ, we need to do it here1431      // (as the final stack adjustment of LocSZ excludes SavSZ).1432      SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ);1433    }1434  }1435  int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0;1436  for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) {1437    if (I == (FloatRegs + 1) / 2 - 1 && FloatRegs % 2 == 1) {1438      // The last register, an odd register without a pair1439      SW.startLine() << format("str d%d, [sp, #%d]\n", 8 + 2 * I,1440                               IntSZ + 16 * I);1441    } else if (I == 0 && RF.RegI() == 0 && RF.CR() != 1) {1442      SW.startLine() << format("stp d%d, d%d, [sp, #-%d]!\n", 8 + 2 * I,1443                               8 + 2 * I + 1, SavSZ);1444    } else {1445      SW.startLine() << format("stp d%d, d%d, [sp, #%d]\n", 8 + 2 * I,1446                               8 + 2 * I + 1, IntSZ + 16 * I);1447    }1448  }1449  if (RF.CR() == 1 && (RF.RegI() % 2) == 0) {1450    if (RF.RegI() == 0)1451      SW.startLine() << format("str lr, [sp, #-%d]!\n", SavSZ);1452    else1453      SW.startLine() << format("str lr, [sp, #%d]\n", IntSZ - 8);1454  }1455  for (int I = (RF.RegI() + 1) / 2 - 1; I >= 0; I--) {1456    if (I == (RF.RegI() + 1) / 2 - 1 && RF.RegI() % 2 == 1) {1457      // The last register, an odd register without a pair1458      if (RF.CR() == 1) {1459        if (I == 0) { // If this is the only register pair1460          // CR=1 combined with RegI=1 doesn't map to a documented case;1461          // it doesn't map to any regular unwind info opcode, and the1462          // actual unwinder doesn't support it.1463          SW.startLine() << "INVALID!\n";1464        } else1465          SW.startLine() << format("stp x%d, lr, [sp, #%d]\n", 19 + 2 * I,1466                                   16 * I);1467      } else {1468        if (I == 0)1469          SW.startLine() << format("str x%d, [sp, #-%d]!\n", 19 + 2 * I, SavSZ);1470        else1471          SW.startLine() << format("str x%d, [sp, #%d]\n", 19 + 2 * I, 16 * I);1472      }1473    } else if (I == 0) {1474      // The first register pair1475      SW.startLine() << format("stp x19, x20, [sp, #-%d]!\n", SavSZ);1476    } else {1477      SW.startLine() << format("stp x%d, x%d, [sp, #%d]\n", 19 + 2 * I,1478                               19 + 2 * I + 1, 16 * I);1479    }1480  }1481  if (RF.CR() == 2)1482    SW.startLine() << "pacibsp\n";1483  SW.startLine() << "end\n";1484 1485  return true;1486}1487 1488bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF,1489                                     const SectionRef Section, unsigned Index,1490                                     ArrayRef<uint8_t> Contents) {1491  uint64_t Offset = PDataEntrySize * Index;1492  const ulittle32_t *Data =1493    reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset);1494 1495  const RuntimeFunction Entry(Data);1496  DictScope RFS(SW, "RuntimeFunction");1497  if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked)1498    return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry);1499  if (isAArch64) {1500    const RuntimeFunctionARM64 EntryARM64(Data);1501    return dumpPackedARM64Entry(COFF, Section, Offset, Index, EntryARM64);1502  }1503  return dumpPackedEntry(COFF, Section, Offset, Index, Entry);1504}1505 1506void Decoder::dumpProcedureData(const COFFObjectFile &COFF,1507                                const SectionRef Section) {1508  ArrayRef<uint8_t> Contents;1509  if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents))1510    return;1511 1512  if (Contents.size() % PDataEntrySize) {1513    errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n";1514    return;1515  }1516 1517  for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI)1518    if (!dumpProcedureDataEntry(COFF, Section, EI, Contents))1519      break;1520}1521 1522Error Decoder::dumpProcedureData(const COFFObjectFile &COFF) {1523  for (const auto &Section : COFF.sections()) {1524    Expected<StringRef> NameOrErr =1525        COFF.getSectionName(COFF.getCOFFSection(Section));1526    if (!NameOrErr)1527      return NameOrErr.takeError();1528 1529    if (NameOrErr->starts_with(".pdata"))1530      dumpProcedureData(COFF, Section);1531  }1532  return Error::success();1533}1534}1535}1536}1537