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 << "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 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 // Unwind opcodes for ARM64. 147 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling 148 const 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, 0xe0, 4, &Decoder::opcode_alloc_l}, 164 {0xff, 0xe1, 1, &Decoder::opcode_setfp}, 165 {0xff, 0xe2, 2, &Decoder::opcode_addfp}, 166 {0xff, 0xe3, 1, &Decoder::opcode_nop}, 167 {0xff, 0xe4, 1, &Decoder::opcode_end}, 168 {0xff, 0xe5, 1, &Decoder::opcode_end_c}, 169 {0xff, 0xe6, 1, &Decoder::opcode_save_next}, 170 {0xff, 0xe7, 3, &Decoder::opcode_save_any_reg}, 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 {0xff, 0xfc, 1, &Decoder::opcode_pac_sign_lr}, 176 }; 177 178 static void printRange(raw_ostream &OS, ListSeparator &LS, unsigned First, 179 unsigned Last, char Letter) { 180 if (First == Last) 181 OS << LS << Letter << First; 182 else 183 OS << LS << Letter << First << "-" << Letter << Last; 184 } 185 186 static void printRange(raw_ostream &OS, uint32_t Mask, ListSeparator &LS, 187 unsigned Start, unsigned End, char Letter) { 188 int First = -1; 189 for (unsigned RI = Start; RI <= End; ++RI) { 190 if (Mask & (1 << RI)) { 191 if (First < 0) 192 First = RI; 193 } else { 194 if (First >= 0) { 195 printRange(OS, LS, First, RI - 1, Letter); 196 First = -1; 197 } 198 } 199 } 200 if (First >= 0) 201 printRange(OS, LS, First, End, Letter); 202 } 203 204 void Decoder::printGPRMask(uint16_t GPRMask) { 205 OS << '{'; 206 ListSeparator LS; 207 printRange(OS, GPRMask, LS, 0, 12, 'r'); 208 if (GPRMask & (1 << 14)) 209 OS << LS << "lr"; 210 if (GPRMask & (1 << 15)) 211 OS << LS << "pc"; 212 OS << '}'; 213 } 214 215 void Decoder::printVFPMask(uint32_t VFPMask) { 216 OS << '{'; 217 ListSeparator LS; 218 printRange(OS, VFPMask, LS, 0, 31, 'd'); 219 OS << '}'; 220 } 221 222 ErrorOr<object::SectionRef> 223 Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) { 224 for (const auto &Section : COFF.sections()) { 225 uint64_t Address = Section.getAddress(); 226 uint64_t Size = Section.getSize(); 227 228 if (VA >= Address && (VA - Address) <= Size) 229 return Section; 230 } 231 return inconvertibleErrorCode(); 232 } 233 234 ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF, 235 uint64_t VA, bool FunctionOnly) { 236 for (const auto &Symbol : COFF.symbols()) { 237 Expected<SymbolRef::Type> Type = Symbol.getType(); 238 if (!Type) 239 return errorToErrorCode(Type.takeError()); 240 if (FunctionOnly && *Type != SymbolRef::ST_Function) 241 continue; 242 243 Expected<uint64_t> Address = Symbol.getAddress(); 244 if (!Address) 245 return errorToErrorCode(Address.takeError()); 246 if (*Address == VA) 247 return Symbol; 248 } 249 return inconvertibleErrorCode(); 250 } 251 252 ErrorOr<SymbolRef> Decoder::getRelocatedSymbol(const COFFObjectFile &, 253 const SectionRef &Section, 254 uint64_t Offset) { 255 for (const auto &Relocation : Section.relocations()) { 256 uint64_t RelocationOffset = Relocation.getOffset(); 257 if (RelocationOffset == Offset) 258 return *Relocation.getSymbol(); 259 } 260 return inconvertibleErrorCode(); 261 } 262 263 SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF, SymbolRef Sym, 264 uint64_t &SymbolOffset) { 265 // The symbol resolved by getRelocatedSymbol can be any internal 266 // nondescriptive symbol; try to resolve a more descriptive one. 267 COFFSymbolRef CoffSym = COFF.getCOFFSymbol(Sym); 268 if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL && 269 CoffSym.getSectionDefinition() == nullptr) 270 return Sym; 271 for (const auto &S : COFF.symbols()) { 272 COFFSymbolRef CS = COFF.getCOFFSymbol(S); 273 if (CS.getSectionNumber() == CoffSym.getSectionNumber() && 274 CS.getValue() <= CoffSym.getValue() + SymbolOffset && 275 CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL && 276 CS.getSectionDefinition() == nullptr) { 277 uint32_t Offset = CoffSym.getValue() + SymbolOffset - CS.getValue(); 278 if (Offset <= SymbolOffset) { 279 SymbolOffset = Offset; 280 Sym = S; 281 CoffSym = CS; 282 if (CS.isExternal() && SymbolOffset == 0) 283 return Sym; 284 } 285 } 286 } 287 return Sym; 288 } 289 290 ErrorOr<SymbolRef> Decoder::getSymbolForLocation( 291 const COFFObjectFile &COFF, const SectionRef &Section, 292 uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress, 293 uint64_t &SymbolOffset, bool FunctionOnly) { 294 // Try to locate a relocation that points at the offset in the section 295 ErrorOr<SymbolRef> SymOrErr = 296 getRelocatedSymbol(COFF, Section, OffsetInSection); 297 if (SymOrErr) { 298 // We found a relocation symbol; the immediate offset needs to be added 299 // to the symbol address. 300 SymbolOffset = ImmediateOffset; 301 302 Expected<uint64_t> AddressOrErr = SymOrErr->getAddress(); 303 if (!AddressOrErr) { 304 std::string Buf; 305 llvm::raw_string_ostream OS(Buf); 306 logAllUnhandledErrors(AddressOrErr.takeError(), OS); 307 report_fatal_error(Twine(OS.str())); 308 } 309 // We apply SymbolOffset here directly. We return it separately to allow 310 // the caller to print it as an offset on the symbol name. 311 SymbolAddress = *AddressOrErr + SymbolOffset; 312 313 if (FunctionOnly) // Resolve label/section symbols into function names. 314 SymOrErr = getPreferredSymbol(COFF, *SymOrErr, SymbolOffset); 315 } else { 316 // No matching relocation found; operating on a linked image. Try to 317 // find a descriptive symbol if possible. The immediate offset contains 318 // the image relative address, and we shouldn't add any offset to the 319 // symbol. 320 SymbolAddress = COFF.getImageBase() + ImmediateOffset; 321 SymbolOffset = 0; 322 SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly); 323 } 324 return SymOrErr; 325 } 326 327 bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset, 328 unsigned Length, bool Prologue) { 329 uint8_t Imm = OC[Offset] & 0x7f; 330 SW.startLine() << format("0x%02x ; %s sp, #(%u * 4)\n", 331 OC[Offset], 332 static_cast<const char *>(Prologue ? "sub" : "add"), 333 Imm); 334 ++Offset; 335 return false; 336 } 337 338 bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset, 339 unsigned Length, bool Prologue) { 340 unsigned Link = (OC[Offset] & 0x20) >> 5; 341 uint16_t RegisterMask = (Link << (Prologue ? 14 : 15)) 342 | ((OC[Offset + 0] & 0x1f) << 8) 343 | ((OC[Offset + 1] & 0xff) << 0); 344 assert((~RegisterMask & (1 << 13)) && "sp must not be set"); 345 assert((~RegisterMask & (1 << (Prologue ? 15 : 14))) && "pc must not be set"); 346 347 SW.startLine() << format("0x%02x 0x%02x ; %s.w ", 348 OC[Offset + 0], OC[Offset + 1], 349 Prologue ? "push" : "pop"); 350 printGPRMask(RegisterMask); 351 OS << '\n'; 352 353 Offset += 2; 354 return false; 355 } 356 357 bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset, 358 unsigned Length, bool Prologue) { 359 if (Prologue) 360 SW.startLine() << format("0x%02x ; mov r%u, sp\n", 361 OC[Offset], OC[Offset] & 0xf); 362 else 363 SW.startLine() << format("0x%02x ; mov sp, r%u\n", 364 OC[Offset], OC[Offset] & 0xf); 365 ++Offset; 366 return false; 367 } 368 369 bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset, 370 unsigned Length, bool Prologue) { 371 unsigned Link = (OC[Offset] & 0x4) >> 2; 372 unsigned Count = (OC[Offset] & 0x3); 373 374 uint16_t GPRMask = (Link << (Prologue ? 14 : 15)) 375 | (((1 << (Count + 1)) - 1) << 4); 376 377 SW.startLine() << format("0x%02x ; %s ", OC[Offset], 378 Prologue ? "push" : "pop"); 379 printGPRMask(GPRMask); 380 OS << '\n'; 381 382 ++Offset; 383 return false; 384 } 385 386 bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset, 387 unsigned Length, bool Prologue) { 388 unsigned Link = (OC[Offset] & 0x4) >> 2; 389 unsigned Count = (OC[Offset] & 0x3) + 4; 390 391 uint16_t GPRMask = (Link << (Prologue ? 14 : 15)) 392 | (((1 << (Count + 1)) - 1) << 4); 393 394 SW.startLine() << format("0x%02x ; %s.w ", OC[Offset], 395 Prologue ? "push" : "pop"); 396 printGPRMask(GPRMask); 397 OS << '\n'; 398 399 ++Offset; 400 return false; 401 } 402 403 bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset, 404 unsigned Length, bool Prologue) { 405 unsigned High = (OC[Offset] & 0x7); 406 uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8); 407 408 SW.startLine() << format("0x%02x ; %s ", OC[Offset], 409 Prologue ? "vpush" : "vpop"); 410 printVFPMask(VFPMask); 411 OS << '\n'; 412 413 ++Offset; 414 return false; 415 } 416 417 bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset, 418 unsigned Length, bool Prologue) { 419 uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0); 420 421 SW.startLine() << format("0x%02x 0x%02x ; %s.w sp, #(%u * 4)\n", 422 OC[Offset + 0], OC[Offset + 1], 423 static_cast<const char *>(Prologue ? "sub" : "add"), 424 Imm); 425 426 Offset += 2; 427 return false; 428 } 429 430 bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset, 431 unsigned Length, bool Prologue) { 432 uint16_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15)) 433 | ((OC[Offset + 1] & 0xff) << 0); 434 435 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0], 436 OC[Offset + 1], Prologue ? "push" : "pop"); 437 printGPRMask(GPRMask); 438 OS << '\n'; 439 440 Offset += 2; 441 return false; 442 } 443 444 bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset, 445 unsigned Length, bool Prologue) { 446 assert(!Prologue && "may not be used in prologue"); 447 448 if (OC[Offset + 1] & 0xf0) 449 SW.startLine() << format("0x%02x 0x%02x ; reserved\n", 450 OC[Offset + 0], OC[Offset + 1]); 451 else 452 SW.startLine() 453 << format("0x%02x 0x%02x ; microsoft-specific (type: %u)\n", 454 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] & 0x0f); 455 456 Offset += 2; 457 return false; 458 } 459 460 bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset, 461 unsigned Length, bool Prologue) { 462 if (OC[Offset + 1] & 0xf0) 463 SW.startLine() << format("0x%02x 0x%02x ; reserved\n", 464 OC[Offset + 0], OC[Offset + 1]); 465 else if (Prologue) 466 SW.startLine() 467 << format("0x%02x 0x%02x ; str.w lr, [sp, #-%u]!\n", 468 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2); 469 else 470 SW.startLine() 471 << format("0x%02x 0x%02x ; ldr.w lr, [sp], #%u\n", 472 OC[Offset + 0], OC[Offset + 1], OC[Offset + 1] << 2); 473 474 Offset += 2; 475 return false; 476 } 477 478 bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset, 479 unsigned Length, bool Prologue) { 480 unsigned Start = (OC[Offset + 1] & 0xf0) >> 4; 481 unsigned End = (OC[Offset + 1] & 0x0f) >> 0; 482 uint32_t VFPMask = ((1 << (End + 1 - Start)) - 1) << Start; 483 484 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0], 485 OC[Offset + 1], Prologue ? "vpush" : "vpop"); 486 printVFPMask(VFPMask); 487 OS << '\n'; 488 489 Offset += 2; 490 return false; 491 } 492 493 bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset, 494 unsigned Length, bool Prologue) { 495 unsigned Start = (OC[Offset + 1] & 0xf0) >> 4; 496 unsigned End = (OC[Offset + 1] & 0x0f) >> 0; 497 uint32_t VFPMask = ((1 << (End + 1 - Start)) - 1) << (16 + Start); 498 499 SW.startLine() << format("0x%02x 0x%02x ; %s ", OC[Offset + 0], 500 OC[Offset + 1], Prologue ? "vpush" : "vpop"); 501 printVFPMask(VFPMask); 502 OS << '\n'; 503 504 Offset += 2; 505 return false; 506 } 507 508 bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset, 509 unsigned Length, bool Prologue) { 510 uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0); 511 512 SW.startLine() << format("0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n", 513 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], 514 static_cast<const char *>(Prologue ? "sub" : "add"), 515 Imm); 516 517 Offset += 3; 518 return false; 519 } 520 521 bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset, 522 unsigned Length, bool Prologue) { 523 uint32_t Imm = (OC[Offset + 1] << 16) 524 | (OC[Offset + 2] << 8) 525 | (OC[Offset + 3] << 0); 526 527 SW.startLine() 528 << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s sp, sp, #(%u * 4)\n", 529 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3], 530 static_cast<const char *>(Prologue ? "sub" : "add"), Imm); 531 532 Offset += 4; 533 return false; 534 } 535 536 bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset, 537 unsigned Length, bool Prologue) { 538 uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0); 539 540 SW.startLine() 541 << format("0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n", 542 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], 543 static_cast<const char *>(Prologue ? "sub" : "add"), Imm); 544 545 Offset += 3; 546 return false; 547 } 548 549 bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset, 550 unsigned Length, bool Prologue) { 551 uint32_t Imm = (OC[Offset + 1] << 16) 552 | (OC[Offset + 2] << 8) 553 | (OC[Offset + 3] << 0); 554 555 SW.startLine() 556 << format("0x%02x 0x%02x 0x%02x 0x%02x ; %s.w sp, sp, #(%u * 4)\n", 557 OC[Offset + 0], OC[Offset + 1], OC[Offset + 2], OC[Offset + 3], 558 static_cast<const char *>(Prologue ? "sub" : "add"), Imm); 559 560 Offset += 4; 561 return false; 562 } 563 564 bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset, 565 unsigned Length, bool Prologue) { 566 SW.startLine() << format("0x%02x ; nop\n", OC[Offset]); 567 ++Offset; 568 return false; 569 } 570 571 bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset, 572 unsigned Length, bool Prologue) { 573 SW.startLine() << format("0x%02x ; nop.w\n", OC[Offset]); 574 ++Offset; 575 return false; 576 } 577 578 bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset, 579 unsigned Length, bool Prologue) { 580 SW.startLine() << format("0x%02x ; bx <reg>\n", OC[Offset]); 581 ++Offset; 582 return true; 583 } 584 585 bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset, 586 unsigned Length, bool Prologue) { 587 SW.startLine() << format("0x%02x ; b.w <target>\n", OC[Offset]); 588 ++Offset; 589 return true; 590 } 591 592 bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset, 593 unsigned Length, bool Prologue) { 594 ++Offset; 595 return true; 596 } 597 598 // ARM64 unwind codes start here. 599 bool Decoder::opcode_alloc_s(const uint8_t *OC, unsigned &Offset, 600 unsigned Length, bool Prologue) { 601 uint32_t NumBytes = (OC[Offset] & 0x1F) << 4; 602 SW.startLine() << format("0x%02x ; %s sp, #%u\n", OC[Offset], 603 static_cast<const char *>(Prologue ? "sub" : "add"), 604 NumBytes); 605 ++Offset; 606 return false; 607 } 608 609 bool Decoder::opcode_save_r19r20_x(const uint8_t *OC, unsigned &Offset, 610 unsigned Length, bool Prologue) { 611 uint32_t Off = (OC[Offset] & 0x1F) << 3; 612 if (Prologue) 613 SW.startLine() << format( 614 "0x%02x ; stp x19, x20, [sp, #-%u]!\n", OC[Offset], Off); 615 else 616 SW.startLine() << format( 617 "0x%02x ; ldp x19, x20, [sp], #%u\n", OC[Offset], Off); 618 ++Offset; 619 return false; 620 } 621 622 bool Decoder::opcode_save_fplr(const uint8_t *OC, unsigned &Offset, 623 unsigned Length, bool Prologue) { 624 uint32_t Off = (OC[Offset] & 0x3F) << 3; 625 SW.startLine() << format( 626 "0x%02x ; %s x29, x30, [sp, #%u]\n", OC[Offset], 627 static_cast<const char *>(Prologue ? "stp" : "ldp"), Off); 628 ++Offset; 629 return false; 630 } 631 632 bool Decoder::opcode_save_fplr_x(const uint8_t *OC, unsigned &Offset, 633 unsigned Length, bool Prologue) { 634 uint32_t Off = ((OC[Offset] & 0x3F) + 1) << 3; 635 if (Prologue) 636 SW.startLine() << format( 637 "0x%02x ; stp x29, x30, [sp, #-%u]!\n", OC[Offset], Off); 638 else 639 SW.startLine() << format( 640 "0x%02x ; ldp x29, x30, [sp], #%u\n", OC[Offset], Off); 641 ++Offset; 642 return false; 643 } 644 645 bool Decoder::opcode_alloc_m(const uint8_t *OC, unsigned &Offset, 646 unsigned Length, bool Prologue) { 647 uint32_t NumBytes = ((OC[Offset] & 0x07) << 8); 648 NumBytes |= (OC[Offset + 1] & 0xFF); 649 NumBytes <<= 4; 650 SW.startLine() << format("0x%02x%02x ; %s sp, #%u\n", 651 OC[Offset], OC[Offset + 1], 652 static_cast<const char *>(Prologue ? "sub" : "add"), 653 NumBytes); 654 Offset += 2; 655 return false; 656 } 657 658 bool Decoder::opcode_save_regp(const uint8_t *OC, unsigned &Offset, 659 unsigned Length, bool Prologue) { 660 uint32_t Reg = ((OC[Offset] & 0x03) << 8); 661 Reg |= (OC[Offset + 1] & 0xC0); 662 Reg >>= 6; 663 Reg += 19; 664 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 665 SW.startLine() << format( 666 "0x%02x%02x ; %s x%u, x%u, [sp, #%u]\n", 667 OC[Offset], OC[Offset + 1], 668 static_cast<const char *>(Prologue ? "stp" : "ldp"), Reg, Reg + 1, Off); 669 Offset += 2; 670 return false; 671 } 672 673 bool Decoder::opcode_save_regp_x(const uint8_t *OC, unsigned &Offset, 674 unsigned Length, bool Prologue) { 675 uint32_t Reg = ((OC[Offset] & 0x03) << 8); 676 Reg |= (OC[Offset + 1] & 0xC0); 677 Reg >>= 6; 678 Reg += 19; 679 uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3; 680 if (Prologue) 681 SW.startLine() << format( 682 "0x%02x%02x ; stp x%u, x%u, [sp, #-%u]!\n", 683 OC[Offset], OC[Offset + 1], Reg, 684 Reg + 1, Off); 685 else 686 SW.startLine() << format( 687 "0x%02x%02x ; ldp x%u, x%u, [sp], #%u\n", 688 OC[Offset], OC[Offset + 1], Reg, 689 Reg + 1, Off); 690 Offset += 2; 691 return false; 692 } 693 694 bool Decoder::opcode_save_reg(const uint8_t *OC, unsigned &Offset, 695 unsigned Length, bool Prologue) { 696 uint32_t Reg = (OC[Offset] & 0x03) << 8; 697 Reg |= (OC[Offset + 1] & 0xC0); 698 Reg >>= 6; 699 Reg += 19; 700 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 701 SW.startLine() << format("0x%02x%02x ; %s x%u, [sp, #%u]\n", 702 OC[Offset], OC[Offset + 1], 703 static_cast<const char *>(Prologue ? "str" : "ldr"), 704 Reg, Off); 705 Offset += 2; 706 return false; 707 } 708 709 bool Decoder::opcode_save_reg_x(const uint8_t *OC, unsigned &Offset, 710 unsigned Length, bool Prologue) { 711 uint32_t Reg = (OC[Offset] & 0x01) << 8; 712 Reg |= (OC[Offset + 1] & 0xE0); 713 Reg >>= 5; 714 Reg += 19; 715 uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3; 716 if (Prologue) 717 SW.startLine() << format("0x%02x%02x ; str x%u, [sp, #-%u]!\n", 718 OC[Offset], OC[Offset + 1], Reg, Off); 719 else 720 SW.startLine() << format("0x%02x%02x ; ldr x%u, [sp], #%u\n", 721 OC[Offset], OC[Offset + 1], Reg, Off); 722 Offset += 2; 723 return false; 724 } 725 726 bool Decoder::opcode_save_lrpair(const uint8_t *OC, unsigned &Offset, 727 unsigned Length, bool Prologue) { 728 uint32_t Reg = (OC[Offset] & 0x01) << 8; 729 Reg |= (OC[Offset + 1] & 0xC0); 730 Reg >>= 6; 731 Reg *= 2; 732 Reg += 19; 733 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 734 SW.startLine() << format("0x%02x%02x ; %s x%u, lr, [sp, #%u]\n", 735 OC[Offset], OC[Offset + 1], 736 static_cast<const char *>(Prologue ? "stp" : "ldp"), 737 Reg, Off); 738 Offset += 2; 739 return false; 740 } 741 742 bool Decoder::opcode_save_fregp(const uint8_t *OC, unsigned &Offset, 743 unsigned Length, bool Prologue) { 744 uint32_t Reg = (OC[Offset] & 0x01) << 8; 745 Reg |= (OC[Offset + 1] & 0xC0); 746 Reg >>= 6; 747 Reg += 8; 748 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 749 SW.startLine() << format("0x%02x%02x ; %s d%u, d%u, [sp, #%u]\n", 750 OC[Offset], OC[Offset + 1], 751 static_cast<const char *>(Prologue ? "stp" : "ldp"), 752 Reg, Reg + 1, Off); 753 Offset += 2; 754 return false; 755 } 756 757 bool Decoder::opcode_save_fregp_x(const uint8_t *OC, unsigned &Offset, 758 unsigned Length, bool Prologue) { 759 uint32_t Reg = (OC[Offset] & 0x01) << 8; 760 Reg |= (OC[Offset + 1] & 0xC0); 761 Reg >>= 6; 762 Reg += 8; 763 uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3; 764 if (Prologue) 765 SW.startLine() << format( 766 "0x%02x%02x ; stp d%u, d%u, [sp, #-%u]!\n", OC[Offset], 767 OC[Offset + 1], Reg, Reg + 1, Off); 768 else 769 SW.startLine() << format( 770 "0x%02x%02x ; ldp d%u, d%u, [sp], #%u\n", OC[Offset], 771 OC[Offset + 1], Reg, Reg + 1, Off); 772 Offset += 2; 773 return false; 774 } 775 776 bool Decoder::opcode_save_freg(const uint8_t *OC, unsigned &Offset, 777 unsigned Length, bool Prologue) { 778 uint32_t Reg = (OC[Offset] & 0x01) << 8; 779 Reg |= (OC[Offset + 1] & 0xC0); 780 Reg >>= 6; 781 Reg += 8; 782 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; 783 SW.startLine() << format("0x%02x%02x ; %s d%u, [sp, #%u]\n", 784 OC[Offset], OC[Offset + 1], 785 static_cast<const char *>(Prologue ? "str" : "ldr"), 786 Reg, Off); 787 Offset += 2; 788 return false; 789 } 790 791 bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset, 792 unsigned Length, bool Prologue) { 793 uint32_t Reg = ((OC[Offset + 1] & 0xE0) >> 5) + 8; 794 uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3; 795 if (Prologue) 796 SW.startLine() << format( 797 "0x%02x%02x ; str d%u, [sp, #-%u]!\n", OC[Offset], 798 OC[Offset + 1], Reg, Off); 799 else 800 SW.startLine() << format( 801 "0x%02x%02x ; ldr d%u, [sp], #%u\n", OC[Offset], 802 OC[Offset + 1], Reg, Off); 803 Offset += 2; 804 return false; 805 } 806 807 bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset, 808 unsigned Length, bool Prologue) { 809 unsigned Off = 810 (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) | (OC[Offset + 3] << 0); 811 Off <<= 4; 812 SW.startLine() << format( 813 "0x%02x%02x%02x%02x ; %s sp, #%u\n", OC[Offset], OC[Offset + 1], 814 OC[Offset + 2], OC[Offset + 3], 815 static_cast<const char *>(Prologue ? "sub" : "add"), Off); 816 Offset += 4; 817 return false; 818 } 819 820 bool Decoder::opcode_setfp(const uint8_t *OC, unsigned &Offset, unsigned Length, 821 bool Prologue) { 822 SW.startLine() << format("0x%02x ; mov %s, %s\n", OC[Offset], 823 static_cast<const char *>(Prologue ? "fp" : "sp"), 824 static_cast<const char *>(Prologue ? "sp" : "fp")); 825 ++Offset; 826 return false; 827 } 828 829 bool Decoder::opcode_addfp(const uint8_t *OC, unsigned &Offset, unsigned Length, 830 bool Prologue) { 831 unsigned NumBytes = OC[Offset + 1] << 3; 832 SW.startLine() << format( 833 "0x%02x%02x ; %s %s, %s, #%u\n", OC[Offset], OC[Offset + 1], 834 static_cast<const char *>(Prologue ? "add" : "sub"), 835 static_cast<const char *>(Prologue ? "fp" : "sp"), 836 static_cast<const char *>(Prologue ? "sp" : "fp"), NumBytes); 837 Offset += 2; 838 return false; 839 } 840 841 bool Decoder::opcode_nop(const uint8_t *OC, unsigned &Offset, unsigned Length, 842 bool Prologue) { 843 SW.startLine() << format("0x%02x ; nop\n", OC[Offset]); 844 ++Offset; 845 return false; 846 } 847 848 bool Decoder::opcode_end(const uint8_t *OC, unsigned &Offset, unsigned Length, 849 bool Prologue) { 850 SW.startLine() << format("0x%02x ; end\n", OC[Offset]); 851 ++Offset; 852 return true; 853 } 854 855 bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length, 856 bool Prologue) { 857 SW.startLine() << format("0x%02x ; end_c\n", OC[Offset]); 858 ++Offset; 859 return false; 860 } 861 862 bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset, 863 unsigned Length, bool Prologue) { 864 if (Prologue) 865 SW.startLine() << format("0x%02x ; save next\n", OC[Offset]); 866 else 867 SW.startLine() << format("0x%02x ; restore next\n", 868 OC[Offset]); 869 ++Offset; 870 return false; 871 } 872 873 bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset, 874 unsigned Length, bool Prologue) { 875 // Whether the instruction has writeback 876 bool Writeback = (OC[Offset + 1] & 0x20) == 0x20; 877 // Whether the instruction is paired. (Paired instructions are required 878 // to save/restore adjacent registers.) 879 bool Paired = (OC[Offset + 1] & 0x40) == 0x40; 880 // The kind of register saved: 881 // - 0 is an x register 882 // - 1 is the low half of a q register 883 // - 2 is a whole q register 884 int RegKind = (OC[Offset + 2] & 0xC0) >> 6; 885 // Encoded register name (0 -> x0/q0, 1 -> x1/q1, etc.) 886 int Reg = OC[Offset + 1] & 0x1F; 887 // Encoded stack offset of load/store instruction; decoding varies by mode. 888 int StackOffset = OC[Offset + 2] & 0x3F; 889 if (Writeback) 890 StackOffset++; 891 if (!Writeback && !Paired && RegKind != 2) 892 StackOffset *= 8; 893 else 894 StackOffset *= 16; 895 896 SW.startLine() << format("0x%02x%02x%02x ; ", OC[Offset], 897 OC[Offset + 1], OC[Offset + 2]); 898 899 // Verify the encoding is in a form we understand. The high bit of the first 900 // byte, and mode 3 for the register kind are apparently reserved. The 901 // encoded register must refer to a valid register. 902 int MaxReg = 0x1F; 903 if (Paired) 904 --MaxReg; 905 if (RegKind == 0) 906 --MaxReg; 907 if ((OC[Offset + 1] & 0x80) == 0x80 || RegKind == 3 || Reg > MaxReg) { 908 SW.getOStream() << "invalid save_any_reg encoding\n"; 909 Offset += 3; 910 return false; 911 } 912 913 if (Paired) { 914 if (Prologue) 915 SW.getOStream() << "stp "; 916 else 917 SW.getOStream() << "ldp "; 918 } else { 919 if (Prologue) 920 SW.getOStream() << "str "; 921 else 922 SW.getOStream() << "ldr "; 923 } 924 925 char RegChar = 'x'; 926 if (RegKind == 1) { 927 RegChar = 'd'; 928 } else if (RegKind == 2) { 929 RegChar = 'q'; 930 } 931 932 if (Paired) 933 SW.getOStream() << format("%c%d, %c%d, ", RegChar, Reg, RegChar, Reg + 1); 934 else 935 SW.getOStream() << format("%c%d, ", RegChar, Reg); 936 937 if (Writeback) { 938 if (Prologue) 939 SW.getOStream() << format("[sp, #-%d]!\n", StackOffset); 940 else 941 SW.getOStream() << format("[sp], #%d\n", StackOffset); 942 } else { 943 SW.getOStream() << format("[sp, #%d]\n", StackOffset); 944 } 945 946 Offset += 3; 947 return false; 948 } 949 950 bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset, 951 unsigned Length, bool Prologue) { 952 SW.startLine() << format("0x%02x ; trap frame\n", OC[Offset]); 953 ++Offset; 954 return false; 955 } 956 957 bool Decoder::opcode_machine_frame(const uint8_t *OC, unsigned &Offset, 958 unsigned Length, bool Prologue) { 959 SW.startLine() << format("0x%02x ; machine frame\n", 960 OC[Offset]); 961 ++Offset; 962 return false; 963 } 964 965 bool Decoder::opcode_context(const uint8_t *OC, unsigned &Offset, 966 unsigned Length, bool Prologue) { 967 SW.startLine() << format("0x%02x ; context\n", OC[Offset]); 968 ++Offset; 969 return false; 970 } 971 972 bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset, 973 unsigned Length, bool Prologue) { 974 SW.startLine() << format("0x%02x ; clear unwound to call\n", 975 OC[Offset]); 976 ++Offset; 977 return false; 978 } 979 980 bool Decoder::opcode_pac_sign_lr(const uint8_t *OC, unsigned &Offset, 981 unsigned Length, bool Prologue) { 982 if (Prologue) 983 SW.startLine() << format("0x%02x ; pacibsp\n", OC[Offset]); 984 else 985 SW.startLine() << format("0x%02x ; autibsp\n", OC[Offset]); 986 ++Offset; 987 return false; 988 } 989 990 void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset, 991 bool Prologue) { 992 assert((!Prologue || Offset == 0) && "prologue should always use offset 0"); 993 const RingEntry* DecodeRing = isAArch64 ? Ring64 : Ring; 994 bool Terminated = false; 995 for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) { 996 for (unsigned DI = 0;; ++DI) { 997 if ((isAArch64 && (DI >= std::size(Ring64))) || 998 (!isAArch64 && (DI >= std::size(Ring)))) { 999 SW.startLine() << format("0x%02x ; Bad opcode!\n", 1000 Opcodes.data()[OI]); 1001 ++OI; 1002 break; 1003 } 1004 1005 if ((Opcodes[OI] & DecodeRing[DI].Mask) == DecodeRing[DI].Value) { 1006 if (OI + DecodeRing[DI].Length > OE) { 1007 SW.startLine() << format("Opcode 0x%02x goes past the unwind data\n", 1008 Opcodes[OI]); 1009 OI += DecodeRing[DI].Length; 1010 break; 1011 } 1012 Terminated = 1013 (this->*DecodeRing[DI].Routine)(Opcodes.data(), OI, 0, Prologue); 1014 break; 1015 } 1016 } 1017 } 1018 } 1019 1020 bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, 1021 const SectionRef &Section, 1022 uint64_t FunctionAddress, uint64_t VA) { 1023 ArrayRef<uint8_t> Contents; 1024 if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents)) 1025 return false; 1026 1027 uint64_t SectionVA = Section.getAddress(); 1028 uint64_t Offset = VA - SectionVA; 1029 const ulittle32_t *Data = 1030 reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset); 1031 1032 // Sanity check to ensure that the .xdata header is present. 1033 // A header is one or two words, followed by at least one word to describe 1034 // the unwind codes. Applicable to both ARM and AArch64. 1035 if (Contents.size() - Offset < 8) 1036 report_fatal_error(".xdata must be at least 8 bytes in size"); 1037 1038 const ExceptionDataRecord XData(Data, isAArch64); 1039 DictScope XRS(SW, "ExceptionData"); 1040 SW.printNumber("FunctionLength", 1041 isAArch64 ? XData.FunctionLengthInBytesAArch64() : 1042 XData.FunctionLengthInBytesARM()); 1043 SW.printNumber("Version", XData.Vers()); 1044 SW.printBoolean("ExceptionData", XData.X()); 1045 SW.printBoolean("EpiloguePacked", XData.E()); 1046 if (!isAArch64) 1047 SW.printBoolean("Fragment", XData.F()); 1048 SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes", 1049 XData.EpilogueCount()); 1050 uint64_t ByteCodeLength = XData.CodeWords() * sizeof(uint32_t); 1051 SW.printNumber("ByteCodeLength", ByteCodeLength); 1052 1053 if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) - 1054 (XData.E() ? 0 : XData.EpilogueCount() * 4) - 1055 (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) { 1056 SW.flush(); 1057 report_fatal_error("Malformed unwind data"); 1058 } 1059 1060 if (XData.E()) { 1061 ArrayRef<uint8_t> UC = XData.UnwindByteCode(); 1062 { 1063 ListScope PS(SW, "Prologue"); 1064 decodeOpcodes(UC, 0, /*Prologue=*/true); 1065 } 1066 if (XData.EpilogueCount()) { 1067 ListScope ES(SW, "Epilogue"); 1068 decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false); 1069 } 1070 } else { 1071 { 1072 ListScope PS(SW, "Prologue"); 1073 decodeOpcodes(XData.UnwindByteCode(), 0, /*Prologue=*/true); 1074 } 1075 ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes(); 1076 ListScope ESS(SW, "EpilogueScopes"); 1077 for (const EpilogueScope ES : EpilogueScopes) { 1078 DictScope ESES(SW, "EpilogueScope"); 1079 SW.printNumber("StartOffset", ES.EpilogueStartOffset()); 1080 if (!isAArch64) 1081 SW.printNumber("Condition", ES.Condition()); 1082 SW.printNumber("EpilogueStartIndex", 1083 isAArch64 ? ES.EpilogueStartIndexAArch64() 1084 : ES.EpilogueStartIndexARM()); 1085 unsigned ReservedMask = isAArch64 ? 0xF : 0x3; 1086 if ((ES.ES >> 18) & ReservedMask) 1087 SW.printNumber("ReservedBits", (ES.ES >> 18) & ReservedMask); 1088 1089 ListScope Opcodes(SW, "Opcodes"); 1090 decodeOpcodes(XData.UnwindByteCode(), 1091 isAArch64 ? ES.EpilogueStartIndexAArch64() 1092 : ES.EpilogueStartIndexARM(), 1093 /*Prologue=*/false); 1094 } 1095 } 1096 1097 if (XData.X()) { 1098 const uint32_t Parameter = XData.ExceptionHandlerParameter(); 1099 const size_t HandlerOffset = HeaderWords(XData) + 1100 (XData.E() ? 0 : XData.EpilogueCount()) + 1101 XData.CodeWords(); 1102 1103 uint64_t Address, SymbolOffset; 1104 ErrorOr<SymbolRef> Symbol = getSymbolForLocation( 1105 COFF, Section, Offset + HandlerOffset * sizeof(uint32_t), 1106 XData.ExceptionHandlerRVA(), Address, SymbolOffset, 1107 /*FunctionOnly=*/true); 1108 if (!Symbol) { 1109 ListScope EHS(SW, "ExceptionHandler"); 1110 SW.printHex("Routine", Address); 1111 SW.printHex("Parameter", Parameter); 1112 return true; 1113 } 1114 1115 Expected<StringRef> Name = Symbol->getName(); 1116 if (!Name) { 1117 std::string Buf; 1118 llvm::raw_string_ostream OS(Buf); 1119 logAllUnhandledErrors(Name.takeError(), OS); 1120 report_fatal_error(Twine(OS.str())); 1121 } 1122 1123 ListScope EHS(SW, "ExceptionHandler"); 1124 SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset)); 1125 SW.printHex("Parameter", Parameter); 1126 } 1127 1128 return true; 1129 } 1130 1131 bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF, 1132 const SectionRef Section, uint64_t Offset, 1133 unsigned Index, const RuntimeFunction &RF) { 1134 assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked && 1135 "packed entry cannot be treated as an unpacked entry"); 1136 1137 uint64_t FunctionAddress, FunctionOffset; 1138 ErrorOr<SymbolRef> Function = getSymbolForLocation( 1139 COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset, 1140 /*FunctionOnly=*/true); 1141 1142 uint64_t XDataAddress, XDataOffset; 1143 ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation( 1144 COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress, 1145 XDataOffset); 1146 1147 if (!RF.BeginAddress && !Function) 1148 return false; 1149 if (!RF.UnwindData && !XDataRecord) 1150 return false; 1151 1152 StringRef FunctionName; 1153 if (Function) { 1154 Expected<StringRef> FunctionNameOrErr = Function->getName(); 1155 if (!FunctionNameOrErr) { 1156 std::string Buf; 1157 llvm::raw_string_ostream OS(Buf); 1158 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); 1159 report_fatal_error(Twine(OS.str())); 1160 } 1161 FunctionName = *FunctionNameOrErr; 1162 } 1163 1164 SW.printString("Function", 1165 formatSymbol(FunctionName, FunctionAddress, FunctionOffset)); 1166 1167 if (XDataRecord) { 1168 Expected<StringRef> Name = XDataRecord->getName(); 1169 if (!Name) { 1170 std::string Buf; 1171 llvm::raw_string_ostream OS(Buf); 1172 logAllUnhandledErrors(Name.takeError(), OS); 1173 report_fatal_error(Twine(OS.str())); 1174 } 1175 1176 SW.printString("ExceptionRecord", 1177 formatSymbol(*Name, XDataAddress, XDataOffset)); 1178 1179 Expected<section_iterator> SIOrErr = XDataRecord->getSection(); 1180 if (!SIOrErr) { 1181 // TODO: Actually report errors helpfully. 1182 consumeError(SIOrErr.takeError()); 1183 return false; 1184 } 1185 section_iterator SI = *SIOrErr; 1186 1187 return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress); 1188 } else { 1189 SW.printString("ExceptionRecord", formatSymbol("", XDataAddress)); 1190 1191 ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress); 1192 if (!Section) 1193 return false; 1194 1195 return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress); 1196 } 1197 } 1198 1199 bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF, 1200 const SectionRef Section, uint64_t Offset, 1201 unsigned Index, const RuntimeFunction &RF) { 1202 assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed || 1203 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && 1204 "unpacked entry cannot be treated as a packed entry"); 1205 1206 uint64_t FunctionAddress, FunctionOffset; 1207 ErrorOr<SymbolRef> Function = getSymbolForLocation( 1208 COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset, 1209 /*FunctionOnly=*/true); 1210 1211 StringRef FunctionName; 1212 if (Function) { 1213 Expected<StringRef> FunctionNameOrErr = Function->getName(); 1214 if (!FunctionNameOrErr) { 1215 std::string Buf; 1216 llvm::raw_string_ostream OS(Buf); 1217 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); 1218 report_fatal_error(Twine(OS.str())); 1219 } 1220 FunctionName = *FunctionNameOrErr; 1221 } 1222 1223 SW.printString("Function", 1224 formatSymbol(FunctionName, FunctionAddress, FunctionOffset)); 1225 SW.printBoolean("Fragment", 1226 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment); 1227 SW.printNumber("FunctionLength", RF.FunctionLength()); 1228 SW.startLine() << "ReturnType: " << RF.Ret() << '\n'; 1229 SW.printBoolean("HomedParameters", RF.H()); 1230 SW.printNumber("Reg", RF.Reg()); 1231 SW.printNumber("R", RF.R()); 1232 SW.printBoolean("LinkRegister", RF.L()); 1233 SW.printBoolean("Chaining", RF.C()); 1234 SW.printNumber("StackAdjustment", StackAdjustment(RF) << 2); 1235 1236 { 1237 ListScope PS(SW, "Prologue"); 1238 1239 uint16_t GPRMask, VFPMask; 1240 std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/true); 1241 1242 if (StackAdjustment(RF) && !PrologueFolding(RF)) 1243 SW.startLine() << "sub sp, sp, #" << StackAdjustment(RF) * 4 << "\n"; 1244 if (VFPMask) { 1245 SW.startLine() << "vpush "; 1246 printVFPMask(VFPMask); 1247 OS << "\n"; 1248 } 1249 if (RF.C()) { 1250 // Count the number of registers pushed below R11 1251 int FpOffset = 4 * llvm::popcount(GPRMask & ((1U << 11) - 1)); 1252 if (FpOffset) 1253 SW.startLine() << "add.w r11, sp, #" << FpOffset << "\n"; 1254 else 1255 SW.startLine() << "mov r11, sp\n"; 1256 } 1257 if (GPRMask) { 1258 SW.startLine() << "push "; 1259 printGPRMask(GPRMask); 1260 OS << "\n"; 1261 } 1262 if (RF.H()) 1263 SW.startLine() << "push {r0-r3}\n"; 1264 } 1265 1266 if (RF.Ret() != ReturnType::RT_NoEpilogue) { 1267 ListScope PS(SW, "Epilogue"); 1268 1269 uint16_t GPRMask, VFPMask; 1270 std::tie(GPRMask, VFPMask) = SavedRegisterMask(RF, /*Prologue=*/false); 1271 1272 if (StackAdjustment(RF) && !EpilogueFolding(RF)) 1273 SW.startLine() << "add sp, sp, #" << StackAdjustment(RF) * 4 << "\n"; 1274 if (VFPMask) { 1275 SW.startLine() << "vpop "; 1276 printVFPMask(VFPMask); 1277 OS << "\n"; 1278 } 1279 if (GPRMask) { 1280 SW.startLine() << "pop "; 1281 printGPRMask(GPRMask); 1282 OS << "\n"; 1283 } 1284 if (RF.H()) { 1285 if (RF.L() == 0 || RF.Ret() != ReturnType::RT_POP) 1286 SW.startLine() << "add sp, sp, #16\n"; 1287 else 1288 SW.startLine() << "ldr pc, [sp], #20\n"; 1289 } 1290 if (RF.Ret() != ReturnType::RT_POP) 1291 SW.startLine() << RF.Ret() << '\n'; 1292 } 1293 1294 return true; 1295 } 1296 1297 bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF, 1298 const SectionRef Section, uint64_t Offset, 1299 unsigned Index, 1300 const RuntimeFunctionARM64 &RF) { 1301 assert((RF.Flag() == RuntimeFunctionFlag::RFF_Packed || 1302 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && 1303 "unpacked entry cannot be treated as a packed entry"); 1304 1305 uint64_t FunctionAddress, FunctionOffset; 1306 ErrorOr<SymbolRef> Function = getSymbolForLocation( 1307 COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset, 1308 /*FunctionOnly=*/true); 1309 1310 StringRef FunctionName; 1311 if (Function) { 1312 Expected<StringRef> FunctionNameOrErr = Function->getName(); 1313 if (!FunctionNameOrErr) { 1314 std::string Buf; 1315 llvm::raw_string_ostream OS(Buf); 1316 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); 1317 report_fatal_error(Twine(OS.str())); 1318 } 1319 FunctionName = *FunctionNameOrErr; 1320 } 1321 1322 SW.printString("Function", 1323 formatSymbol(FunctionName, FunctionAddress, FunctionOffset)); 1324 SW.printBoolean("Fragment", 1325 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment); 1326 SW.printNumber("FunctionLength", RF.FunctionLength()); 1327 SW.printNumber("RegF", RF.RegF()); 1328 SW.printNumber("RegI", RF.RegI()); 1329 SW.printBoolean("HomedParameters", RF.H()); 1330 SW.printNumber("CR", RF.CR()); 1331 SW.printNumber("FrameSize", RF.FrameSize() << 4); 1332 ListScope PS(SW, "Prologue"); 1333 1334 // Synthesize the equivalent prologue according to the documentation 1335 // at https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling, 1336 // printed in reverse order compared to the docs, to match how prologues 1337 // are printed for the non-packed case. 1338 int IntSZ = 8 * RF.RegI(); 1339 if (RF.CR() == 1) 1340 IntSZ += 8; 1341 int FpSZ = 8 * RF.RegF(); 1342 if (RF.RegF()) 1343 FpSZ += 8; 1344 int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf; 1345 int LocSZ = (RF.FrameSize() << 4) - SavSZ; 1346 1347 if (RF.CR() == 2 || RF.CR() == 3) { 1348 SW.startLine() << "mov x29, sp\n"; 1349 if (LocSZ <= 512) { 1350 SW.startLine() << format("stp x29, lr, [sp, #-%d]!\n", LocSZ); 1351 } else { 1352 SW.startLine() << "stp x29, lr, [sp, #0]\n"; 1353 } 1354 } 1355 if (LocSZ > 4080) { 1356 SW.startLine() << format("sub sp, sp, #%d\n", LocSZ - 4080); 1357 SW.startLine() << "sub sp, sp, #4080\n"; 1358 } else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) { 1359 SW.startLine() << format("sub sp, sp, #%d\n", LocSZ); 1360 } 1361 if (RF.H()) { 1362 SW.startLine() << format("stp x6, x7, [sp, #%d]\n", SavSZ - 16); 1363 SW.startLine() << format("stp x4, x5, [sp, #%d]\n", SavSZ - 32); 1364 SW.startLine() << format("stp x2, x3, [sp, #%d]\n", SavSZ - 48); 1365 if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) { 1366 SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64); 1367 } else { 1368 // This case isn't documented; if neither RegI nor RegF nor CR=1 1369 // have decremented the stack pointer by SavSZ, we need to do it here 1370 // (as the final stack adjustment of LocSZ excludes SavSZ). 1371 SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ); 1372 } 1373 } 1374 int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0; 1375 for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) { 1376 if (I == (FloatRegs + 1) / 2 - 1 && FloatRegs % 2 == 1) { 1377 // The last register, an odd register without a pair 1378 SW.startLine() << format("str d%d, [sp, #%d]\n", 8 + 2 * I, 1379 IntSZ + 16 * I); 1380 } else if (I == 0 && RF.RegI() == 0 && RF.CR() != 1) { 1381 SW.startLine() << format("stp d%d, d%d, [sp, #-%d]!\n", 8 + 2 * I, 1382 8 + 2 * I + 1, SavSZ); 1383 } else { 1384 SW.startLine() << format("stp d%d, d%d, [sp, #%d]\n", 8 + 2 * I, 1385 8 + 2 * I + 1, IntSZ + 16 * I); 1386 } 1387 } 1388 if (RF.CR() == 1 && (RF.RegI() % 2) == 0) { 1389 if (RF.RegI() == 0) 1390 SW.startLine() << format("str lr, [sp, #-%d]!\n", SavSZ); 1391 else 1392 SW.startLine() << format("str lr, [sp, #%d]\n", IntSZ - 8); 1393 } 1394 for (int I = (RF.RegI() + 1) / 2 - 1; I >= 0; I--) { 1395 if (I == (RF.RegI() + 1) / 2 - 1 && RF.RegI() % 2 == 1) { 1396 // The last register, an odd register without a pair 1397 if (RF.CR() == 1) { 1398 if (I == 0) { // If this is the only register pair 1399 // CR=1 combined with RegI=1 doesn't map to a documented case; 1400 // it doesn't map to any regular unwind info opcode, and the 1401 // actual unwinder doesn't support it. 1402 SW.startLine() << "INVALID!\n"; 1403 } else 1404 SW.startLine() << format("stp x%d, lr, [sp, #%d]\n", 19 + 2 * I, 1405 16 * I); 1406 } else { 1407 if (I == 0) 1408 SW.startLine() << format("str x%d, [sp, #-%d]!\n", 19 + 2 * I, SavSZ); 1409 else 1410 SW.startLine() << format("str x%d, [sp, #%d]\n", 19 + 2 * I, 16 * I); 1411 } 1412 } else if (I == 0) { 1413 // The first register pair 1414 SW.startLine() << format("stp x19, x20, [sp, #-%d]!\n", SavSZ); 1415 } else { 1416 SW.startLine() << format("stp x%d, x%d, [sp, #%d]\n", 19 + 2 * I, 1417 19 + 2 * I + 1, 16 * I); 1418 } 1419 } 1420 // CR=2 is yet undocumented, see 1421 // https://github.com/MicrosoftDocs/cpp-docs/pull/4202 for upstream 1422 // progress on getting it documented. 1423 if (RF.CR() == 2) 1424 SW.startLine() << "pacibsp\n"; 1425 SW.startLine() << "end\n"; 1426 1427 return true; 1428 } 1429 1430 bool Decoder::dumpProcedureDataEntry(const COFFObjectFile &COFF, 1431 const SectionRef Section, unsigned Index, 1432 ArrayRef<uint8_t> Contents) { 1433 uint64_t Offset = PDataEntrySize * Index; 1434 const ulittle32_t *Data = 1435 reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset); 1436 1437 const RuntimeFunction Entry(Data); 1438 DictScope RFS(SW, "RuntimeFunction"); 1439 if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked) 1440 return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry); 1441 if (isAArch64) { 1442 const RuntimeFunctionARM64 EntryARM64(Data); 1443 return dumpPackedARM64Entry(COFF, Section, Offset, Index, EntryARM64); 1444 } 1445 return dumpPackedEntry(COFF, Section, Offset, Index, Entry); 1446 } 1447 1448 void Decoder::dumpProcedureData(const COFFObjectFile &COFF, 1449 const SectionRef Section) { 1450 ArrayRef<uint8_t> Contents; 1451 if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents)) 1452 return; 1453 1454 if (Contents.size() % PDataEntrySize) { 1455 errs() << ".pdata content is not " << PDataEntrySize << "-byte aligned\n"; 1456 return; 1457 } 1458 1459 for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI) 1460 if (!dumpProcedureDataEntry(COFF, Section, EI, Contents)) 1461 break; 1462 } 1463 1464 Error Decoder::dumpProcedureData(const COFFObjectFile &COFF) { 1465 for (const auto &Section : COFF.sections()) { 1466 Expected<StringRef> NameOrErr = 1467 COFF.getSectionName(COFF.getCOFFSection(Section)); 1468 if (!NameOrErr) 1469 return NameOrErr.takeError(); 1470 1471 if (NameOrErr->startswith(".pdata")) 1472 dumpProcedureData(COFF, Section); 1473 } 1474 return Error::success(); 1475 } 1476 } 1477 } 1478 } 1479