1 //===-------------------------- DwarfInstructions.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 // Processor specific interpretation of DWARF unwind info. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef __DWARF_INSTRUCTIONS_HPP__ 14 #define __DWARF_INSTRUCTIONS_HPP__ 15 16 #include <cstdint> 17 #include <cstdlib> 18 19 #include "dwarf2.h" 20 #include "AddressSpace.hpp" 21 #include "Registers.hpp" 22 #include "DwarfParser.hpp" 23 24 namespace _Unwind { 25 26 enum step_result { 27 UNW_STEP_SUCCESS, 28 UNW_STEP_END, 29 UNW_STEP_FAILED 30 }; 31 32 /// DwarfInstructions maps abtract dwarf unwind instructions to a particular 33 /// architecture 34 template <typename A, typename R> class DwarfInstructions { 35 public: 36 typedef typename A::pint_t pint_t; 37 typedef typename A::sint_t sint_t; 38 39 static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *); 40 41 private: 42 static pint_t evaluateExpression(pint_t, A &, const R &, pint_t); 43 static pint_t 44 getSavedRegister(A &, const R &, pint_t, 45 const typename CFI_Parser<A, R>::RegisterLocation &); 46 static pint_t 47 computeRegisterLocation(A &, const R &, pint_t, 48 const typename CFI_Parser<A, R>::RegisterLocation &); 49 50 static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; } 51 52 static pint_t getCFA(A &addressSpace, 53 const typename CFI_Parser<A, R>::PrologInfo &prolog, 54 const R ®isters) { 55 if (prolog.cfaRegister != 0) 56 return registers.getRegister(prolog.cfaRegister) + 57 prolog.cfaRegisterOffset; 58 if (prolog.cfaExpression != 0) 59 return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 60 0); 61 assert(0 && "getCFA(): unknown location"); 62 __builtin_unreachable(); 63 } 64 }; 65 66 template <typename A, typename R> 67 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( 68 A &addressSpace, const R ®isters, pint_t cfa, 69 const typename CFI_Parser<A, R>::RegisterLocation &savedReg) { 70 switch (savedReg.location) { 71 case CFI_Parser<A, R>::kRegisterInCFA: 72 return addressSpace.getP(cfa + savedReg.value); 73 74 case CFI_Parser<A, R>::kRegisterAtExpression: 75 return addressSpace.getP( 76 evaluateExpression(savedReg.value, addressSpace, registers, cfa)); 77 78 case CFI_Parser<A, R>::kRegisterIsExpression: 79 return evaluateExpression(savedReg.value, addressSpace, registers, cfa); 80 81 case CFI_Parser<A, R>::kRegisterInRegister: 82 return registers.getRegister(savedReg.value); 83 84 case CFI_Parser<A, R>::kRegisterUnused: 85 case CFI_Parser<A, R>::kRegisterOffsetFromCFA: 86 assert(0 && "unsupported restore location for register"); 87 } 88 __builtin_unreachable(); 89 } 90 91 template <typename A, typename R> 92 typename DwarfInstructions<A, R>::pint_t 93 DwarfInstructions<A, R>::computeRegisterLocation( 94 A &addressSpace, const R ®isters, pint_t cfa, 95 const typename CFI_Parser<A, R>::RegisterLocation &savedReg) { 96 switch (savedReg.location) { 97 case CFI_Parser<A, R>::kRegisterInCFA: 98 return cfa + savedReg.value; 99 100 case CFI_Parser<A, R>::kRegisterAtExpression: 101 return evaluateExpression(savedReg.value, addressSpace, registers, cfa); 102 103 case CFI_Parser<A, R>::kRegisterIsExpression: 104 case CFI_Parser<A, R>::kRegisterUnused: 105 case CFI_Parser<A, R>::kRegisterOffsetFromCFA: 106 case CFI_Parser<A, R>::kRegisterInRegister: 107 assert(0 && "unsupported restore location for float/vector register"); 108 } 109 __builtin_unreachable(); 110 } 111 112 template <typename A, typename R> 113 step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, 114 pint_t fdeStart, 115 R ®isters, 116 unw_proc_info_t *ctx) { 117 typename CFI_Parser<A, R>::FDE_Info fdeInfo; 118 typename CFI_Parser<A, R>::CIE_Info cieInfo; 119 if (!CFI_Parser<A, R>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo, 120 ctx)) 121 return UNW_STEP_FAILED; 122 123 typename CFI_Parser<A, R>::PrologInfo prolog; 124 if (!CFI_Parser<A, R>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, 125 pc, &prolog, ctx)) 126 return UNW_STEP_FAILED; 127 128 // Create working copy of the register set. 129 R newRegisters = registers; 130 131 // Get pointer to CFA by the architecture-specific code. 132 pint_t cfa = getCFA(addressSpace, prolog, registers); 133 134 // Restore registers according to DWARF instructions 135 pint_t returnAddress = 0; 136 for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) { 137 if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused) 138 continue; 139 if (i == (int)cieInfo.returnAddressRegister) 140 returnAddress = getSavedRegister(addressSpace, registers, cfa, 141 prolog.savedRegisters[i]); 142 else if (registers.validRegister(i)) 143 newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa, 144 prolog.savedRegisters[i])); 145 else if (registers.validFloatVectorRegister(i)) 146 newRegisters.copyFloatVectorRegister( 147 i, computeRegisterLocation(addressSpace, registers, cfa, 148 prolog.savedRegisters[i])); 149 else 150 return UNW_STEP_FAILED; 151 } 152 153 // The CFA is defined as the stack pointer at the call site. 154 // Therefore the SP is restored by setting it to the CFA. 155 newRegisters.setSP(cfa); 156 newRegisters.setIP(returnAddress + R::RETURN_OFFSET); 157 returnAddress += R::RETURN_OFFSET; 158 returnAddress &= ~R::RETURN_MASK; 159 newRegisters.setIP(returnAddress); 160 161 // Now replace register set with the working copy. 162 registers = newRegisters; 163 164 return UNW_STEP_SUCCESS; 165 } 166 167 template <typename A, typename R> 168 typename A::pint_t 169 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, 170 const R ®isters, 171 pint_t initialStackValue) { 172 pint_t p = expression; 173 pint_t expressionEnd = expression + 20; // Rough estimate 174 uint64_t length = addressSpace.getULEB128(p, expressionEnd); 175 expressionEnd = p + length; 176 pint_t stack[100]; 177 pint_t *sp = stack; 178 *(++sp) = initialStackValue; 179 180 while (p < expressionEnd) { 181 uint8_t opcode = addressSpace.get8(p++); 182 sint_t svalue; 183 pint_t value; 184 uint32_t reg; 185 switch (opcode) { 186 case DW_OP_addr: 187 // push immediate address sized value 188 value = addressSpace.getP(p); 189 p += sizeof(pint_t); 190 *(++sp) = value; 191 break; 192 193 case DW_OP_deref: 194 // pop stack, dereference, push result 195 value = *sp--; 196 *(++sp) = addressSpace.getP(value); 197 break; 198 199 case DW_OP_const1u: 200 // push immediate 1 byte value 201 value = addressSpace.get8(p); 202 p += 1; 203 *(++sp) = value; 204 break; 205 206 case DW_OP_const1s: 207 // push immediate 1 byte signed value 208 svalue = (int8_t)addressSpace.get8(p); 209 p += 1; 210 *(++sp) = svalue; 211 break; 212 213 case DW_OP_const2u: 214 // push immediate 2 byte value 215 value = addressSpace.get16(p); 216 p += 2; 217 *(++sp) = value; 218 break; 219 220 case DW_OP_const2s: 221 // push immediate 2 byte signed value 222 svalue = (int16_t)addressSpace.get16(p); 223 p += 2; 224 *(++sp) = svalue; 225 break; 226 227 case DW_OP_const4u: 228 // push immediate 4 byte value 229 value = addressSpace.get32(p); 230 p += 4; 231 *(++sp) = value; 232 break; 233 234 case DW_OP_const4s: 235 // push immediate 4 byte signed value 236 svalue = (int32_t)addressSpace.get32(p); 237 p += 4; 238 *(++sp) = svalue; 239 break; 240 241 case DW_OP_const8u: 242 // push immediate 8 byte value 243 value = addressSpace.get64(p); 244 p += 8; 245 *(++sp) = value; 246 break; 247 248 case DW_OP_const8s: 249 // push immediate 8 byte signed value 250 value = (int32_t)addressSpace.get64(p); 251 p += 8; 252 *(++sp) = value; 253 break; 254 255 case DW_OP_constu: 256 // push immediate ULEB128 value 257 value = addressSpace.getULEB128(p, expressionEnd); 258 *(++sp) = value; 259 break; 260 261 case DW_OP_consts: 262 // push immediate SLEB128 value 263 svalue = addressSpace.getSLEB128(p, expressionEnd); 264 *(++sp) = svalue; 265 break; 266 267 case DW_OP_dup: 268 // push top of stack 269 value = *sp; 270 *(++sp) = value; 271 break; 272 273 case DW_OP_drop: 274 // pop 275 --sp; 276 break; 277 278 case DW_OP_over: 279 // dup second 280 value = sp[-1]; 281 *(++sp) = value; 282 break; 283 284 case DW_OP_pick: 285 // pick from 286 reg = addressSpace.get8(p); 287 p += 1; 288 value = sp[-reg]; 289 *(++sp) = value; 290 break; 291 292 case DW_OP_swap: 293 // swap top two 294 value = sp[0]; 295 sp[0] = sp[-1]; 296 sp[-1] = value; 297 break; 298 299 case DW_OP_rot: 300 // rotate top three 301 value = sp[0]; 302 sp[0] = sp[-1]; 303 sp[-1] = sp[-2]; 304 sp[-2] = value; 305 break; 306 307 case DW_OP_xderef: 308 // pop stack, dereference, push result 309 value = *sp--; 310 *sp = *((uint64_t *)value); 311 break; 312 313 case DW_OP_abs: 314 svalue = *sp; 315 if (svalue < 0) 316 *sp = -svalue; 317 break; 318 319 case DW_OP_and: 320 value = *sp--; 321 *sp &= value; 322 break; 323 324 case DW_OP_div: 325 svalue = *sp--; 326 *sp = *sp / svalue; 327 break; 328 329 case DW_OP_minus: 330 svalue = *sp--; 331 *sp = *sp - svalue; 332 break; 333 334 case DW_OP_mod: 335 svalue = *sp--; 336 *sp = *sp % svalue; 337 break; 338 339 case DW_OP_mul: 340 svalue = *sp--; 341 *sp = *sp * svalue; 342 break; 343 344 case DW_OP_neg: 345 *sp = 0 - *sp; 346 break; 347 348 case DW_OP_not: 349 svalue = *sp; 350 *sp = ~svalue; 351 break; 352 353 case DW_OP_or: 354 value = *sp--; 355 *sp |= value; 356 break; 357 358 case DW_OP_plus: 359 value = *sp--; 360 *sp += value; 361 break; 362 363 case DW_OP_plus_uconst: 364 // pop stack, add uelb128 constant, push result 365 *sp += addressSpace.getULEB128(p, expressionEnd); 366 break; 367 368 case DW_OP_shl: 369 value = *sp--; 370 *sp = *sp << value; 371 break; 372 373 case DW_OP_shr: 374 value = *sp--; 375 *sp = *sp >> value; 376 break; 377 378 case DW_OP_shra: 379 value = *sp--; 380 svalue = *sp; 381 *sp = svalue >> value; 382 break; 383 384 case DW_OP_xor: 385 value = *sp--; 386 *sp ^= value; 387 break; 388 389 case DW_OP_skip: 390 svalue = (int16_t)addressSpace.get16(p); 391 p += 2; 392 p += svalue; 393 break; 394 395 case DW_OP_bra: 396 svalue = (int16_t)addressSpace.get16(p); 397 p += 2; 398 if (*sp--) 399 p += svalue; 400 break; 401 402 case DW_OP_eq: 403 value = *sp--; 404 *sp = (*sp == value); 405 break; 406 407 case DW_OP_ge: 408 value = *sp--; 409 *sp = (*sp >= value); 410 break; 411 412 case DW_OP_gt: 413 value = *sp--; 414 *sp = (*sp > value); 415 break; 416 417 case DW_OP_le: 418 value = *sp--; 419 *sp = (*sp <= value); 420 break; 421 422 case DW_OP_lt: 423 value = *sp--; 424 *sp = (*sp < value); 425 break; 426 427 case DW_OP_ne: 428 value = *sp--; 429 *sp = (*sp != value); 430 break; 431 432 case DW_OP_lit0: 433 case DW_OP_lit1: 434 case DW_OP_lit2: 435 case DW_OP_lit3: 436 case DW_OP_lit4: 437 case DW_OP_lit5: 438 case DW_OP_lit6: 439 case DW_OP_lit7: 440 case DW_OP_lit8: 441 case DW_OP_lit9: 442 case DW_OP_lit10: 443 case DW_OP_lit11: 444 case DW_OP_lit12: 445 case DW_OP_lit13: 446 case DW_OP_lit14: 447 case DW_OP_lit15: 448 case DW_OP_lit16: 449 case DW_OP_lit17: 450 case DW_OP_lit18: 451 case DW_OP_lit19: 452 case DW_OP_lit20: 453 case DW_OP_lit21: 454 case DW_OP_lit22: 455 case DW_OP_lit23: 456 case DW_OP_lit24: 457 case DW_OP_lit25: 458 case DW_OP_lit26: 459 case DW_OP_lit27: 460 case DW_OP_lit28: 461 case DW_OP_lit29: 462 case DW_OP_lit30: 463 case DW_OP_lit31: 464 value = opcode - DW_OP_lit0; 465 *(++sp) = value; 466 break; 467 468 case DW_OP_reg0: 469 case DW_OP_reg1: 470 case DW_OP_reg2: 471 case DW_OP_reg3: 472 case DW_OP_reg4: 473 case DW_OP_reg5: 474 case DW_OP_reg6: 475 case DW_OP_reg7: 476 case DW_OP_reg8: 477 case DW_OP_reg9: 478 case DW_OP_reg10: 479 case DW_OP_reg11: 480 case DW_OP_reg12: 481 case DW_OP_reg13: 482 case DW_OP_reg14: 483 case DW_OP_reg15: 484 case DW_OP_reg16: 485 case DW_OP_reg17: 486 case DW_OP_reg18: 487 case DW_OP_reg19: 488 case DW_OP_reg20: 489 case DW_OP_reg21: 490 case DW_OP_reg22: 491 case DW_OP_reg23: 492 case DW_OP_reg24: 493 case DW_OP_reg25: 494 case DW_OP_reg26: 495 case DW_OP_reg27: 496 case DW_OP_reg28: 497 case DW_OP_reg29: 498 case DW_OP_reg30: 499 case DW_OP_reg31: 500 reg = opcode - DW_OP_reg0; 501 *(++sp) = registers.getRegister(reg); 502 break; 503 504 case DW_OP_regx: 505 reg = addressSpace.getULEB128(p, expressionEnd); 506 *(++sp) = registers.getRegister(reg); 507 break; 508 509 case DW_OP_breg0: 510 case DW_OP_breg1: 511 case DW_OP_breg2: 512 case DW_OP_breg3: 513 case DW_OP_breg4: 514 case DW_OP_breg5: 515 case DW_OP_breg6: 516 case DW_OP_breg7: 517 case DW_OP_breg8: 518 case DW_OP_breg9: 519 case DW_OP_breg10: 520 case DW_OP_breg11: 521 case DW_OP_breg12: 522 case DW_OP_breg13: 523 case DW_OP_breg14: 524 case DW_OP_breg15: 525 case DW_OP_breg16: 526 case DW_OP_breg17: 527 case DW_OP_breg18: 528 case DW_OP_breg19: 529 case DW_OP_breg20: 530 case DW_OP_breg21: 531 case DW_OP_breg22: 532 case DW_OP_breg23: 533 case DW_OP_breg24: 534 case DW_OP_breg25: 535 case DW_OP_breg26: 536 case DW_OP_breg27: 537 case DW_OP_breg28: 538 case DW_OP_breg29: 539 case DW_OP_breg30: 540 case DW_OP_breg31: 541 reg = opcode - DW_OP_breg0; 542 svalue = addressSpace.getSLEB128(p, expressionEnd); 543 *(++sp) = registers.getRegister(reg) + svalue; 544 break; 545 546 case DW_OP_bregx: 547 reg = addressSpace.getULEB128(p, expressionEnd); 548 svalue = addressSpace.getSLEB128(p, expressionEnd); 549 *(++sp) = registers.getRegister(reg) + svalue; 550 break; 551 552 case DW_OP_deref_size: 553 // pop stack, dereference, push result 554 value = *sp--; 555 switch (addressSpace.get8(p++)) { 556 case 1: 557 value = addressSpace.get8(value); 558 break; 559 case 2: 560 value = addressSpace.get16(value); 561 break; 562 case 4: 563 value = addressSpace.get32(value); 564 break; 565 case 8: 566 value = addressSpace.get64(value); 567 break; 568 default: 569 assert(0 && "DW_OP_deref_size with bad size"); 570 } 571 *(++sp) = value; 572 break; 573 574 case DW_OP_fbreg: 575 case DW_OP_piece: 576 case DW_OP_xderef_size: 577 case DW_OP_nop: 578 case DW_OP_push_object_addres: 579 case DW_OP_call2: 580 case DW_OP_call4: 581 case DW_OP_call_ref: 582 default: 583 assert(0 && "dwarf opcode not implemented"); 584 } 585 } 586 return *sp; 587 } 588 589 } // namespace _Unwind 590 591 #endif // __DWARF_INSTRUCTIONS_HPP__ 592