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