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