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