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