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