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