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 <cstdint> 17 #include <cstdlib> 18 19 #include "dwarf2.h" 20 #include "AddressSpace.hpp" 21 22 namespace _Unwind { 23 24 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. 25 /// See Dwarf Spec for details: 26 /// http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html 27 /// 28 template <typename A, typename R> class CFI_Parser { 29 public: 30 typedef typename A::pint_t pint_t; 31 32 /// Information encoded in a CIE (Common Information Entry) 33 struct CIE_Info { 34 pint_t cieStart; 35 pint_t cieLength; 36 pint_t cieInstructions; 37 pint_t personality; 38 uint32_t codeAlignFactor; 39 int dataAlignFactor; 40 uint8_t pointerEncoding; 41 uint8_t lsdaEncoding; 42 uint8_t personalityEncoding; 43 uint8_t personalityOffsetInCIE; 44 bool isSignalFrame; 45 bool fdesHaveAugmentationData; 46 }; 47 48 /// Information about an FDE (Frame Description Entry) 49 struct FDE_Info { 50 pint_t fdeStart; 51 pint_t fdeLength; 52 pint_t fdeInstructions; 53 pint_t pcStart; 54 pint_t pcEnd; 55 pint_t lsda; 56 }; 57 58 /// Information about a frame layout and registers saved determined 59 /// by "running" the DWARF FDE "instructions" 60 enum { 61 kMaxRegisterNumber = R::LAST_REGISTER + 1 62 }; 63 enum RegisterSavedWhere { 64 kRegisterUnused, 65 kRegisterInCFA, 66 kRegisterOffsetFromCFA, 67 kRegisterInRegister, 68 kRegisterAtExpression, 69 kRegisterIsExpression, 70 }; 71 struct RegisterLocation { 72 RegisterSavedWhere location; 73 int64_t value; 74 }; 75 struct PrologInfo { 76 uint32_t cfaRegister; 77 int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset 78 int64_t cfaExpression; // CFA = expression 79 uint32_t spExtraArgSize; 80 uint32_t codeOffsetAtStackDecrement; 81 RegisterLocation savedRegisters[kMaxRegisterNumber]; 82 }; 83 84 struct PrologInfoStackEntry { 85 PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i) 86 : next(n), info(i) {} 87 PrologInfoStackEntry *next; 88 PrologInfo info; 89 }; 90 91 static void findPCRange(A &, pint_t, pint_t &, pint_t &); 92 93 static bool decodeFDE(A &, pint_t, FDE_Info *, CIE_Info *, 94 unw_proc_info_t *ctx); 95 static bool parseFDEInstructions(A &, const FDE_Info &, const CIE_Info &, 96 pint_t, PrologInfo *, unw_proc_info_t *ctx); 97 98 static bool parseCIE(A &, pint_t, CIE_Info *); 99 100 private: 101 static bool parseInstructions(A &, pint_t, pint_t, const CIE_Info &, pint_t, 102 PrologInfoStackEntry *&, PrologInfo *, 103 unw_proc_info_t *ctx); 104 }; 105 106 /// 107 /// Parse a FDE and return the last PC it covers. 108 /// 109 template <typename A, typename R> 110 void CFI_Parser<A, R>::findPCRange(A &addressSpace, pint_t fde, pint_t &pcStart, 111 pint_t &pcEnd) { 112 pcStart = 0; 113 pcEnd = 0; 114 pint_t p = fde; 115 uint64_t cfiLength = addressSpace.get32(p); 116 p += 4; 117 if (cfiLength == 0xffffffff) { 118 // 0xffffffff means length is really the next 8 Bytes. 119 cfiLength = addressSpace.get64(p); 120 p += 8; 121 } 122 if (cfiLength == 0) 123 return; 124 uint32_t ciePointer = addressSpace.get32(p); 125 if (ciePointer == 0) 126 return; 127 pint_t nextCFI = p + cfiLength; 128 pint_t cieStart = p - ciePointer; 129 typename CFI_Parser<A, R>::CIE_Info cieInfo; 130 if (!parseCIE(addressSpace, cieStart, &cieInfo)) 131 return; 132 p += 4; 133 // Parse pc begin and range. 134 pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding, NULL); 135 pcEnd = pcStart + addressSpace.getEncodedP( 136 p, nextCFI, cieInfo.pointerEncoding & 0x0F, NULL); 137 } 138 139 /// 140 /// Parse a FDE into a CIE_Info and an FDE_Info 141 /// 142 template <typename A, typename R> 143 bool CFI_Parser<A, R>::decodeFDE(A &addressSpace, pint_t fdeStart, 144 FDE_Info *fdeInfo, CIE_Info *cieInfo, 145 unw_proc_info_t *ctx) { 146 pint_t p = fdeStart; 147 uint64_t cfiLength = addressSpace.get32(p); 148 p += 4; 149 if (cfiLength == 0xffffffff) { 150 // 0xffffffff means length is really the next 8 Bytes. 151 cfiLength = addressSpace.get64(p); 152 p += 8; 153 } 154 if (cfiLength == 0) 155 return false; 156 uint32_t ciePointer = addressSpace.get32(p); 157 if (ciePointer == 0) 158 return false; 159 pint_t nextCFI = p + cfiLength; 160 pint_t cieStart = p - ciePointer; 161 if (!parseCIE(addressSpace, cieStart, cieInfo)) 162 return false; 163 p += 4; 164 // Parse pc begin and range. 165 pint_t pcStart = 166 addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding, ctx); 167 pint_t pcRange = addressSpace.getEncodedP( 168 p, nextCFI, cieInfo->pointerEncoding & 0x0F, ctx); 169 // Parse rest of info. 170 fdeInfo->lsda = 0; 171 // Check for augmentation length 172 if (cieInfo->fdesHaveAugmentationData) { 173 uintptr_t augLen = addressSpace.getULEB128(p, nextCFI); 174 pint_t endOfAug = p + augLen; 175 if (cieInfo->lsdaEncoding != 0) { 176 // Peek at value (without indirection). Zero means no LSDA. 177 pint_t lsdaStart = p; 178 if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F, 179 ctx) != 0) { 180 // Reset pointer and re-parse LSDA address. 181 p = lsdaStart; 182 fdeInfo->lsda = 183 addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding, ctx); 184 } 185 } 186 p = endOfAug; 187 } 188 fdeInfo->fdeStart = fdeStart; 189 fdeInfo->fdeLength = nextCFI - fdeStart; 190 fdeInfo->fdeInstructions = p; 191 fdeInfo->pcStart = pcStart; 192 fdeInfo->pcEnd = pcStart + pcRange; 193 return true; 194 } 195 196 /// Extract info from a CIE 197 template <typename A, typename R> 198 bool CFI_Parser<A, R>::parseCIE(A &addressSpace, pint_t cie, 199 CIE_Info *cieInfo) { 200 cieInfo->pointerEncoding = 0; 201 cieInfo->lsdaEncoding = 0; 202 cieInfo->personalityEncoding = 0; 203 cieInfo->personalityOffsetInCIE = 0; 204 cieInfo->personality = 0; 205 cieInfo->codeAlignFactor = 0; 206 cieInfo->dataAlignFactor = 0; 207 cieInfo->isSignalFrame = false; 208 cieInfo->fdesHaveAugmentationData = false; 209 cieInfo->cieStart = cie; 210 pint_t p = cie; 211 uint64_t cieLength = addressSpace.get32(p); 212 p += 4; 213 pint_t cieContentEnd = p + cieLength; 214 if (cieLength == 0xffffffff) { 215 // 0xffffffff means length is really the next 8 Bytes. 216 cieLength = addressSpace.get64(p); 217 p += 8; 218 cieContentEnd = p + cieLength; 219 } 220 if (cieLength == 0) 221 return true; 222 // CIE ID is always 0 223 if (addressSpace.get32(p) != 0) 224 return false; 225 p += 4; 226 // Version is always 1 or 3 227 uint8_t version = addressSpace.get8(p); 228 if (version != 1 && version != 3) 229 return false; 230 ++p; 231 // Save start of augmentation string and find end. 232 pint_t strStart = p; 233 while (addressSpace.get8(p) != 0) 234 ++p; 235 ++p; 236 // Parse code aligment factor 237 cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd); 238 // Parse data alignment factor 239 cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd); 240 // Parse return address register 241 addressSpace.getULEB128(p, cieContentEnd); 242 // Parse augmentation data based on augmentation string. 243 if (addressSpace.get8(strStart) == 'z') { 244 // parse augmentation data length 245 addressSpace.getULEB128(p, cieContentEnd); 246 for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) { 247 switch (addressSpace.get8(s)) { 248 case 'z': 249 cieInfo->fdesHaveAugmentationData = true; 250 break; 251 case 'P': 252 cieInfo->personalityEncoding = addressSpace.get8(p); 253 ++p; 254 cieInfo->personalityOffsetInCIE = p - cie; 255 cieInfo->personality = addressSpace.getEncodedP( 256 p, cieContentEnd, cieInfo->personalityEncoding, NULL); 257 break; 258 case 'L': 259 cieInfo->lsdaEncoding = addressSpace.get8(p); 260 ++p; 261 break; 262 case 'R': 263 cieInfo->pointerEncoding = addressSpace.get8(p); 264 ++p; 265 break; 266 case 'S': 267 cieInfo->isSignalFrame = true; 268 break; 269 default: 270 // ignore unknown letters 271 break; 272 } 273 } 274 } 275 cieInfo->cieLength = cieContentEnd - cieInfo->cieStart; 276 cieInfo->cieInstructions = p; 277 return true; 278 } 279 280 /// "Run" the dwarf instructions and create the abstact PrologInfo for an FDE. 281 template <typename A, typename R> 282 bool CFI_Parser<A, R>::parseFDEInstructions(A &addressSpace, 283 const FDE_Info &fdeInfo, 284 const CIE_Info &cieInfo, 285 pint_t upToPC, PrologInfo *results, 286 unw_proc_info_t *ctx) { 287 // Clear results. 288 memset(results, 0, sizeof(*results)); 289 PrologInfoStackEntry *rememberStack = NULL; 290 291 // First parse the CIE then FDE instructions. 292 if (!parseInstructions(addressSpace, cieInfo.cieInstructions, 293 cieInfo.cieStart + cieInfo.cieLength, cieInfo, 294 (pint_t)(-1), rememberStack, results, ctx)) 295 return false; 296 return parseInstructions(addressSpace, fdeInfo.fdeInstructions, 297 fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, 298 upToPC - fdeInfo.pcStart, rememberStack, results, 299 ctx); 300 } 301 302 /// "Run" the DWARF instructions. 303 template <typename A, typename R> 304 bool 305 CFI_Parser<A, R>::parseInstructions(A &addressSpace, pint_t instructions, 306 pint_t instructionsEnd, 307 const CIE_Info &cieInfo, pint_t pcoffset, 308 PrologInfoStackEntry *&rememberStack, 309 PrologInfo *results, unw_proc_info_t *ctx) { 310 pint_t p = instructions; 311 uint32_t codeOffset = 0; 312 PrologInfo initialState = *results; 313 314 // See Dwarf Spec, section 6.4.2 for details on unwind opcodes. 315 while (p < instructionsEnd && codeOffset < pcoffset) { 316 uint64_t reg; 317 uint64_t reg2; 318 int64_t offset; 319 uint64_t length; 320 uint8_t opcode = addressSpace.get8(p); 321 uint8_t operand; 322 PrologInfoStackEntry *entry; 323 ++p; 324 switch (opcode) { 325 case DW_CFA_nop: 326 break; 327 case DW_CFA_set_loc: 328 codeOffset = addressSpace.getEncodedP(p, instructionsEnd, 329 cieInfo.pointerEncoding, ctx); 330 break; 331 case DW_CFA_advance_loc1: 332 codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); 333 p += 1; 334 break; 335 case DW_CFA_advance_loc2: 336 codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); 337 p += 2; 338 break; 339 case DW_CFA_advance_loc4: 340 codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); 341 p += 4; 342 break; 343 case DW_CFA_offset_extended: 344 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 345 offset = 346 addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 347 if (reg > kMaxRegisterNumber) 348 return false; 349 results->savedRegisters[reg].location = kRegisterInCFA; 350 results->savedRegisters[reg].value = offset; 351 break; 352 case DW_CFA_restore_extended: 353 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 354 if (reg > kMaxRegisterNumber) 355 return false; 356 results->savedRegisters[reg] = initialState.savedRegisters[reg]; 357 break; 358 case DW_CFA_undefined: 359 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 360 if (reg > kMaxRegisterNumber) 361 return false; 362 results->savedRegisters[reg].location = kRegisterUnused; 363 break; 364 case DW_CFA_same_value: 365 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 366 if (reg > kMaxRegisterNumber) 367 return false; 368 // "same value" means register was stored in frame, but its current 369 // value has not changed, so no need to restore from frame. 370 // We model this as if the register was never saved. 371 results->savedRegisters[reg].location = kRegisterUnused; 372 break; 373 case DW_CFA_register: 374 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 375 reg2 = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 376 if (reg > kMaxRegisterNumber) 377 return false; 378 if (reg2 > kMaxRegisterNumber) 379 return false; 380 results->savedRegisters[reg].location = kRegisterInRegister; 381 results->savedRegisters[reg].value = reg2; 382 break; 383 case DW_CFA_remember_state: 384 // avoid operator new, because that would be an upward dependency 385 entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry)); 386 if (entry == NULL) 387 return false; 388 389 entry->next = rememberStack; 390 entry->info = *results; 391 rememberStack = entry; 392 break; 393 case DW_CFA_restore_state: 394 if (rememberStack == NULL) 395 return false; 396 { 397 PrologInfoStackEntry *top = rememberStack; 398 *results = top->info; 399 rememberStack = top->next; 400 free((char *)top); 401 } 402 break; 403 case DW_CFA_def_cfa: 404 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 405 offset = addressSpace.getULEB128(p, instructionsEnd); 406 if (reg > kMaxRegisterNumber) 407 return false; 408 results->cfaRegister = reg; 409 results->cfaRegisterOffset = offset; 410 break; 411 case DW_CFA_def_cfa_register: 412 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 413 if (reg > kMaxRegisterNumber) 414 return false; 415 results->cfaRegister = reg; 416 break; 417 case DW_CFA_def_cfa_offset: 418 results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd); 419 results->codeOffsetAtStackDecrement = codeOffset; 420 break; 421 case DW_CFA_def_cfa_expression: 422 results->cfaRegister = 0; 423 results->cfaExpression = p; 424 length = addressSpace.getULEB128(p, instructionsEnd); 425 p += length; 426 break; 427 case DW_CFA_expression: 428 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 429 if (reg > kMaxRegisterNumber) 430 return false; 431 results->savedRegisters[reg].location = kRegisterAtExpression; 432 results->savedRegisters[reg].value = p; 433 length = addressSpace.getULEB128(p, instructionsEnd); 434 p += length; 435 break; 436 case DW_CFA_offset_extended_sf: 437 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 438 if (reg > kMaxRegisterNumber) 439 return false; 440 offset = 441 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 442 results->savedRegisters[reg].location = kRegisterInCFA; 443 results->savedRegisters[reg].value = offset; 444 break; 445 case DW_CFA_def_cfa_sf: 446 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 447 offset = 448 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 449 if (reg > kMaxRegisterNumber) 450 return false; 451 results->cfaRegister = reg; 452 results->cfaRegisterOffset = offset; 453 break; 454 case DW_CFA_def_cfa_offset_sf: 455 results->cfaRegisterOffset = 456 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 457 results->codeOffsetAtStackDecrement = codeOffset; 458 break; 459 case DW_CFA_val_offset: 460 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 461 offset = 462 addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 463 results->savedRegisters[reg].location = kRegisterOffsetFromCFA; 464 results->savedRegisters[reg].value = offset; 465 break; 466 case DW_CFA_val_offset_sf: 467 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 468 if (reg > kMaxRegisterNumber) 469 return false; 470 offset = 471 addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 472 results->savedRegisters[reg].location = kRegisterOffsetFromCFA; 473 results->savedRegisters[reg].value = offset; 474 break; 475 case DW_CFA_val_expression: 476 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 477 if (reg > kMaxRegisterNumber) 478 return false; 479 results->savedRegisters[reg].location = kRegisterIsExpression; 480 results->savedRegisters[reg].value = p; 481 length = addressSpace.getULEB128(p, instructionsEnd); 482 p += length; 483 break; 484 case DW_CFA_GNU_args_size: 485 offset = addressSpace.getULEB128(p, instructionsEnd); 486 results->spExtraArgSize = offset; 487 break; 488 case DW_CFA_GNU_negative_offset_extended: 489 reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); 490 if (reg > kMaxRegisterNumber) 491 return false; 492 offset = 493 addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; 494 results->savedRegisters[reg].location = kRegisterInCFA; 495 results->savedRegisters[reg].value = -offset; 496 break; 497 default: 498 operand = opcode & 0x3F; 499 switch (opcode & 0xC0) { 500 case DW_CFA_offset: 501 reg = R::dwarf2regno(operand); 502 if (reg > kMaxRegisterNumber) 503 return false; 504 offset = addressSpace.getULEB128(p, instructionsEnd) * 505 cieInfo.dataAlignFactor; 506 results->savedRegisters[reg].location = kRegisterInCFA; 507 results->savedRegisters[reg].value = offset; 508 break; 509 case DW_CFA_advance_loc: 510 codeOffset += operand * cieInfo.codeAlignFactor; 511 break; 512 case DW_CFA_restore: 513 reg = R::dwarf2regno(operand); 514 if (reg > kMaxRegisterNumber) 515 return false; 516 results->savedRegisters[reg] = initialState.savedRegisters[reg]; 517 break; 518 default: 519 return false; 520 } 521 } 522 } 523 524 return true; 525 } 526 527 } // namespace _Unwind 528 529 #endif // __DWARF_PARSER_HPP__ 530