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-exception 6 // 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 data 14 // can be stored in a "packed" form. In this case, the data is packed into the 15 // 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 is 24 // 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 the 26 // purposes of validation, with the synthesis being required only by a proper 27 // unwinder. 28 // 29 // For functions that are large or do not match canonical forms, the data is 30 // split up into two portions, with the actual data residing in the "exception 31 // 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 the 35 // epilogue scopes (for functions for which there are multiple exit points) and 36 // the associated exception handler. Additionally, the entry contains byte-code 37 // 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 must 46 // first resolve the exception data entry address. This structure 47 // (ExceptionDataRecord) has a variable sized header 48 // (c.f. ARM::WinEH::HeaderWords) and encodes most of the same information as 49 // the packed form. However, because this information is insufficient to 50 // synthesize the unwinding, there are associated unwinding bytecode which make 51 // up the bulk of the Decoder. 52 // 53 // The decoder itself is table-driven, using the first byte to determine the 54 // opcode and dispatching to the associated printing routine. The bytecode 55 // itself is a variable length instruction encoding that can fully describe the 56 // state of the stack and the necessary operations for unwinding to the 57 // beginning of the frame. 58 // 59 // The byte-code maintains a 1-1 instruction mapping, indicating both the width 60 // of the instruction (Thumb2 instructions are variable length, 16 or 32 bits 61 // wide) allowing the program to unwind from any point in the prologue, body, or 62 // 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 70 using namespace llvm; 71 using namespace llvm::object; 72 using namespace llvm::support; 73 74 namespace llvm { 75 raw_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 << "b target"; 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 94 static 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 else 107 OS << format("0x%" PRIX64, Address); 108 109 return OS.str(); 110 } 111 112 namespace llvm { 113 namespace ARM { 114 namespace WinEH { 115 const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction); 116 117 // TODO name the uops more appropriately 118 const 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_FRAME 129 // UOP_PUSH_CONTEXT 130 // UOP_PUSH_TRAP_FRAME 131 // UOP_REDZONE_RESTORE_LR 132 { 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) / END 142 { 0xff, 0xfe, 1, &Decoder::opcode_11111110 }, // UOP_NOP (32-bit) / END 143 { 0xff, 0xff, 1, &Decoder::opcode_11111111 }, // UOP_END 144 }; 145 146 147 // Unwind opcodes for ARM64. 148 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling 149 const Decoder::RingEntry Decoder::Ring64[] = { 150 { 0xe0, 0x00, 1, &Decoder::opcode_alloc_s }, 151 { 0xe0, 0x20, 1, &Decoder::opcode_save_r19r20_x }, 152 { 0xc0, 0x40, 1, &Decoder::opcode_save_fplr }, 153 { 0xc0, 0x80, 1, &Decoder::opcode_save_fplr_x }, 154 { 0xf8, 0xc0, 2, &Decoder::opcode_alloc_m }, 155 { 0xfc, 0xc8, 2, &Decoder::opcode_save_regp }, 156 { 0xfc, 0xcc, 2, &Decoder::opcode_save_regp_x }, 157 { 0xfc, 0xd0, 2, &Decoder::opcode_save_reg }, 158 { 0xfe, 0xd4, 2, &Decoder::opcode_save_reg_x }, 159 { 0xfe, 0xd6, 2, &Decoder::opcode_save_lrpair }, 160 { 0xfe, 0xd8, 2, &Decoder::opcode_save_fregp }, 161 { 0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x }, 162 { 0xfe, 0xdc, 2, &Decoder::opcode_save_freg }, 163 { 0xff, 0xde, 2, &Decoder::opcode_save_freg_x }, 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, 0xe8, 1, &Decoder::opcode_trap_frame }, 172 { 0xff, 0xe9, 1, &Decoder::opcode_machine_frame }, 173 { 0xff, 0xea, 1, &Decoder::opcode_context }, 174 { 0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call }, 175 }; 176 177 void Decoder::printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask) { 178 static const char * const GPRRegisterNames[16] = { 179 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", 180 "r11", "ip", "sp", "lr", "pc", 181 }; 182 183 const uint16_t GPRMask = std::get<0>(RegisterMask); 184 const uint16_t VFPMask = std::get<1>(RegisterMask); 185 186 OS << '{'; 187 ListSeparator LS; 188 for (unsigned RI = 0, RE = 11; RI < RE; ++RI) 189 if (GPRMask & (1 << RI)) 190 OS << LS << GPRRegisterNames[RI]; 191 for (unsigned RI = 0, RE = 32; RI < RE; ++RI) 192 if (VFPMask & (1 << RI)) 193 OS << LS << "d" << unsigned(RI); 194 for (unsigned RI = 11, RE = 16; RI < RE; ++RI) 195 if (GPRMask & (1 << RI)) 196 OS << LS << GPRRegisterNames[RI]; 197 OS << '}'; 198 } 199 200 ErrorOr<object::SectionRef> 201 Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) { 202 for (const auto &Section : COFF.sections()) { 203 uint64_t Address = Section.getAddress(); 204 uint64_t Size = Section.getSize(); 205 206 if (VA >= Address && (VA - Address) <= Size) 207 return Section; 208 } 209 return inconvertibleErrorCode(); 210 } 211 212 ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF, 213 uint64_t VA, bool FunctionOnly) { 214 for (const auto &Symbol : COFF.symbols()) { 215 Expected<SymbolRef::Type> Type = Symbol.getType(); 216 if (!Type) 217 return errorToErrorCode(Type.takeError()); 218 if (FunctionOnly && *Type != SymbolRef::ST_Function) 219 continue; 220 221 Expected<uint64_t> Address = Symbol.getAddress(); 222 if (!Address) 223 return errorToErrorCode(Address.takeError()); 224 if (*Address == VA) 225 return Symbol; 226 } 227 return inconvertibleErrorCode(); 228 } 229 230 ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &, 231 const SectionRef &Section, 232 uint64_t Offset) { 233 for (const auto &Relocation : Section.relocations()) { 234 uint64_t RelocationOffset = Relocation.getOffset(); 235 if (RelocationOffset == Offset) 236 return *Relocation.getSymbol(); 237 } 238 return inconvertibleErrorCode(); 239 } 240 241 SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF, SymbolRef Sym, 242 uint64_t &SymbolOffset) { 243 // The symbol resolved by getRelocatedSymbol can be any internal 244 // nondescriptive symbol; try to resolve a more descriptive one. 245 COFFSymbolRef CoffSym = COFF.getCOFFSymbol(Sym); 246 if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL && 247 CoffSym.getSectionDefinition() == nullptr) 248 return Sym; 249 for (const auto &S : COFF.symbols()) { 250 COFFSymbolRef CS = COFF.getCOFFSymbol(S); 251 if (CS.getSectionNumber() == CoffSym.getSectionNumber() && 252 CS.getValue() <= CoffSym.getValue() + SymbolOffset && 253 CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL && 254 CS.getSectionDefinition() == nullptr) { 255 uint32_t Offset = CoffSym.getValue() + SymbolOffset - CS.getValue(); 256 if (Offset <= SymbolOffset) { 257 SymbolOffset = Offset; 258 Sym = S; 259 CoffSym = CS; 260 if (CS.isExternal() && SymbolOffset == 0) 261 return Sym; 262 } 263 } 264 } 265 return Sym; 266 } 267 268 ErrorOr<SymbolRef> Decoder::getSymbolForLocation( 269 const COFFObjectFile &COFF, const SectionRef &Section, 270 uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress, 271 uint64_t &SymbolOffset, bool FunctionOnly) { 272 // Try to locate a relocation that points at the offset in the section 273 ErrorOr<SymbolRef> SymOrErr = 274 getRelocatedSymbol(COFF, Section, OffsetInSection); 275 if (SymOrErr) { 276 // We found a relocation symbol; the immediate offset needs to be added 277 // to the symbol address. 278 SymbolOffset = ImmediateOffset; 279 280 Expected<uint64_t> AddressOrErr = SymOrErr->getAddress(); 281 if (!AddressOrErr) { 282 std::string Buf; 283 llvm::raw_string_ostream OS(Buf); 284 logAllUnhandledErrors(AddressOrErr.takeError(), OS); 285 OS.flush(); 286 report_fatal_error(Buf); 287 } 288 // We apply SymbolOffset here directly. We return it separately to allow 289 // the caller to print it as an offset on the symbol name. 290 SymbolAddress = *AddressOrErr + SymbolOffset; 291 292 if (FunctionOnly) // Resolve label/section symbols into function names. 293 SymOrErr = getPreferredSymbol(COFF, *SymOrErr, SymbolOffset); 294 } else { 295 // No matching relocation found; operating on a linked image. Try to 296 // find a descriptive symbol if possible. The immediate offset contains 297 // the image relative address, and we shouldn't add any offset to the 298 // symbol. 299 SymbolAddress = COFF.getImageBase() + ImmediateOffset; 300 SymbolOffset = 0; 301 SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly); 302 } 303 return SymOrErr; 304 } 305 306 bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset, 307 unsigned Length, bool Prologue) { 308 uint8_t Imm = OC[Offset] & 0x7f; 309 SW.startLine() << format("0x%02x ; %s sp, #(%u * 4)\n", 310 OC[Offset], 311 static_cast<const char *>(Prologue ? "sub" : "add"), 312 Imm); 313 ++Offset; 314 return false; 315 } 316 317 bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset, 318 unsigned Length, bool Prologue) { 319 unsigned Link = (OC[Offset] & 0x20) >> 5; 320 uint16_t RegisterMask = (Link << (Prologue ? 14 : 15)) 321 | ((OC[Offset + 0] & 0x1f) << 8) 322 | ((OC[Offset + 1] & 0xff) << 0); 323 assert((~RegisterMask & (1 << 13)) && "sp must not be set"); 324 assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set"); 325 326 SW.startLine() << format("0x%02x 0x%02x ; %s.w ", 327 OC[Offset + 0], OC[Offset + 1], 328 Prologue ? "push" : "pop"); 329 printRegisters(std::make_pair(RegisterMask, 0)); 330 OS << '\n'; 331 332 Offset += 2; 333 return false; 334 } 335 336 bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset, 337 unsigned Length, bool Prologue) { 338 if (Prologue) 339 SW.startLine() << format("0x%02x ; mov r%u, sp\n", 340 OC[Offset], OC[Offset] & 0xf); 341 else 342 SW.startLine() << format("0x%02x ; mov sp, r%u\n", 343 OC[Offset], OC[Offset] & 0xf); 344 ++Offset; 345 return false; 346 } 347 348 bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset, 349 unsigned Length, bool Prologue) { 350 unsigned Link = (OC[Offset] & 0x4) >> 3; 351 unsigned Count = (OC[Offset] & 0x3); 352 353 uint16_t GPRMask = (Link << (Prologue ? 14 : 15)) 354 | (((1 << (Count + 1)) - 1) << 4); 355 356 SW.startLine() << format("0x%02x ; %s ", OC[Offset], 357 Prologue ? "push" : "pop"); 358 printRegisters(std::make_pair(GPRMask, 0)); 359 OS << '\n'; 360 361 ++Offset; 362 return false; 363 } 364 365 bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset, 366 unsigned Length, bool Prologue) { 367 unsigned Link = (OC[Offset] & 0x4) >> 2; 368 unsigned Count = (OC[Offset] & 0x3) + 4; 369 370 uint16_t GPRMask = (Link << (Prologue ? 14 : 15)) 371 | (((1 << (Count + 1)) - 1) << 4); 372 373 SW.startLine() << format("0x%02x ; %s.w ", OC[Offset], 374 Prologue ? "push" : "pop"); 375 printRegisters(std::make_pair(GPRMask, 0)); 376 OS << '\n'; 377 378 ++Offset; 379 return false; 380 } 381 382 bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset, 383 unsigned Length, bool Prologue) { 384 unsigned High = (OC[Offset] & 0x7); 385 uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8); 386 387 SW.startLine() << format("0x%02x ; %s ", OC[Offset], 388 Prologue ? "vpush" : "vpop"); 389 printRegisters(std::make_pair(0, VFPMask)); 390 OS << '\n'; 391 392 ++Offset; 393 return false; 394 } 395 396 bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset, 397 unsigned Length, bool Prologue) { 398 uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0); 399 400 SW.startLine() << format("0x%02x 0x%02x ; %s.w sp, #(%u * 4)\n", 401 OC[Offset + 0], OC[Offset + 1], 402 static_cast<const char *>(Prologue ? "sub" : "add"), 403 Imm); 404 405 Offset += 2; 406 return false; 407 } 408 409 bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset, 410 unsigned Length, bool Prologue) { 411 uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15)) 412 | ((OC[Offset + 1] & 0xff) << 0); 413 414 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0], 415 OC[Offset + 1], Prologue ? "push" : "pop"); 416 printRegisters(std::make_pair(GPRMask, 0)); 417 OS << '\n'; 418 419 Offset += 2; 420 return false; 421 } 422 423 bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset, 424 unsigned Length, bool Prologue) { 425 assert(!Prologue && "may not be used in prologue"); 426 427 if (OC[Offset + 1] & 0xf0) 428 SW.startLine() << format("0x%02x 0x%02x ; reserved\n", 429 OC[Offset + 0], OC[Offset + 1]); 430 else 431 SW.startLine() 432 << format("0x%02x 0x%02x ; microsoft-specific (type: %u)\n", 433 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f); 434 435 Offset += 2; 436 return false; 437 } 438 439 bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset, 440 unsigned Length, bool Prologue) { 441 assert(!Prologue && "may not be used in prologue"); 442 443 if (OC[Offset + 1] & 0xf0) 444 SW.startLine() << format("0x%02x 0x%02x ; reserved\n", 445 OC[Offset + 0], OC[Offset + 1]); 446 else 447 SW.startLine() 448 << format("0x%02x 0x%02x ; ldr.w lr, [sp], #%u\n", 449 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2); 450 451 Offset += 2; 452 return false; 453 } 454 455 bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset, 456 unsigned Length, bool Prologue) { 457 unsigned Start = (OC[Offset + 1] & 0xf0) >> 4; 458 unsigned End = (OC[Offset + 1] & 0x0f) >> 0; 459 uint32_t VFPMask = ((1 << (End - Start)) - 1) << Start; 460 461 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0], 462 OC[Offset + 1], Prologue ? "vpush" : "vpop"); 463 printRegisters(std::make_pair(0, VFPMask)); 464 OS << '\n'; 465 466 Offset += 2; 467 return false; 468 } 469 470 bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset, 471 unsigned Length, bool Prologue) { 472 unsigned Start = (OC[Offset + 1] & 0xf0) >> 4; 473 unsigned End = (OC[Offset + 1] & 0x0f) >> 0; 474 uint32_t VFPMask = ((1 << (End - Start)) - 1) << 16; 475 476 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0], 477 OC[Offset + 1], Prologue ? "vpush" : "vpop"); 478 printRegisters(std::make_pair(0, VFPMask)); 479 OS << '\n'; 480 481 Offset += 2; 482 return false; 483 } 484 485 bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset, 486 unsigned Length, bool Prologue) { 487 uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0); 488 489 SW.startLine() << format("0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n", 490 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], 491 static_cast<const char *>(Prologue ? "sub" : "add"), 492 Imm); 493 494 Offset += 3; 495 return false; 496 } 497 498 bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset, 499 unsigned Length, bool Prologue) { 500 uint32_t Imm = (OC[Offset + 1] << 16) 501 | (OC[Offset + 2] << 8) 502 | (OC[Offset + 3] << 0); 503 504 SW.startLine() 505 << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n", 506 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3], 507 static_cast<const char *>(Prologue ? "sub" : "add"), Imm); 508 509 Offset += 4; 510 return false; 511 } 512 513 bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset, 514 unsigned Length, bool Prologue) { 515 uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0); 516 517 SW.startLine() 518 << format("0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n", 519 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], 520 static_cast<const char *>(Prologue ? "sub" : "add"), Imm); 521 522 Offset += 3; 523 return false; 524 } 525 526 bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset, 527 unsigned Length, bool Prologue) { 528 uint32_t Imm = (OC[Offset + 1] << 16) 529 | (OC[Offset + 2] << 8) 530 | (OC[Offset + 3] << 0); 531 532 SW.startLine() 533 << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n", 534 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3], 535 static_cast<const char *>(Prologue ? "sub" : "add"), Imm); 536 537 Offset += 4; 538 return false; 539 } 540 541 bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset, 542 unsigned Length, bool Prologue) { 543 SW.startLine() << format("0x%02x ; nop\n", OC[Offset]); 544 ++Offset; 545 return false; 546 } 547 548 bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset, 549 unsigned Length, bool Prologue) { 550 SW.startLine() << format("0x%02x ; nop.w\n", OC[Offset]); 551 ++Offset; 552 return false; 553 } 554 555 bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset, 556 unsigned Length, bool Prologue) { 557 SW.startLine() << format("0x%02x ; b\n", OC[Offset]); 558 ++Offset; 559 return true; 560 } 561 562 bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset, 563 unsigned Length, bool Prologue) { 564 SW.startLine() << format("0x%02x ; b.w\n", OC[Offset]); 565 ++Offset; 566 return true; 567 } 568 569 bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset, 570 unsigned Length, bool Prologue) { 571 ++Offset; 572 return true; 573 } 574 575 // ARM64 unwind codes start here. 576 bool Decoder::opcode_alloc_s(const uint8_t *OC, unsigned &Offset, 577 unsigned Length, bool Prologue) { 578 uint32_t NumBytes = (OC[Offset] & 0x1F) << 4; 579 SW.startLine() << format("0x%02x ; %s sp, #%u\n", OC[Offset], 580 static_cast<const char *>(Prologue ? "sub" : "add"), 581 NumBytes); 582 ++Offset; 583 return false; 584 } 585 586 bool Decoder::opcode_save_r19r20_x(const uint8_t *OC, unsigned &Offset, 587 unsigned Length, bool Prologue) { 588 uint32_t Off = (OC[Offset] & 0x1F) << 3; 589 if (Prologue) 590 SW.startLine() << format( 591 "0x%02x ; stp x19, x20, [sp, #-%u]!\n", OC[Offset], Off); 592 else 593 SW.startLine() << format( 594 "0x%02x ; ldp x19, x20, [sp], #%u\n", OC[Offset], Off); 595 ++Offset; 596 return false; 597 } 598 599 bool Decoder::opcode_save_fplr(const uint8_t *OC, unsigned &Offset, 600 unsigned Length, bool Prologue) { 601 uint32_t Off = (OC[Offset] & 0x3F) << 3; 602 SW.startLine() << format( 603 "0x%02x ; %s x29, x30, [sp, #%u]\n", OC[Offset], 604 static_cast<const char *>(Prologue ? "stp" : "ldp"), Off); 605 ++Offset; 606 return false; 607 } 608 609 bool Decoder::opcode_save_fplr_x(const uint8_t *OC, unsigned &Offset, 610 unsigned Length, bool Prologue) { 611 uint32_t Off = ((OC[Offset] & 0x3F) + 1) << 3; 612 if (Prologue) 613 SW.startLine() << format( 614 "0x%02x ; stp x29, x30, [sp, #-%u]!\n", OC[Offset], Off); 615 else 616 SW.startLine() << format( 617 "0x%02x ; ldp x29, x30, [sp], #%u\n", OC[Offset], Off); 618 ++Offset; 619 return false; 620 } 621 622 bool Decoder::opcode_alloc_m(const uint8_t *OC, unsigned &Offset, 623 unsigned Length, bool Prologue) { 624 uint32_t NumBytes = ((OC[Offset] & 0x07) << 8); 625 NumBytes |= (OC[Offset + 1] & 0xFF); 626 NumBytes <<= 4; 627 SW.startLine() << format("0x%02x%02x ; %s sp, #%u\n", 628 OC[Offset], OC[Offset + 1], 629 static_cast<const char *>(Prologue ? "sub" : "add"), 630 NumBytes); 631 Offset += 2; 632 return false; 633 } 634 635 bool Decoder::opcode_save_regp(const uint8_t *OC, unsigned &Offset, 636 unsigned Length, bool Prologue) { 637 uint32_t Reg = ((OC[Offset] & 0x03) << 8); 638 Reg |= (OC[Offset + 1] & 0xC0); 639 Reg >>= 6; 640 Reg += 19; 641 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 642 SW.startLine() << format( 643 "0x%02x%02x ; %s x%u, x%u, [sp, #%u]\n", 644 OC[Offset], OC[Offset + 1], 645 static_cast<const char *>(Prologue ? "stp" : "ldp"), Reg, Reg + 1, Off); 646 Offset += 2; 647 return false; 648 } 649 650 bool Decoder::opcode_save_regp_x(const uint8_t *OC, unsigned &Offset, 651 unsigned Length, bool Prologue) { 652 uint32_t Reg = ((OC[Offset] & 0x03) << 8); 653 Reg |= (OC[Offset + 1] & 0xC0); 654 Reg >>= 6; 655 Reg += 19; 656 uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3; 657 if (Prologue) 658 SW.startLine() << format( 659 "0x%02x%02x ; stp x%u, x%u, [sp, #-%u]!\n", 660 OC[Offset], OC[Offset + 1], Reg, 661 Reg + 1, Off); 662 else 663 SW.startLine() << format( 664 "0x%02x%02x ; ldp x%u, x%u, [sp], #%u\n", 665 OC[Offset], OC[Offset + 1], Reg, 666 Reg + 1, Off); 667 Offset += 2; 668 return false; 669 } 670 671 bool Decoder::opcode_save_reg(const uint8_t *OC, unsigned &Offset, 672 unsigned Length, bool Prologue) { 673 uint32_t Reg = (OC[Offset] & 0x03) << 8; 674 Reg |= (OC[Offset + 1] & 0xC0); 675 Reg >>= 6; 676 Reg += 19; 677 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 678 SW.startLine() << format("0x%02x%02x ; %s x%u, [sp, #%u]\n", 679 OC[Offset], OC[Offset + 1], 680 static_cast<const char *>(Prologue ? "str" : "ldr"), 681 Reg, Off); 682 Offset += 2; 683 return false; 684 } 685 686 bool Decoder::opcode_save_reg_x(const uint8_t *OC, unsigned &Offset, 687 unsigned Length, bool Prologue) { 688 uint32_t Reg = (OC[Offset] & 0x01) << 8; 689 Reg |= (OC[Offset + 1] & 0xE0); 690 Reg >>= 5; 691 Reg += 19; 692 uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3; 693 if (Prologue) 694 SW.startLine() << format("0x%02x%02x ; str x%u, [sp, #-%u]!\n", 695 OC[Offset], OC[Offset + 1], Reg, Off); 696 else 697 SW.startLine() << format("0x%02x%02x ; ldr x%u, [sp], #%u\n", 698 OC[Offset], OC[Offset + 1], Reg, Off); 699 Offset += 2; 700 return false; 701 } 702 703 bool Decoder::opcode_save_lrpair(const uint8_t *OC, unsigned &Offset, 704 unsigned Length, bool Prologue) { 705 uint32_t Reg = (OC[Offset] & 0x01) << 8; 706 Reg |= (OC[Offset + 1] & 0xC0); 707 Reg >>= 6; 708 Reg *= 2; 709 Reg += 19; 710 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 711 SW.startLine() << format("0x%02x%02x ; %s x%u, lr, [sp, #%u]\n", 712 OC[Offset], OC[Offset + 1], 713 static_cast<const char *>(Prologue ? "stp" : "ldp"), 714 Reg, Off); 715 Offset += 2; 716 return false; 717 } 718 719 bool Decoder::opcode_save_fregp(const uint8_t *OC, unsigned &Offset, 720 unsigned Length, bool Prologue) { 721 uint32_t Reg = (OC[Offset] & 0x01) << 8; 722 Reg |= (OC[Offset + 1] & 0xC0); 723 Reg >>= 6; 724 Reg += 8; 725 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 726 SW.startLine() << format("0x%02x%02x ; %s d%u, d%u, [sp, #%u]\n", 727 OC[Offset], OC[Offset + 1], 728 static_cast<const char *>(Prologue ? "stp" : "ldp"), 729 Reg, Reg + 1, Off); 730 Offset += 2; 731 return false; 732 } 733 734 bool Decoder::opcode_save_fregp_x(const uint8_t *OC, unsigned &Offset, 735 unsigned Length, bool Prologue) { 736 uint32_t Reg = (OC[Offset] & 0x01) << 8; 737 Reg |= (OC[Offset + 1] & 0xC0); 738 Reg >>= 6; 739 Reg += 8; 740 uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3; 741 if (Prologue) 742 SW.startLine() << format( 743 "0x%02x%02x ; stp d%u, d%u, [sp, #-%u]!\n", OC[Offset], 744 OC[Offset + 1], Reg, Reg + 1, Off); 745 else 746 SW.startLine() << format( 747 "0x%02x%02x ; ldp d%u, d%u, [sp], #%u\n", OC[Offset], 748 OC[Offset + 1], Reg, Reg + 1, Off); 749 Offset += 2; 750 return false; 751 } 752 753 bool Decoder::opcode_save_freg(const uint8_t *OC, unsigned &Offset, 754 unsigned Length, bool Prologue) { 755 uint32_t Reg = (OC[Offset] & 0x01) << 8; 756 Reg |= (OC[Offset + 1] & 0xC0); 757 Reg >>= 6; 758 Reg += 8; 759 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 760 SW.startLine() << format("0x%02x%02x ; %s d%u, [sp, #%u]\n", 761 OC[Offset], OC[Offset + 1], 762 static_cast<const char *>(Prologue ? "str" : "ldr"), 763 Reg, Off); 764 Offset += 2; 765 return false; 766 } 767 768 bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset, 769 unsigned Length, bool Prologue) { 770 uint32_t Reg = ((OC[Offset + 1] & 0xE0) >> 5) + 8; 771 uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3; 772 if (Prologue) 773 SW.startLine() << format( 774 "0x%02x%02x ; str d%u, [sp, #-%u]!\n", OC[Offset], 775 OC[Offset + 1], Reg, Off); 776 else 777 SW.startLine() << format( 778 "0x%02x%02x ; ldr d%u, [sp], #%u\n", OC[Offset], 779 OC[Offset + 1], Reg, Off); 780 Offset += 2; 781 return false; 782 } 783 784 bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset, 785 unsigned Length, bool Prologue) { 786 unsigned Off = 787 (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) | (OC[Offset + 3] << 0); 788 Off <<= 4; 789 SW.startLine() << format( 790 "0x%02x%02x%02x%02x ; %s sp, #%u\n", OC[Offset], OC[Offset + 1], 791 OC[Offset + 2], OC[Offset + 3], 792 static_cast<const char *>(Prologue ? "sub" : "add"), Off); 793 Offset += 4; 794 return false; 795 } 796 797 bool Decoder::opcode_setfp(const uint8_t *OC, unsigned &Offset, unsigned Length, 798 bool Prologue) { 799 SW.startLine() << format("0x%02x ; mov %s, %s\n", OC[Offset], 800 static_cast<const char *>(Prologue ? "fp" : "sp"), 801 static_cast<const char *>(Prologue ? "sp" : "fp")); 802 ++Offset; 803 return false; 804 } 805 806 bool Decoder::opcode_addfp(const uint8_t *OC, unsigned &Offset, unsigned Length, 807 bool Prologue) { 808 unsigned NumBytes = OC[Offset + 1] << 3; 809 SW.startLine() << format( 810 "0x%02x%02x ; %s %s, %s, #%u\n", OC[Offset], OC[Offset + 1], 811 static_cast<const char *>(Prologue ? "add" : "sub"), 812 static_cast<const char *>(Prologue ? "fp" : "sp"), 813 static_cast<const char *>(Prologue ? "sp" : "fp"), NumBytes); 814 Offset += 2; 815 return false; 816 } 817 818 bool Decoder::opcode_nop(const uint8_t *OC, unsigned &Offset, unsigned Length, 819 bool Prologue) { 820 SW.startLine() << format("0x%02x ; nop\n", OC[Offset]); 821 ++Offset; 822 return false; 823 } 824 825 bool Decoder::opcode_end(const uint8_t *OC, unsigned &Offset, unsigned Length, 826 bool Prologue) { 827 SW.startLine() << format("0x%02x ; end\n", OC[Offset]); 828 ++Offset; 829 return true; 830 } 831 832 bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length, 833 bool Prologue) { 834 SW.startLine() << format("0x%02x ; end_c\n", OC[Offset]); 835 ++Offset; 836 return true; 837 } 838 839 bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset, 840 unsigned Length, bool Prologue) { 841 if (Prologue) 842 SW.startLine() << format("0x%02x ; save next\n", OC[Offset]); 843 else 844 SW.startLine() << format("0x%02x ; restore next\n", 845 OC[Offset]); 846 ++Offset; 847 return false; 848 } 849 850 bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset, 851 unsigned Length, bool Prologue) { 852 SW.startLine() << format("0x%02x ; trap frame\n", OC[Offset]); 853 ++Offset; 854 return false; 855 } 856 857 bool Decoder::opcode_machine_frame(const uint8_t *OC, unsigned &Offset, 858 unsigned Length, bool Prologue) { 859 SW.startLine() << format("0x%02x ; machine frame\n", 860 OC[Offset]); 861 ++Offset; 862 return false; 863 } 864 865 bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset, 866 unsigned Length, bool Prologue) { 867 SW.startLine() << format("0x%02x ; context\n", OC[Offset]); 868 ++Offset; 869 return false; 870 } 871 872 bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset, 873 unsigned Length, bool Prologue) { 874 SW.startLine() << format("0x%02x ; clear unwound to call\n", 875 OC[Offset]); 876 ++Offset; 877 return false; 878 } 879 880 void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset, 881 bool Prologue) { 882 assert((!Prologue || Offset == 0) && "prologue should always use offset 0"); 883 const RingEntry* DecodeRing = isAArch64 ? Ring64 : Ring; 884 bool Terminated = false; 885 for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) { 886 for (unsigned DI = 0;; ++DI) { 887 if ((isAArch64 && (DI >= array_lengthof(Ring64))) || 888 (!isAArch64 && (DI >= array_lengthof(Ring)))) { 889 SW.startLine() << format("0x%02x ; Bad opcode!\n", 890 Opcodes.data()[OI]); 891 ++OI; 892 break; 893 } 894 895 if ((Opcodes[OI] & DecodeRing[DI].Mask) == DecodeRing[DI].Value) { 896 if (OI + DecodeRing[DI].Length > OE) { 897 SW.startLine() << format("Opcode 0x%02x goes past the unwind data\n", 898 Opcodes[OI]); 899 OI += DecodeRing[DI].Length; 900 break; 901 } 902 Terminated = 903 (this->*DecodeRing[DI].Routine)(Opcodes.data(), OI, 0, Prologue); 904 break; 905 } 906 } 907 } 908 } 909 910 bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, 911 const SectionRef &Section, 912 uint64_t FunctionAddress, uint64_t VA) { 913 ArrayRef<uint8_t> Contents; 914 if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents)) 915 return false; 916 917 uint64_t SectionVA = Section.getAddress(); 918 uint64_t Offset = VA - SectionVA; 919 const ulittle32_t *Data = 920 reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset); 921 922 // Sanity check to ensure that the .xdata header is present. 923 // A header is one or two words, followed by at least one word to describe 924 // the unwind codes. Applicable to both ARM and AArch64. 925 if (Contents.size() - Offset < 8) 926 report_fatal_error(".xdata must be at least 8 bytes in size"); 927 928 const ExceptionDataRecord XData(Data, isAArch64); 929 DictScope XRS(SW, "ExceptionData"); 930 SW.printNumber("FunctionLength", 931 isAArch64 ? XData.FunctionLengthInBytesAArch64() : 932 XData.FunctionLengthInBytesARM()); 933 SW.printNumber("Version", XData.Vers()); 934 SW.printBoolean("ExceptionData", XData.X()); 935 SW.printBoolean("EpiloguePacked", XData.E()); 936 if (!isAArch64) 937 SW.printBoolean("Fragment", XData.F()); 938 SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes", 939 XData.EpilogueCount()); 940 uint64_t ByteCodeLength = XData.CodeWords() * sizeof(uint32_t); 941 SW.printNumber("ByteCodeLength", ByteCodeLength); 942 943 if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) - 944 (XData.E() ? 0 : XData.EpilogueCount() * 4) - 945 (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) { 946 SW.flush(); 947 report_fatal_error("Malformed unwind data"); 948 } 949 950 if (XData.E()) { 951 ArrayRef<uint8_t> UC = XData.UnwindByteCode(); 952 if (isAArch64 || !XData.F()) { 953 ListScope PS(SW, "Prologue"); 954 decodeOpcodes(UC, 0, /*Prologue=*/true); 955 } 956 if (XData.EpilogueCount()) { 957 ListScope ES(SW, "Epilogue"); 958 decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false); 959 } 960 } else { 961 { 962 ListScope PS(SW, "Prologue"); 963 decodeOpcodes(XData.UnwindByteCode(), 0, /*Prologue=*/true); 964 } 965 ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes(); 966 ListScope ESS(SW, "EpilogueScopes"); 967 for (const EpilogueScope ES : EpilogueScopes) { 968 DictScope ESES(SW, "EpilogueScope"); 969 SW.printNumber("StartOffset", ES.EpilogueStartOffset()); 970 if (!isAArch64) 971 SW.printNumber("Condition", ES.Condition()); 972 SW.printNumber("EpilogueStartIndex", 973 isAArch64 ? ES.EpilogueStartIndexAArch64() 974 : ES.EpilogueStartIndexARM()); 975 if (ES.ES & ~0xffc3ffff) 976 SW.printNumber("ReservedBits", (ES.ES >> 18) & 0xF); 977 978 ListScope Opcodes(SW, "Opcodes"); 979 decodeOpcodes(XData.UnwindByteCode(), 980 isAArch64 ? ES.EpilogueStartIndexAArch64() 981 : ES.EpilogueStartIndexARM(), 982 /*Prologue=*/false); 983 } 984 } 985 986 if (XData.X()) { 987 const uint32_t Parameter = XData.ExceptionHandlerParameter(); 988 const size_t HandlerOffset = HeaderWords(XData) + 989 (XData.E() ? 0 : XData.EpilogueCount()) + 990 XData.CodeWords(); 991 992 uint64_t Address, SymbolOffset; 993 ErrorOr<SymbolRef> Symbol = getSymbolForLocation( 994 COFF, Section, Offset + HandlerOffset * sizeof(uint32_t), 995 XData.ExceptionHandlerRVA(), Address, SymbolOffset, 996 /*FunctionOnly=*/true); 997 if (!Symbol) { 998 ListScope EHS(SW, "ExceptionHandler"); 999 SW.printHex("Routine", Address); 1000 SW.printHex("Parameter", Parameter); 1001 return true; 1002 } 1003 1004 Expected<StringRef> Name = Symbol->getName(); 1005 if (!Name) { 1006 std::string Buf; 1007 llvm::raw_string_ostream OS(Buf); 1008 logAllUnhandledErrors(Name.takeError(), OS); 1009 OS.flush(); 1010 report_fatal_error(Buf); 1011 } 1012 1013 ListScope EHS(SW, "ExceptionHandler"); 1014 SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset)); 1015 SW.printHex("Parameter", Parameter); 1016 } 1017 1018 return true; 1019 } 1020 1021 bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF, 1022 const SectionRef Section, uint64_t Offset, 1023 unsigned Index, const RuntimeFunction &RF) { 1024 assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked && 1025 "packed entry cannot be treated as an unpacked entry"); 1026 1027 uint64_t FunctionAddress, FunctionOffset; 1028 ErrorOr<SymbolRef> Function = getSymbolForLocation( 1029 COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset, 1030 /*FunctionOnly=*/true); 1031 1032 uint64_t XDataAddress, XDataOffset; 1033 ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation( 1034 COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress, 1035 XDataOffset); 1036 1037 if (!RF.BeginAddress && !Function) 1038 return false; 1039 if (!RF.UnwindData && !XDataRecord) 1040 return false; 1041 1042 StringRef FunctionName; 1043 if (Function) { 1044 Expected<StringRef> FunctionNameOrErr = Function->getName(); 1045 if (!FunctionNameOrErr) { 1046 std::string Buf; 1047 llvm::raw_string_ostream OS(Buf); 1048 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); 1049 OS.flush(); 1050 report_fatal_error(Buf); 1051 } 1052 FunctionName = *FunctionNameOrErr; 1053 } 1054 1055 SW.printString("Function", 1056 formatSymbol(FunctionName, FunctionAddress, FunctionOffset)); 1057 1058 if (XDataRecord) { 1059 Expected<StringRef> Name = XDataRecord->getName(); 1060 if (!Name) { 1061 std::string Buf; 1062 llvm::raw_string_ostream OS(Buf); 1063 logAllUnhandledErrors(Name.takeError(), OS); 1064 OS.flush(); 1065 report_fatal_error(Buf); 1066 } 1067 1068 SW.printString("ExceptionRecord", 1069 formatSymbol(*Name, XDataAddress, XDataOffset)); 1070 1071 Expected<section_iterator> SIOrErr = XDataRecord->getSection(); 1072 if (!SIOrErr) { 1073 // TODO: Actually report errors helpfully. 1074 consumeError(SIOrErr.takeError()); 1075 return false; 1076 } 1077 section_iterator SI = *SIOrErr; 1078 1079 return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress); 1080 } else { 1081 SW.printString("ExceptionRecord", formatSymbol("", XDataAddress)); 1082 1083 ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress); 1084 if (!Section) 1085 return false; 1086 1087 return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress); 1088 } 1089 } 1090 1091 bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF, 1092 const SectionRef Section, uint64_t Offset, 1093 unsigned Index, const RuntimeFunction &RF) { 1094 assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed || 1095 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && 1096 "unpacked entry cannot be treated as a packed entry"); 1097 1098 uint64_t FunctionAddress, FunctionOffset; 1099 ErrorOr<SymbolRef> Function = getSymbolForLocation( 1100 COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset, 1101 /*FunctionOnly=*/true); 1102 1103 StringRef FunctionName; 1104 if (Function) { 1105 Expected<StringRef> FunctionNameOrErr = Function->getName(); 1106 if (!FunctionNameOrErr) { 1107 std::string Buf; 1108 llvm::raw_string_ostream OS(Buf); 1109 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); 1110 OS.flush(); 1111 report_fatal_error(Buf); 1112 } 1113 FunctionName = *FunctionNameOrErr; 1114 } 1115 1116 SW.printString("Function", 1117 formatSymbol(FunctionName, FunctionAddress, FunctionOffset)); 1118 if (!isAArch64) 1119 SW.printBoolean("Fragment", 1120 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment); 1121 SW.printNumber("FunctionLength", RF.FunctionLength()); 1122 SW.startLine() << "ReturnType: " << RF.Ret() << '\n'; 1123 SW.printBoolean("HomedParameters", RF.H()); 1124 SW.startLine() << "SavedRegisters: "; 1125 printRegisters(SavedRegisterMask(RF)); 1126 OS << '\n'; 1127 SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2); 1128 1129 return true; 1130 } 1131 1132 bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF, 1133 const SectionRef Section, uint64_t Offset, 1134 unsigned Index, 1135 const RuntimeFunctionARM64 &RF) { 1136 assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed || 1137 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && 1138 "unpacked entry cannot be treated as a packed entry"); 1139 1140 uint64_t FunctionAddress, FunctionOffset; 1141 ErrorOr<SymbolRef> Function = getSymbolForLocation( 1142 COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset, 1143 /*FunctionOnly=*/true); 1144 1145 StringRef FunctionName; 1146 if (Function) { 1147 Expected<StringRef> FunctionNameOrErr = Function->getName(); 1148 if (!FunctionNameOrErr) { 1149 std::string Buf; 1150 llvm::raw_string_ostream OS(Buf); 1151 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); 1152 OS.flush(); 1153 report_fatal_error(Buf); 1154 } 1155 FunctionName = *FunctionNameOrErr; 1156 } 1157 1158 SW.printString("Function", 1159 formatSymbol(FunctionName, FunctionAddress, FunctionOffset)); 1160 SW.printBoolean("Fragment", 1161 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment); 1162 SW.printNumber("FunctionLength", RF.FunctionLength()); 1163 SW.printNumber("RegF", RF.RegF()); 1164 SW.printNumber("RegI", RF.RegI()); 1165 SW.printBoolean("HomedParameters", RF.H()); 1166 SW.printNumber("CR", RF.CR()); 1167 SW.printNumber("FrameSize", RF.FrameSize() << 4); 1168 ListScope PS(SW, "Prologue"); 1169 1170 // Synthesize the equivalent prologue according to the documentation 1171 // at https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling, 1172 // printed in reverse order compared to the docs, to match how prologues 1173 // are printed for the non-packed case. 1174 int IntSZ = 8 * RF.RegI(); 1175 if (RF.CR() == 1) 1176 IntSZ += 8; 1177 int FpSZ = 8 * RF.RegF(); 1178 if (RF.RegF()) 1179 FpSZ += 8; 1180 int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf; 1181 int LocSZ = (RF.FrameSize() << 4) - SavSZ; 1182 1183 if (RF.CR() == 3) { 1184 SW.startLine() << "mov x29, sp\n"; 1185 if (LocSZ <= 512) { 1186 SW.startLine() << format("stp x29, lr, [sp, #-%d]!\n", LocSZ); 1187 } else { 1188 SW.startLine() << "stp x29, lr, [sp, #0]\n"; 1189 } 1190 } 1191 if (LocSZ > 4080) { 1192 SW.startLine() << format("sub sp, sp, #%d\n", LocSZ - 4080); 1193 SW.startLine() << "sub sp, sp, #4080\n"; 1194 } else if ((RF.CR() != 3 && LocSZ > 0) || LocSZ > 512) { 1195 SW.startLine() << format("sub sp, sp, #%d\n", LocSZ); 1196 } 1197 if (RF.H()) { 1198 SW.startLine() << format("stp x6, x7, [sp, #%d]\n", IntSZ + FpSZ + 48); 1199 SW.startLine() << format("stp x4, x5, [sp, #%d]\n", IntSZ + FpSZ + 32); 1200 SW.startLine() << format("stp x2, x3, [sp, #%d]\n", IntSZ + FpSZ + 16); 1201 if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) { 1202 SW.startLine() << format("stp x0, x1, [sp, #%d]\n", IntSZ + FpSZ); 1203 } else { 1204 // This case isn't documented; if neither RegI nor RegF nor CR=1 1205 // have decremented the stack pointer by SavSZ, we need to do it here 1206 // (as the final stack adjustment of LocSZ excludes SavSZ). 1207 SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ); 1208 } 1209 } 1210 int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0; 1211 for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) { 1212 if (I == (FloatRegs + 1) / 2 - 1 && FloatRegs % 2 == 1) { 1213 // The last register, an odd register without a pair 1214 SW.startLine() << format("str d%d, [sp, #%d]\n", 8 + 2 * I, 1215 IntSZ + 16 * I); 1216 } else if (I == 0 && RF.RegI() == 0 && RF.CR() != 1) { 1217 SW.startLine() << format("stp d%d, d%d, [sp, #-%d]!\n", 8 + 2 * I, 1218 8 + 2 * I + 1, SavSZ); 1219 } else { 1220 SW.startLine() << format("stp d%d, d%d, [sp, #%d]\n", 8 + 2 * I, 1221 8 + 2 * I + 1, IntSZ + 16 * I); 1222 } 1223 } 1224 if (RF.CR() == 1 && (RF.RegI() % 2) == 0) { 1225 if (RF.RegI() == 0) 1226 SW.startLine() << format("str lr, [sp, #-%d]!\n", SavSZ); 1227 else 1228 SW.startLine() << format("str lr, [sp, #%d]\n", IntSZ - 8); 1229 } 1230 for (int I = (RF.RegI() + 1) / 2 - 1; I >= 0; I--) { 1231 if (I == (RF.RegI() + 1) / 2 - 1 && RF.RegI() % 2 == 1) { 1232 // The last register, an odd register without a pair 1233 if (RF.CR() == 1) { 1234 if (I == 0) { // If this is the only register pair 1235 // CR=1 combined with RegI=1 doesn't map to a documented case; 1236 // it doesn't map to any regular unwind info opcode, and the 1237 // actual unwinder doesn't support it. 1238 SW.startLine() << "INVALID!\n"; 1239 } else 1240 SW.startLine() << format("stp x%d, lr, [sp, #%d]\n", 19 + 2 * I, 1241 16 * I); 1242 } else { 1243 if (I == 0) 1244 SW.startLine() << format("str x%d, [sp, #-%d]!\n", 19 + 2 * I, SavSZ); 1245 else 1246 SW.startLine() << format("str x%d, [sp, #%d]\n", 19 + 2 * I, 16 * I); 1247 } 1248 } else if (I == 0) { 1249 // The first register pair 1250 SW.startLine() << format("stp x19, x20, [sp, #-%d]!\n", SavSZ); 1251 } else { 1252 SW.startLine() << format("stp x%d, x%d, [sp, #%d]\n", 19 + 2 * I, 1253 19 + 2 * I + 1, 16 * I); 1254 } 1255 } 1256 SW.startLine() << "end\n"; 1257 1258 return true; 1259 } 1260 1261 bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF, 1262 const SectionRef Section, unsigned Index, 1263 ArrayRef<uint8_t> Contents) { 1264 uint64_t Offset = PDataEntrySize * Index; 1265 const ulittle32_t *Data = 1266 reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset); 1267 1268 const RuntimeFunction Entry(Data); 1269 DictScope RFS(SW, "RuntimeFunction"); 1270 if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked) 1271 return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry); 1272 if (isAArch64) { 1273 const RuntimeFunctionARM64 EntryARM64(Data); 1274 return dumpPackedARM64Entry(COFF, Section, Offset, Index, EntryARM64); 1275 } 1276 return dumpPackedEntry(COFF, Section, Offset, Index, Entry); 1277 } 1278 1279 void Decoder::dumpProcedureData(const COFFObjectFile &COFF, 1280 const SectionRef Section) { 1281 ArrayRef<uint8_t> Contents; 1282 if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents)) 1283 return; 1284 1285 if (Contents.size() % PDataEntrySize) { 1286 errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n"; 1287 return; 1288 } 1289 1290 for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI) 1291 if (!dumpProcedureDataEntry(COFF, Section, EI, Contents)) 1292 break; 1293 } 1294 1295 Error Decoder::dumpProcedureData(const COFFObjectFile &COFF) { 1296 for (const auto &Section : COFF.sections()) { 1297 Expected<StringRef> NameOrErr = 1298 COFF.getSectionName(COFF.getCOFFSection(Section)); 1299 if (!NameOrErr) 1300 return NameOrErr.takeError(); 1301 1302 if (NameOrErr->startswith(".pdata")) 1303 dumpProcedureData(COFF, Section); 1304 } 1305 return Error::success(); 1306 } 1307 } 1308 } 1309 } 1310