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