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