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