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