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