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