1 //===--------------------------- DwarfParser.hpp --------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 // 9 // Parses DWARF CFIs (FDEs and CIEs). 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef __DWARF_PARSER_HPP__ 14 #define __DWARF_PARSER_HPP__ 15 16 #include <inttypes.h> 17 #include <stdint.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 21 #include "libunwind.h" 22 #include "dwarf2.h" 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 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, 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 PrologInfo *results) { 358 // clear results 359 memset(results, '\0', sizeof(PrologInfo)); 360 PrologInfoStackEntry *rememberStack = NULL; 361 362 // parse CIE then FDE instructions 363 return parseInstructions(addressSpace, cieInfo.cieInstructions, 364 cieInfo.cieStart + cieInfo.cieLength, cieInfo, 365 (pint_t)(-1), rememberStack, results) && 366 parseInstructions(addressSpace, fdeInfo.fdeInstructions, 367 fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, 368 upToPC - fdeInfo.pcStart, rememberStack, results); 369 } 370 371 /// "run" the DWARF instructions 372 template <typename A> 373 bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, 374 pint_t instructionsEnd, 375 const CIE_Info &cieInfo, pint_t pcoffset, 376 PrologInfoStackEntry *&rememberStack, 377 PrologInfo *results) { 378 pint_t p = instructions; 379 pint_t codeOffset = 0; 380 PrologInfo initialState = *results; 381 382 _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", 383 static_cast<uint64_t>(instructionsEnd)); 384 385 // see DWARF Spec, section 6.4.2 for details on unwind opcodes 386 while ((p < instructionsEnd) && (codeOffset < pcoffset)) { 387 uint64_t reg; 388 uint64_t reg2; 389 int64_t offset; 390 uint64_t length; 391 uint8_t opcode = addressSpace.get8(p); 392 uint8_t operand; 393 #if !defined(_LIBUNWIND_NO_HEAP) 394 PrologInfoStackEntry *entry; 395 #endif 396 ++p; 397 switch (opcode) { 398 case DW_CFA_nop: 399 _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); 400 break; 401 case DW_CFA_set_loc: 402 codeOffset = 403 addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); 404 _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); 405 break; 406 case DW_CFA_advance_loc1: 407 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); 408 p += 1; 409 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", 410 static_cast<uint64_t>(codeOffset)); 411 break; 412 case DW_CFA_advance_loc2: 413 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); 414 p += 2; 415 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", 416 static_cast<uint64_t>(codeOffset)); 417 break; 418 case DW_CFA_advance_loc4: 419 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); 420 p += 4; 421 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", 422 static_cast<uint64_t>(codeOffset)); 423 break; 424 case DW_CFA_offset_extended: 425 reg = addressSpace.getULEB128(p, instructionsEnd); 426 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) 427 * cieInfo.dataAlignFactor; 428 if (reg > kMaxRegisterNumber) { 429 _LIBUNWIND_LOG0( 430 "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); 431 return false; 432 } 433 results->savedRegisters[reg].location = kRegisterInCFA; 434 results->savedRegisters[reg].value = offset; 435 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " 436 "offset=%" PRId64 ")\n", 437 reg, offset); 438 break; 439 case DW_CFA_restore_extended: 440 reg = addressSpace.getULEB128(p, instructionsEnd); 441 if (reg > kMaxRegisterNumber) { 442 _LIBUNWIND_LOG0( 443 "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); 444 return false; 445 } 446 results->savedRegisters[reg] = initialState.savedRegisters[reg]; 447 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); 448 break; 449 case DW_CFA_undefined: 450 reg = addressSpace.getULEB128(p, instructionsEnd); 451 if (reg > kMaxRegisterNumber) { 452 _LIBUNWIND_LOG0( 453 "malformed DW_CFA_undefined DWARF unwind, reg too big"); 454 return false; 455 } 456 results->savedRegisters[reg].location = kRegisterUnused; 457 _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); 458 break; 459 case DW_CFA_same_value: 460 reg = addressSpace.getULEB128(p, instructionsEnd); 461 if (reg > kMaxRegisterNumber) { 462 _LIBUNWIND_LOG0( 463 "malformed DW_CFA_same_value DWARF unwind, reg too big"); 464 return false; 465 } 466 // <rdar://problem/8456377> DW_CFA_same_value unsupported 467 // "same value" means register was stored in frame, but its current 468 // value has not changed, so no need to restore from frame. 469 // We model this as if the register was never saved. 470 results->savedRegisters[reg].location = kRegisterUnused; 471 // set flag to disable conversion to compact unwind 472 results->sameValueUsed = true; 473 _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); 474 break; 475 case DW_CFA_register: 476 reg = addressSpace.getULEB128(p, instructionsEnd); 477 reg2 = addressSpace.getULEB128(p, instructionsEnd); 478 if (reg > kMaxRegisterNumber) { 479 _LIBUNWIND_LOG0( 480 "malformed DW_CFA_register DWARF unwind, reg too big"); 481 return false; 482 } 483 if (reg2 > kMaxRegisterNumber) { 484 _LIBUNWIND_LOG0( 485 "malformed DW_CFA_register DWARF unwind, reg2 too big"); 486 return false; 487 } 488 results->savedRegisters[reg].location = kRegisterInRegister; 489 results->savedRegisters[reg].value = (int64_t)reg2; 490 // set flag to disable conversion to compact unwind 491 results->registersInOtherRegisters = true; 492 _LIBUNWIND_TRACE_DWARF( 493 "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); 494 break; 495 #if !defined(_LIBUNWIND_NO_HEAP) 496 case DW_CFA_remember_state: 497 // avoid operator new, because that would be an upward dependency 498 entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry)); 499 if (entry != NULL) { 500 entry->next = rememberStack; 501 entry->info = *results; 502 rememberStack = entry; 503 } else { 504 return false; 505 } 506 _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); 507 break; 508 case DW_CFA_restore_state: 509 if (rememberStack != NULL) { 510 PrologInfoStackEntry *top = rememberStack; 511 *results = top->info; 512 rememberStack = top->next; 513 free((char *)top); 514 } else { 515 return false; 516 } 517 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n"); 518 break; 519 #endif 520 case DW_CFA_def_cfa: 521 reg = addressSpace.getULEB128(p, instructionsEnd); 522 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); 523 if (reg > kMaxRegisterNumber) { 524 _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); 525 return false; 526 } 527 results->cfaRegister = (uint32_t)reg; 528 results->cfaRegisterOffset = (int32_t)offset; 529 _LIBUNWIND_TRACE_DWARF( 530 "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset); 531 break; 532 case DW_CFA_def_cfa_register: 533 reg = addressSpace.getULEB128(p, instructionsEnd); 534 if (reg > kMaxRegisterNumber) { 535 _LIBUNWIND_LOG0( 536 "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); 537 return false; 538 } 539 results->cfaRegister = (uint32_t)reg; 540 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); 541 break; 542 case DW_CFA_def_cfa_offset: 543 results->cfaRegisterOffset = (int32_t) 544 addressSpace.getULEB128(p, instructionsEnd); 545 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; 546 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n", 547 results->cfaRegisterOffset); 548 break; 549 case DW_CFA_def_cfa_expression: 550 results->cfaRegister = 0; 551 results->cfaExpression = (int64_t)p; 552 length = addressSpace.getULEB128(p, instructionsEnd); 553 assert(length < static_cast<pint_t>(~0) && "pointer overflow"); 554 p += static_cast<pint_t>(length); 555 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64 556 ", length=%" PRIu64 ")\n", 557 results->cfaExpression, length); 558 break; 559 case DW_CFA_expression: 560 reg = addressSpace.getULEB128(p, instructionsEnd); 561 if (reg > kMaxRegisterNumber) { 562 _LIBUNWIND_LOG0( 563 "malformed DW_CFA_expression DWARF unwind, reg too big"); 564 return false; 565 } 566 results->savedRegisters[reg].location = kRegisterAtExpression; 567 results->savedRegisters[reg].value = (int64_t)p; 568 length = addressSpace.getULEB128(p, instructionsEnd); 569 assert(length < static_cast<pint_t>(~0) && "pointer overflow"); 570 p += static_cast<pint_t>(length); 571 _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " 572 "expression=0x%" PRIx64 ", " 573 "length=%" PRIu64 ")\n", 574 reg, results->savedRegisters[reg].value, length); 575 break; 576 case DW_CFA_offset_extended_sf: 577 reg = addressSpace.getULEB128(p, instructionsEnd); 578 if (reg > kMaxRegisterNumber) { 579 _LIBUNWIND_LOG0( 580 "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); 581 return false; 582 } 583 offset = 584 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 585 results->savedRegisters[reg].location = kRegisterInCFA; 586 results->savedRegisters[reg].value = offset; 587 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " 588 "offset=%" PRId64 ")\n", 589 reg, offset); 590 break; 591 case DW_CFA_def_cfa_sf: 592 reg = addressSpace.getULEB128(p, instructionsEnd); 593 offset = 594 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 595 if (reg > kMaxRegisterNumber) { 596 _LIBUNWIND_LOG0( 597 "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); 598 return false; 599 } 600 results->cfaRegister = (uint32_t)reg; 601 results->cfaRegisterOffset = (int32_t)offset; 602 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", " 603 "offset=%" PRId64 ")\n", 604 reg, offset); 605 break; 606 case DW_CFA_def_cfa_offset_sf: 607 results->cfaRegisterOffset = (int32_t) 608 (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor); 609 results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; 610 _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n", 611 results->cfaRegisterOffset); 612 break; 613 case DW_CFA_val_offset: 614 reg = addressSpace.getULEB128(p, instructionsEnd); 615 if (reg > kMaxRegisterNumber) { 616 _LIBUNWIND_LOG( 617 "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 618 ") out of range\n", 619 reg); 620 return false; 621 } 622 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) 623 * cieInfo.dataAlignFactor; 624 results->savedRegisters[reg].location = kRegisterOffsetFromCFA; 625 results->savedRegisters[reg].value = offset; 626 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " 627 "offset=%" PRId64 "\n", 628 reg, offset); 629 break; 630 case DW_CFA_val_offset_sf: 631 reg = addressSpace.getULEB128(p, instructionsEnd); 632 if (reg > kMaxRegisterNumber) { 633 _LIBUNWIND_LOG0( 634 "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); 635 return false; 636 } 637 offset = 638 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 639 results->savedRegisters[reg].location = kRegisterOffsetFromCFA; 640 results->savedRegisters[reg].value = offset; 641 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " 642 "offset=%" PRId64 "\n", 643 reg, offset); 644 break; 645 case DW_CFA_val_expression: 646 reg = addressSpace.getULEB128(p, instructionsEnd); 647 if (reg > kMaxRegisterNumber) { 648 _LIBUNWIND_LOG0( 649 "malformed DW_CFA_val_expression DWARF unwind, reg too big"); 650 return false; 651 } 652 results->savedRegisters[reg].location = kRegisterIsExpression; 653 results->savedRegisters[reg].value = (int64_t)p; 654 length = addressSpace.getULEB128(p, instructionsEnd); 655 assert(length < static_cast<pint_t>(~0) && "pointer overflow"); 656 p += static_cast<pint_t>(length); 657 _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " 658 "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", 659 reg, results->savedRegisters[reg].value, length); 660 break; 661 case DW_CFA_GNU_args_size: 662 length = addressSpace.getULEB128(p, instructionsEnd); 663 results->spExtraArgSize = (uint32_t)length; 664 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); 665 break; 666 case DW_CFA_GNU_negative_offset_extended: 667 reg = addressSpace.getULEB128(p, instructionsEnd); 668 if (reg > kMaxRegisterNumber) { 669 _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " 670 "unwind, reg too big"); 671 return false; 672 } 673 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) 674 * cieInfo.dataAlignFactor; 675 results->savedRegisters[reg].location = kRegisterInCFA; 676 results->savedRegisters[reg].value = -offset; 677 _LIBUNWIND_TRACE_DWARF( 678 "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); 679 break; 680 681 #if defined(_LIBUNWIND_TARGET_AARCH64) 682 case DW_CFA_AARCH64_negate_ra_state: 683 results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1; 684 _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); 685 break; 686 #endif 687 688 #if defined(_LIBUNWIND_TARGET_SPARC) 689 case DW_CFA_GNU_window_save: 690 _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); 691 for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { 692 results->savedRegisters[reg].location = kRegisterInRegister; 693 results->savedRegisters[reg].value = 694 (reg - UNW_SPARC_O0) + UNW_SPARC_I0; 695 } 696 697 for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { 698 results->savedRegisters[reg].location = kRegisterInCFA; 699 results->savedRegisters[reg].value = (reg - UNW_SPARC_L0) * 4; 700 } 701 break; 702 #endif 703 704 default: 705 operand = opcode & 0x3F; 706 switch (opcode & 0xC0) { 707 case DW_CFA_offset: 708 reg = operand; 709 if (reg > kMaxRegisterNumber) { 710 _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 711 ") out of range", 712 reg); 713 return false; 714 } 715 offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) 716 * cieInfo.dataAlignFactor; 717 results->savedRegisters[reg].location = kRegisterInCFA; 718 results->savedRegisters[reg].value = offset; 719 _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", 720 operand, offset); 721 break; 722 case DW_CFA_advance_loc: 723 codeOffset += operand * cieInfo.codeAlignFactor; 724 _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", 725 static_cast<uint64_t>(codeOffset)); 726 break; 727 case DW_CFA_restore: 728 reg = operand; 729 if (reg > kMaxRegisterNumber) { 730 _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 731 ") out of range", 732 reg); 733 return false; 734 } 735 results->savedRegisters[reg] = initialState.savedRegisters[reg]; 736 _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", 737 static_cast<uint64_t>(operand)); 738 break; 739 default: 740 _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode); 741 return false; 742 } 743 } 744 } 745 746 return true; 747 } 748 749 } // namespace libunwind 750 751 #endif // __DWARF_PARSER_HPP__ 752