1 //===----------------------------------------------------------------------===// 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 // Parses DWARF CFIs (FDEs and CIEs). 9 // 10 //===----------------------------------------------------------------------===// 11 12 #ifndef __DWARF_PARSER_HPP__ 13 #define __DWARF_PARSER_HPP__ 14 15 #include <inttypes.h> 16 #include <stdint.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 20 #include "libunwind.h" 21 #include "dwarf2.h" 22 #include "Registers.hpp" 23 24 #include "config.h" 25 26 namespace libunwind { 27 28 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. 29 /// See DWARF Spec for details: 30 /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 31 /// 32 template <typename A> 33 class CFI_Parser { 34 public: 35 typedef typename A::pint_t pint_t; 36 37 /// Information encoded in a CIE (Common Information Entry) 38 struct CIE_Info { 39 pint_t cieStart; 40 pint_t cieLength; 41 pint_t cieInstructions; 42 uint8_t pointerEncoding; 43 uint8_t lsdaEncoding; 44 uint8_t personalityEncoding; 45 uint8_t personalityOffsetInCIE; 46 pint_t personality; 47 uint32_t codeAlignFactor; 48 int dataAlignFactor; 49 bool isSignalFrame; 50 bool fdesHaveAugmentationData; 51 uint8_t returnAddressRegister; 52 #if defined(_LIBUNWIND_TARGET_AARCH64) 53 bool addressesSignedWithBKey; 54 bool mteTaggedFrame; 55 #endif 56 }; 57 58 /// Information about an FDE (Frame Description Entry) 59 struct FDE_Info { 60 pint_t fdeStart; 61 pint_t fdeLength; 62 pint_t fdeInstructions; 63 pint_t pcStart; 64 pint_t pcEnd; 65 pint_t lsda; 66 }; 67 68 enum { 69 kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER 70 }; 71 enum RegisterSavedWhere { 72 kRegisterUnused, 73 kRegisterUndefined, 74 kRegisterInCFA, 75 kRegisterInCFADecrypt, // sparc64 specific 76 kRegisterOffsetFromCFA, 77 kRegisterInRegister, 78 kRegisterAtExpression, 79 kRegisterIsExpression 80 }; 81 struct RegisterLocation { 82 RegisterSavedWhere location; 83 bool initialStateSaved; 84 int64_t value; 85 }; 86 /// Information about a frame layout and registers saved determined 87 /// by "running" the DWARF FDE "instructions" 88 struct PrologInfo { 89 uint32_t cfaRegister; 90 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset 91 int64_t cfaExpression; // CFA = expression 92 uint32_t spExtraArgSize; 93 RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; 94 #if defined(_LIBUNWIND_TARGET_AARCH64) 95 pint_t ptrAuthDiversifier; 96 #endif 97 enum class InitializeTime { kLazy, kNormal }; 98 99 // When saving registers, this data structure is lazily initialized. 100 PrologInfo(InitializeTime IT = InitializeTime::kNormal) { 101 if (IT == InitializeTime::kNormal) 102 memset(this, 0, sizeof(*this)); 103 } 104 void checkSaveRegister(uint64_t reg, PrologInfo &initialState) { 105 if (!savedRegisters[reg].initialStateSaved) { 106 initialState.savedRegisters[reg] = savedRegisters[reg]; 107 savedRegisters[reg].initialStateSaved = true; 108 } 109 } 110 void setRegister(uint64_t reg, RegisterSavedWhere newLocation, 111 int64_t newValue, PrologInfo &initialState) { 112 checkSaveRegister(reg, initialState); 113 savedRegisters[reg].location = newLocation; 114 savedRegisters[reg].value = newValue; 115 } 116 void setRegisterLocation(uint64_t reg, RegisterSavedWhere newLocation, 117 PrologInfo &initialState) { 118 checkSaveRegister(reg, initialState); 119 savedRegisters[reg].location = newLocation; 120 } 121 void setRegisterValue(uint64_t reg, int64_t newValue, 122 PrologInfo &initialState) { 123 checkSaveRegister(reg, initialState); 124 savedRegisters[reg].value = newValue; 125 } 126 void restoreRegisterToInitialState(uint64_t reg, PrologInfo &initialState) { 127 if (savedRegisters[reg].initialStateSaved) 128 savedRegisters[reg] = initialState.savedRegisters[reg]; 129 // else the register still holds its initial state 130 } 131 }; 132 133 struct PrologInfoStackEntry { 134 PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i) 135 : next(n), info(i) {} 136 PrologInfoStackEntry *next; 137 PrologInfo info; 138 }; 139 140 struct RememberStack { 141 PrologInfoStackEntry *entry; 142 RememberStack() : entry(nullptr) {} 143 ~RememberStack() { 144 #if defined(_LIBUNWIND_REMEMBER_CLEANUP_NEEDED) 145 // Clean up rememberStack. Even in the case where every 146 // DW_CFA_remember_state is paired with a DW_CFA_restore_state, 147 // parseInstructions can skip restore opcodes if it reaches the target PC 148 // and stops interpreting, so we have to make sure we don't leak memory. 149 while (entry) { 150 PrologInfoStackEntry *next = entry->next; 151 _LIBUNWIND_REMEMBER_FREE(entry); 152 entry = next; 153 } 154 #endif 155 } 156 }; 157 158 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, 159 size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, 160 CIE_Info *cieInfo); 161 static const char *decodeFDE(A &addressSpace, pint_t fdeStart, 162 FDE_Info *fdeInfo, CIE_Info *cieInfo, 163 bool useCIEInfo = false); 164 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, 165 const CIE_Info &cieInfo, pint_t upToPC, 166 int arch, PrologInfo *results); 167 168 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); 169 }; 170 171 /// Parse a FDE into a CIE_Info and an FDE_Info. If useCIEInfo is 172 /// true, treat cieInfo as already-parsed CIE_Info (whose start offset 173 /// must match the one specified by the FDE) rather than parsing the 174 /// one indicated within the FDE. 175 template <typename A> 176 const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, 177 FDE_Info *fdeInfo, CIE_Info *cieInfo, 178 bool useCIEInfo) { 179 pint_t p = fdeStart; 180 pint_t cfiLength = (pint_t)addressSpace.get32(p); 181 p += 4; 182 if (cfiLength == 0xffffffff) { 183 // 0xffffffff means length is really next 8 bytes 184 cfiLength = (pint_t)addressSpace.get64(p); 185 p += 8; 186 } 187 if (cfiLength == 0) 188 return "FDE has zero length"; // zero terminator 189 uint32_t ciePointer = addressSpace.get32(p); 190 if (ciePointer == 0) 191 return "FDE is really a CIE"; // this is a CIE not an FDE 192 pint_t nextCFI = p + cfiLength; 193 pint_t cieStart = p - ciePointer; 194 if (useCIEInfo) { 195 if (cieInfo->cieStart != cieStart) 196 return "CIE start does not match"; 197 } else { 198 const char *err = parseCIE(addressSpace, cieStart, cieInfo); 199 if (err != NULL) 200 return err; 201 } 202 p += 4; 203 // Parse pc begin and range. 204 pint_t pcStart = 205 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); 206 pint_t pcRange = 207 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F); 208 // Parse rest of info. 209 fdeInfo->lsda = 0; 210 // Check for augmentation length. 211 if (cieInfo->fdesHaveAugmentationData) { 212 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); 213 pint_t endOfAug = p + augLen; 214 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { 215 // Peek at value (without indirection). Zero means no LSDA. 216 pint_t lsdaStart = p; 217 if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 218 0) { 219 // Reset pointer and re-parse LSDA address. 220 p = lsdaStart; 221 fdeInfo->lsda = 222 addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); 223 } 224 } 225 p = endOfAug; 226 } 227 fdeInfo->fdeStart = fdeStart; 228 fdeInfo->fdeLength = nextCFI - fdeStart; 229 fdeInfo->fdeInstructions = p; 230 fdeInfo->pcStart = pcStart; 231 fdeInfo->pcEnd = pcStart + pcRange; 232 return NULL; // success 233 } 234 235 /// Scan an eh_frame section to find an FDE for a pc 236 template <typename A> 237 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, 238 size_t sectionLength, pint_t fdeHint, 239 FDE_Info *fdeInfo, CIE_Info *cieInfo) { 240 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); 241 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; 242 const pint_t ehSectionEnd = (sectionLength == SIZE_MAX) 243 ? static_cast<pint_t>(-1) 244 : (ehSectionStart + sectionLength); 245 while (p < ehSectionEnd) { 246 pint_t currentCFI = p; 247 //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); 248 pint_t cfiLength = addressSpace.get32(p); 249 p += 4; 250 if (cfiLength == 0xffffffff) { 251 // 0xffffffff means length is really next 8 bytes 252 cfiLength = (pint_t)addressSpace.get64(p); 253 p += 8; 254 } 255 if (cfiLength == 0) 256 return false; // zero terminator 257 uint32_t id = addressSpace.get32(p); 258 if (id == 0) { 259 // Skip over CIEs. 260 p += cfiLength; 261 } else { 262 // Process FDE to see if it covers pc. 263 pint_t nextCFI = p + cfiLength; 264 uint32_t ciePointer = addressSpace.get32(p); 265 pint_t cieStart = p - ciePointer; 266 // Validate pointer to CIE is within section. 267 if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) { 268 if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) { 269 p += 4; 270 // Parse pc begin and range. 271 pint_t pcStart = 272 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding); 273 pint_t pcRange = addressSpace.getEncodedP( 274 p, nextCFI, cieInfo->pointerEncoding & 0x0F); 275 // Test if pc is within the function this FDE covers. 276 if ((pcStart < pc) && (pc <= pcStart + pcRange)) { 277 // parse rest of info 278 fdeInfo->lsda = 0; 279 // check for augmentation length 280 if (cieInfo->fdesHaveAugmentationData) { 281 pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI); 282 pint_t endOfAug = p + augLen; 283 if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { 284 // Peek at value (without indirection). Zero means no LSDA. 285 pint_t lsdaStart = p; 286 if (addressSpace.getEncodedP( 287 p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) { 288 // Reset pointer and re-parse LSDA address. 289 p = lsdaStart; 290 fdeInfo->lsda = addressSpace 291 .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding); 292 } 293 } 294 p = endOfAug; 295 } 296 fdeInfo->fdeStart = currentCFI; 297 fdeInfo->fdeLength = nextCFI - currentCFI; 298 fdeInfo->fdeInstructions = p; 299 fdeInfo->pcStart = pcStart; 300 fdeInfo->pcEnd = pcStart + pcRange; 301 return true; 302 } else { 303 // pc is not in begin/range, skip this FDE 304 } 305 } else { 306 // Malformed CIE, now augmentation describing pc range encoding. 307 } 308 } else { 309 // malformed FDE. CIE is bad 310 } 311 p = nextCFI; 312 } 313 } 314 return false; 315 } 316 317 /// Extract info from a CIE 318 template <typename A> 319 const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, 320 CIE_Info *cieInfo) { 321 cieInfo->pointerEncoding = 0; 322 cieInfo->lsdaEncoding = DW_EH_PE_omit; 323 cieInfo->personalityEncoding = 0; 324 cieInfo->personalityOffsetInCIE = 0; 325 cieInfo->personality = 0; 326 cieInfo->codeAlignFactor = 0; 327 cieInfo->dataAlignFactor = 0; 328 cieInfo->isSignalFrame = false; 329 cieInfo->fdesHaveAugmentationData = false; 330 #if defined(_LIBUNWIND_TARGET_AARCH64) 331 cieInfo->addressesSignedWithBKey = false; 332 cieInfo->mteTaggedFrame = false; 333 #endif 334 cieInfo->cieStart = cie; 335 pint_t p = cie; 336 pint_t cieLength = (pint_t)addressSpace.get32(p); 337 p += 4; 338 pint_t cieContentEnd = p + cieLength; 339 if (cieLength == 0xffffffff) { 340 // 0xffffffff means length is really next 8 bytes 341 cieLength = (pint_t)addressSpace.get64(p); 342 p += 8; 343 cieContentEnd = p + cieLength; 344 } 345 if (cieLength == 0) 346 return NULL; 347 // CIE ID is always 0 348 if (addressSpace.get32(p) != 0) 349 return "CIE ID is not zero"; 350 p += 4; 351 // Version is always 1 or 3 352 uint8_t version = addressSpace.get8(p); 353 if ((version != 1) && (version != 3)) 354 return "CIE version is not 1 or 3"; 355 ++p; 356 // save start of augmentation string and find end 357 pint_t strStart = p; 358 while (addressSpace.get8(p) != 0) 359 ++p; 360 ++p; 361 // parse code alignment factor 362 cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd); 363 // parse data alignment factor 364 cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); 365 // parse return address register 366 uint64_t raReg = (version == 1) ? addressSpace.get8(p++) 367 : addressSpace.getULEB128(p, cieContentEnd); 368 assert(raReg < 255 && "return address register too large"); 369 cieInfo->returnAddressRegister = (uint8_t)raReg; 370 // parse augmentation data based on augmentation string 371 const char *result = NULL; 372 if (addressSpace.get8(strStart) == 'z') { 373 // parse augmentation data length 374 addressSpace.getULEB128(p, cieContentEnd); 375 for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) { 376 switch (addressSpace.get8(s)) { 377 case 'z': 378 cieInfo->fdesHaveAugmentationData = true; 379 break; 380 case 'P': 381 cieInfo->personalityEncoding = addressSpace.get8(p); 382 ++p; 383 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie); 384 cieInfo->personality = addressSpace 385 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); 386 break; 387 case 'L': 388 cieInfo->lsdaEncoding = addressSpace.get8(p); 389 ++p; 390 break; 391 case 'R': 392 cieInfo->pointerEncoding = addressSpace.get8(p); 393 ++p; 394 break; 395 case 'S': 396 cieInfo->isSignalFrame = true; 397 break; 398 #if defined(_LIBUNWIND_TARGET_AARCH64) 399 case 'B': 400 cieInfo->addressesSignedWithBKey = true; 401 break; 402 case 'G': 403 cieInfo->mteTaggedFrame = true; 404 break; 405 #endif 406 default: 407 // ignore unknown letters 408 break; 409 } 410 } 411 } 412 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart; 413 cieInfo->cieInstructions = p; 414 return result; 415 } 416 417 418 /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE 419 template <typename A> 420 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, 421 const FDE_Info &fdeInfo, 422 const CIE_Info &cieInfo, pint_t upToPC, 423 int arch, PrologInfo *results) { 424 // Alloca is used for the allocation of the rememberStack entries. It removes 425 // the dependency on new/malloc but the below for loop can not be refactored 426 // into functions. Entry could be saved during the processing of a CIE and 427 // restored by an FDE. 428 RememberStack rememberStack; 429 430 struct ParseInfo { 431 pint_t instructions; 432 pint_t instructionsEnd; 433 pint_t pcoffset; 434 }; 435 436 ParseInfo parseInfoArray[] = { 437 {cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, 438 (pint_t)(-1)}, 439 {fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength, 440 upToPC - fdeInfo.pcStart}}; 441 442 for (const auto &info : parseInfoArray) { 443 pint_t p = info.instructions; 444 pint_t instructionsEnd = info.instructionsEnd; 445 pint_t pcoffset = info.pcoffset; 446 pint_t codeOffset = 0; 447 448 // initialState initialized as registers in results are modified. Use 449 // PrologInfo accessor functions to avoid reading uninitialized data. 450 PrologInfo initialState(PrologInfo::InitializeTime::kLazy); 451 452 _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(instructions=0x%0" PRIx64 453 ")\n", 454 static_cast<uint64_t>(instructionsEnd)); 455 456 // see DWARF Spec, section 6.4.2 for details on unwind opcodes 457 while ((p < instructionsEnd) && (codeOffset < pcoffset)) { 458 uint64_t reg; 459 uint64_t reg2; 460 int64_t offset; 461 uint64_t length; 462 uint8_t opcode = addressSpace.get8(p); 463 uint8_t operand; 464 465 ++p; 466 switch (opcode) { 467 case DW_CFA_nop: 468 _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); 469 break; 470 case DW_CFA_set_loc: 471 codeOffset = addressSpace.getEncodedP(p, instructionsEnd, 472 cieInfo.pointerEncoding); 473 _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); 474 break; 475 case DW_CFA_advance_loc1: 476 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); 477 p += 1; 478 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", 479 static_cast<uint64_t>(codeOffset)); 480 break; 481 case DW_CFA_advance_loc2: 482 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); 483 p += 2; 484 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", 485 static_cast<uint64_t>(codeOffset)); 486 break; 487 case DW_CFA_advance_loc4: 488 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); 489 p += 4; 490 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", 491 static_cast<uint64_t>(codeOffset)); 492 break; 493 case DW_CFA_offset_extended: 494 reg = addressSpace.getULEB128(p, instructionsEnd); 495 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * 496 cieInfo.dataAlignFactor; 497 if (reg > kMaxRegisterNumber) { 498 _LIBUNWIND_LOG0( 499 "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); 500 return false; 501 } 502 results->setRegister(reg, kRegisterInCFA, offset, initialState); 503 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " 504 "offset=%" PRId64 ")\n", 505 reg, offset); 506 break; 507 case DW_CFA_restore_extended: 508 reg = addressSpace.getULEB128(p, instructionsEnd); 509 if (reg > kMaxRegisterNumber) { 510 _LIBUNWIND_LOG0( 511 "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); 512 return false; 513 } 514 results->restoreRegisterToInitialState(reg, initialState); 515 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", 516 reg); 517 break; 518 case DW_CFA_undefined: 519 reg = addressSpace.getULEB128(p, instructionsEnd); 520 if (reg > kMaxRegisterNumber) { 521 _LIBUNWIND_LOG0( 522 "malformed DW_CFA_undefined DWARF unwind, reg too big"); 523 return false; 524 } 525 results->setRegisterLocation(reg, kRegisterUndefined, initialState); 526 _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); 527 break; 528 case DW_CFA_same_value: 529 reg = addressSpace.getULEB128(p, instructionsEnd); 530 if (reg > kMaxRegisterNumber) { 531 _LIBUNWIND_LOG0( 532 "malformed DW_CFA_same_value DWARF unwind, reg too big"); 533 return false; 534 } 535 // <rdar://problem/8456377> DW_CFA_same_value unsupported 536 // "same value" means register was stored in frame, but its current 537 // value has not changed, so no need to restore from frame. 538 // We model this as if the register was never saved. 539 results->setRegisterLocation(reg, kRegisterUnused, initialState); 540 _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); 541 break; 542 case DW_CFA_register: 543 reg = addressSpace.getULEB128(p, instructionsEnd); 544 reg2 = addressSpace.getULEB128(p, instructionsEnd); 545 if (reg > kMaxRegisterNumber) { 546 _LIBUNWIND_LOG0( 547 "malformed DW_CFA_register DWARF unwind, reg too big"); 548 return false; 549 } 550 if (reg2 > kMaxRegisterNumber) { 551 _LIBUNWIND_LOG0( 552 "malformed DW_CFA_register DWARF unwind, reg2 too big"); 553 return false; 554 } 555 results->setRegister(reg, kRegisterInRegister, (int64_t)reg2, 556 initialState); 557 _LIBUNWIND_TRACE_DWARF( 558 "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); 559 break; 560 case DW_CFA_remember_state: { 561 // Avoid operator new because that would be an upward dependency. 562 // Avoid malloc because it needs heap allocation. 563 PrologInfoStackEntry *entry = 564 (PrologInfoStackEntry *)_LIBUNWIND_REMEMBER_ALLOC( 565 sizeof(PrologInfoStackEntry)); 566 if (entry != NULL) { 567 entry->next = rememberStack.entry; 568 entry->info = *results; 569 rememberStack.entry = entry; 570 } else { 571 return false; 572 } 573 _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); 574 break; 575 } 576 case DW_CFA_restore_state: 577 if (rememberStack.entry != NULL) { 578 PrologInfoStackEntry *top = rememberStack.entry; 579 *results = top->info; 580 rememberStack.entry = top->next; 581 _LIBUNWIND_REMEMBER_FREE(top); 582 } else { 583 return false; 584 } 585 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n"); 586 break; 587 case DW_CFA_def_cfa: 588 reg = addressSpace.getULEB128(p, instructionsEnd); 589 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); 590 if (reg > kMaxRegisterNumber) { 591 _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); 592 return false; 593 } 594 results->cfaRegister = (uint32_t)reg; 595 results->cfaRegisterOffset = (int32_t)offset; 596 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 597 ")\n", 598 reg, offset); 599 break; 600 case DW_CFA_def_cfa_register: 601 reg = addressSpace.getULEB128(p, instructionsEnd); 602 if (reg > kMaxRegisterNumber) { 603 _LIBUNWIND_LOG0( 604 "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); 605 return false; 606 } 607 results->cfaRegister = (uint32_t)reg; 608 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); 609 break; 610 case DW_CFA_def_cfa_offset: 611 results->cfaRegisterOffset = 612 (int32_t)addressSpace.getULEB128(p, instructionsEnd); 613 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n", 614 results->cfaRegisterOffset); 615 break; 616 case DW_CFA_def_cfa_expression: 617 results->cfaRegister = 0; 618 results->cfaExpression = (int64_t)p; 619 length = addressSpace.getULEB128(p, instructionsEnd); 620 assert(length < static_cast<pint_t>(~0) && "pointer overflow"); 621 p += static_cast<pint_t>(length); 622 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64 623 ", length=%" PRIu64 ")\n", 624 results->cfaExpression, length); 625 break; 626 case DW_CFA_expression: 627 reg = addressSpace.getULEB128(p, instructionsEnd); 628 if (reg > kMaxRegisterNumber) { 629 _LIBUNWIND_LOG0( 630 "malformed DW_CFA_expression DWARF unwind, reg too big"); 631 return false; 632 } 633 results->setRegister(reg, kRegisterAtExpression, (int64_t)p, 634 initialState); 635 length = addressSpace.getULEB128(p, instructionsEnd); 636 assert(length < static_cast<pint_t>(~0) && "pointer overflow"); 637 p += static_cast<pint_t>(length); 638 _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " 639 "expression=0x%" PRIx64 ", " 640 "length=%" PRIu64 ")\n", 641 reg, results->savedRegisters[reg].value, length); 642 break; 643 case DW_CFA_offset_extended_sf: 644 reg = addressSpace.getULEB128(p, instructionsEnd); 645 if (reg > kMaxRegisterNumber) { 646 _LIBUNWIND_LOG0( 647 "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); 648 return false; 649 } 650 offset = addressSpace.getSLEB128(p, instructionsEnd) * 651 cieInfo.dataAlignFactor; 652 results->setRegister(reg, kRegisterInCFA, offset, initialState); 653 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " 654 "offset=%" PRId64 ")\n", 655 reg, offset); 656 break; 657 case DW_CFA_def_cfa_sf: 658 reg = addressSpace.getULEB128(p, instructionsEnd); 659 offset = addressSpace.getSLEB128(p, instructionsEnd) * 660 cieInfo.dataAlignFactor; 661 if (reg > kMaxRegisterNumber) { 662 _LIBUNWIND_LOG0( 663 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); 664 return false; 665 } 666 results->cfaRegister = (uint32_t)reg; 667 results->cfaRegisterOffset = (int32_t)offset; 668 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", " 669 "offset=%" PRId64 ")\n", 670 reg, offset); 671 break; 672 case DW_CFA_def_cfa_offset_sf: 673 results->cfaRegisterOffset = 674 (int32_t)(addressSpace.getSLEB128(p, instructionsEnd) * 675 cieInfo.dataAlignFactor); 676 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n", 677 results->cfaRegisterOffset); 678 break; 679 case DW_CFA_val_offset: 680 reg = addressSpace.getULEB128(p, instructionsEnd); 681 if (reg > kMaxRegisterNumber) { 682 _LIBUNWIND_LOG( 683 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 684 ") out of range\n", 685 reg); 686 return false; 687 } 688 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * 689 cieInfo.dataAlignFactor; 690 results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); 691 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " 692 "offset=%" PRId64 "\n", 693 reg, offset); 694 break; 695 case DW_CFA_val_offset_sf: 696 reg = addressSpace.getULEB128(p, instructionsEnd); 697 if (reg > kMaxRegisterNumber) { 698 _LIBUNWIND_LOG0( 699 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); 700 return false; 701 } 702 offset = addressSpace.getSLEB128(p, instructionsEnd) * 703 cieInfo.dataAlignFactor; 704 results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); 705 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " 706 "offset=%" PRId64 "\n", 707 reg, offset); 708 break; 709 case DW_CFA_val_expression: 710 reg = addressSpace.getULEB128(p, instructionsEnd); 711 if (reg > kMaxRegisterNumber) { 712 _LIBUNWIND_LOG0( 713 "malformed DW_CFA_val_expression DWARF unwind, reg too big"); 714 return false; 715 } 716 results->setRegister(reg, kRegisterIsExpression, (int64_t)p, 717 initialState); 718 length = addressSpace.getULEB128(p, instructionsEnd); 719 assert(length < static_cast<pint_t>(~0) && "pointer overflow"); 720 p += static_cast<pint_t>(length); 721 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " 722 "expression=0x%" PRIx64 ", length=%" PRIu64 723 ")\n", 724 reg, results->savedRegisters[reg].value, length); 725 break; 726 case DW_CFA_GNU_args_size: 727 length = addressSpace.getULEB128(p, instructionsEnd); 728 results->spExtraArgSize = (uint32_t)length; 729 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); 730 break; 731 case DW_CFA_GNU_negative_offset_extended: 732 reg = addressSpace.getULEB128(p, instructionsEnd); 733 if (reg > kMaxRegisterNumber) { 734 _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " 735 "unwind, reg too big"); 736 return false; 737 } 738 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * 739 cieInfo.dataAlignFactor; 740 results->setRegister(reg, kRegisterInCFA, -offset, initialState); 741 _LIBUNWIND_TRACE_DWARF( 742 "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); 743 break; 744 745 #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) || \ 746 defined(_LIBUNWIND_TARGET_SPARC64) 747 // The same constant is used to represent different instructions on 748 // AArch64 (negate_ra_state) and SPARC (window_save). 749 static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, 750 "uses the same constant"); 751 case DW_CFA_AARCH64_negate_ra_state: 752 switch (arch) { 753 #if defined(_LIBUNWIND_TARGET_AARCH64) 754 case REGISTERS_ARM64: { 755 int64_t value = 756 results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x1; 757 results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, 758 initialState); 759 _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); 760 } break; 761 #endif 762 763 #if defined(_LIBUNWIND_TARGET_SPARC) 764 // case DW_CFA_GNU_window_save: 765 case REGISTERS_SPARC: 766 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); 767 for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { 768 results->setRegister(reg, kRegisterInRegister, 769 ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0, 770 initialState); 771 } 772 773 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { 774 results->setRegister(reg, kRegisterInCFA, 775 ((int64_t)reg - UNW_SPARC_L0) * 4, 776 initialState); 777 } 778 break; 779 #endif 780 781 #if defined(_LIBUNWIND_TARGET_SPARC64) 782 // case DW_CFA_GNU_window_save: 783 case REGISTERS_SPARC64: 784 // Don't save %o0-%o7 on sparc64. 785 // https://reviews.llvm.org/D32450#736405 786 787 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { 788 if (reg == UNW_SPARC_I7) 789 results->setRegister( 790 reg, kRegisterInCFADecrypt, 791 static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)), 792 initialState); 793 else 794 results->setRegister( 795 reg, kRegisterInCFA, 796 static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)), 797 initialState); 798 } 799 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n"); 800 break; 801 #endif 802 } 803 break; 804 805 #if defined(_LIBUNWIND_TARGET_AARCH64) 806 case DW_CFA_AARCH64_negate_ra_state_with_pc: { 807 int64_t value = 808 results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3; 809 results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, 810 initialState); 811 // When calculating the value of the PC, it is assumed that the CFI 812 // instruction is placed before the signing instruction, however it is 813 // placed after. Because of this, we need to take into account the CFI 814 // instruction is one instruction call later than expected, and reduce 815 // the PC value by 4 bytes to compensate. 816 results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4; 817 _LIBUNWIND_TRACE_DWARF( 818 "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n", 819 static_cast<uint64_t>(results->ptrAuthDiversifier)); 820 } break; 821 #endif 822 823 #else 824 (void)arch; 825 #endif 826 827 default: 828 operand = opcode & 0x3F; 829 switch (opcode & 0xC0) { 830 case DW_CFA_offset: 831 reg = operand; 832 if (reg > kMaxRegisterNumber) { 833 _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 834 ") out of range", 835 reg); 836 return false; 837 } 838 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * 839 cieInfo.dataAlignFactor; 840 results->setRegister(reg, kRegisterInCFA, offset, initialState); 841 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", 842 operand, offset); 843 break; 844 case DW_CFA_advance_loc: 845 codeOffset += operand * cieInfo.codeAlignFactor; 846 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", 847 static_cast<uint64_t>(codeOffset)); 848 break; 849 case DW_CFA_restore: 850 reg = operand; 851 if (reg > kMaxRegisterNumber) { 852 _LIBUNWIND_LOG( 853 "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 854 ") out of range", 855 reg); 856 return false; 857 } 858 results->restoreRegisterToInitialState(reg, initialState); 859 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", 860 static_cast<uint64_t>(operand)); 861 break; 862 default: 863 _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode); 864 return false; 865 } 866 } 867 } 868 } 869 return true; 870 } 871 872 } // namespace libunwind 873 874 #endif // __DWARF_PARSER_HPP__ 875