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