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