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