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 returnAddress += R::RETURN_OFFSET; 157 returnAddress &= ~R::RETURN_MASK; 158 newRegisters.setIP(returnAddress); 159 160 // Now replace register set with the working copy. 161 registers = newRegisters; 162 163 return UNW_STEP_SUCCESS; 164 } 165 166 template <typename A, typename R> 167 typename A::pint_t 168 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, 169 const R ®isters, 170 pint_t initialStackValue) { 171 pint_t p = expression; 172 pint_t expressionEnd = expression + 20; // Rough estimate 173 uint64_t length = addressSpace.getULEB128(p, expressionEnd); 174 expressionEnd = p + length; 175 pint_t stack[100]; 176 pint_t *sp = stack; 177 *(++sp) = initialStackValue; 178 179 while (p < expressionEnd) { 180 uint8_t opcode = addressSpace.get8(p++); 181 sint_t svalue; 182 pint_t value; 183 uint32_t reg; 184 switch (opcode) { 185 case DW_OP_addr: 186 // push immediate address sized value 187 value = addressSpace.getP(p); 188 p += sizeof(pint_t); 189 *(++sp) = value; 190 break; 191 192 case DW_OP_deref: 193 // pop stack, dereference, push result 194 value = *sp--; 195 *(++sp) = addressSpace.getP(value); 196 break; 197 198 case DW_OP_const1u: 199 // push immediate 1 byte value 200 value = addressSpace.get8(p); 201 p += 1; 202 *(++sp) = value; 203 break; 204 205 case DW_OP_const1s: 206 // push immediate 1 byte signed value 207 svalue = (int8_t)addressSpace.get8(p); 208 p += 1; 209 *(++sp) = svalue; 210 break; 211 212 case DW_OP_const2u: 213 // push immediate 2 byte value 214 value = addressSpace.get16(p); 215 p += 2; 216 *(++sp) = value; 217 break; 218 219 case DW_OP_const2s: 220 // push immediate 2 byte signed value 221 svalue = (int16_t)addressSpace.get16(p); 222 p += 2; 223 *(++sp) = svalue; 224 break; 225 226 case DW_OP_const4u: 227 // push immediate 4 byte value 228 value = addressSpace.get32(p); 229 p += 4; 230 *(++sp) = value; 231 break; 232 233 case DW_OP_const4s: 234 // push immediate 4 byte signed value 235 svalue = (int32_t)addressSpace.get32(p); 236 p += 4; 237 *(++sp) = svalue; 238 break; 239 240 case DW_OP_const8u: 241 // push immediate 8 byte value 242 value = addressSpace.get64(p); 243 p += 8; 244 *(++sp) = value; 245 break; 246 247 case DW_OP_const8s: 248 // push immediate 8 byte signed value 249 value = (int32_t)addressSpace.get64(p); 250 p += 8; 251 *(++sp) = value; 252 break; 253 254 case DW_OP_constu: 255 // push immediate ULEB128 value 256 value = addressSpace.getULEB128(p, expressionEnd); 257 *(++sp) = value; 258 break; 259 260 case DW_OP_consts: 261 // push immediate SLEB128 value 262 svalue = addressSpace.getSLEB128(p, expressionEnd); 263 *(++sp) = svalue; 264 break; 265 266 case DW_OP_dup: 267 // push top of stack 268 value = *sp; 269 *(++sp) = value; 270 break; 271 272 case DW_OP_drop: 273 // pop 274 --sp; 275 break; 276 277 case DW_OP_over: 278 // dup second 279 value = sp[-1]; 280 *(++sp) = value; 281 break; 282 283 case DW_OP_pick: 284 // pick from 285 reg = addressSpace.get8(p); 286 p += 1; 287 value = sp[-reg]; 288 *(++sp) = value; 289 break; 290 291 case DW_OP_swap: 292 // swap top two 293 value = sp[0]; 294 sp[0] = sp[-1]; 295 sp[-1] = value; 296 break; 297 298 case DW_OP_rot: 299 // rotate top three 300 value = sp[0]; 301 sp[0] = sp[-1]; 302 sp[-1] = sp[-2]; 303 sp[-2] = value; 304 break; 305 306 case DW_OP_xderef: 307 // pop stack, dereference, push result 308 value = *sp--; 309 *sp = *((uint64_t *)value); 310 break; 311 312 case DW_OP_abs: 313 svalue = *sp; 314 if (svalue < 0) 315 *sp = -svalue; 316 break; 317 318 case DW_OP_and: 319 value = *sp--; 320 *sp &= value; 321 break; 322 323 case DW_OP_div: 324 svalue = *sp--; 325 *sp = *sp / svalue; 326 break; 327 328 case DW_OP_minus: 329 svalue = *sp--; 330 *sp = *sp - svalue; 331 break; 332 333 case DW_OP_mod: 334 svalue = *sp--; 335 *sp = *sp % svalue; 336 break; 337 338 case DW_OP_mul: 339 svalue = *sp--; 340 *sp = *sp * svalue; 341 break; 342 343 case DW_OP_neg: 344 *sp = 0 - *sp; 345 break; 346 347 case DW_OP_not: 348 svalue = *sp; 349 *sp = ~svalue; 350 break; 351 352 case DW_OP_or: 353 value = *sp--; 354 *sp |= value; 355 break; 356 357 case DW_OP_plus: 358 value = *sp--; 359 *sp += value; 360 break; 361 362 case DW_OP_plus_uconst: 363 // pop stack, add uelb128 constant, push result 364 *sp += addressSpace.getULEB128(p, expressionEnd); 365 break; 366 367 case DW_OP_shl: 368 value = *sp--; 369 *sp = *sp << value; 370 break; 371 372 case DW_OP_shr: 373 value = *sp--; 374 *sp = *sp >> value; 375 break; 376 377 case DW_OP_shra: 378 value = *sp--; 379 svalue = *sp; 380 *sp = svalue >> value; 381 break; 382 383 case DW_OP_xor: 384 value = *sp--; 385 *sp ^= value; 386 break; 387 388 case DW_OP_skip: 389 svalue = (int16_t)addressSpace.get16(p); 390 p += 2; 391 p += svalue; 392 break; 393 394 case DW_OP_bra: 395 svalue = (int16_t)addressSpace.get16(p); 396 p += 2; 397 if (*sp--) 398 p += svalue; 399 break; 400 401 case DW_OP_eq: 402 value = *sp--; 403 *sp = (*sp == value); 404 break; 405 406 case DW_OP_ge: 407 value = *sp--; 408 *sp = (*sp >= value); 409 break; 410 411 case DW_OP_gt: 412 value = *sp--; 413 *sp = (*sp > value); 414 break; 415 416 case DW_OP_le: 417 value = *sp--; 418 *sp = (*sp <= value); 419 break; 420 421 case DW_OP_lt: 422 value = *sp--; 423 *sp = (*sp < value); 424 break; 425 426 case DW_OP_ne: 427 value = *sp--; 428 *sp = (*sp != value); 429 break; 430 431 case DW_OP_lit0: 432 case DW_OP_lit1: 433 case DW_OP_lit2: 434 case DW_OP_lit3: 435 case DW_OP_lit4: 436 case DW_OP_lit5: 437 case DW_OP_lit6: 438 case DW_OP_lit7: 439 case DW_OP_lit8: 440 case DW_OP_lit9: 441 case DW_OP_lit10: 442 case DW_OP_lit11: 443 case DW_OP_lit12: 444 case DW_OP_lit13: 445 case DW_OP_lit14: 446 case DW_OP_lit15: 447 case DW_OP_lit16: 448 case DW_OP_lit17: 449 case DW_OP_lit18: 450 case DW_OP_lit19: 451 case DW_OP_lit20: 452 case DW_OP_lit21: 453 case DW_OP_lit22: 454 case DW_OP_lit23: 455 case DW_OP_lit24: 456 case DW_OP_lit25: 457 case DW_OP_lit26: 458 case DW_OP_lit27: 459 case DW_OP_lit28: 460 case DW_OP_lit29: 461 case DW_OP_lit30: 462 case DW_OP_lit31: 463 value = opcode - DW_OP_lit0; 464 *(++sp) = value; 465 break; 466 467 case DW_OP_reg0: 468 case DW_OP_reg1: 469 case DW_OP_reg2: 470 case DW_OP_reg3: 471 case DW_OP_reg4: 472 case DW_OP_reg5: 473 case DW_OP_reg6: 474 case DW_OP_reg7: 475 case DW_OP_reg8: 476 case DW_OP_reg9: 477 case DW_OP_reg10: 478 case DW_OP_reg11: 479 case DW_OP_reg12: 480 case DW_OP_reg13: 481 case DW_OP_reg14: 482 case DW_OP_reg15: 483 case DW_OP_reg16: 484 case DW_OP_reg17: 485 case DW_OP_reg18: 486 case DW_OP_reg19: 487 case DW_OP_reg20: 488 case DW_OP_reg21: 489 case DW_OP_reg22: 490 case DW_OP_reg23: 491 case DW_OP_reg24: 492 case DW_OP_reg25: 493 case DW_OP_reg26: 494 case DW_OP_reg27: 495 case DW_OP_reg28: 496 case DW_OP_reg29: 497 case DW_OP_reg30: 498 case DW_OP_reg31: 499 reg = opcode - DW_OP_reg0; 500 *(++sp) = registers.getRegister(reg); 501 break; 502 503 case DW_OP_regx: 504 reg = addressSpace.getULEB128(p, expressionEnd); 505 *(++sp) = registers.getRegister(reg); 506 break; 507 508 case DW_OP_breg0: 509 case DW_OP_breg1: 510 case DW_OP_breg2: 511 case DW_OP_breg3: 512 case DW_OP_breg4: 513 case DW_OP_breg5: 514 case DW_OP_breg6: 515 case DW_OP_breg7: 516 case DW_OP_breg8: 517 case DW_OP_breg9: 518 case DW_OP_breg10: 519 case DW_OP_breg11: 520 case DW_OP_breg12: 521 case DW_OP_breg13: 522 case DW_OP_breg14: 523 case DW_OP_breg15: 524 case DW_OP_breg16: 525 case DW_OP_breg17: 526 case DW_OP_breg18: 527 case DW_OP_breg19: 528 case DW_OP_breg20: 529 case DW_OP_breg21: 530 case DW_OP_breg22: 531 case DW_OP_breg23: 532 case DW_OP_breg24: 533 case DW_OP_breg25: 534 case DW_OP_breg26: 535 case DW_OP_breg27: 536 case DW_OP_breg28: 537 case DW_OP_breg29: 538 case DW_OP_breg30: 539 case DW_OP_breg31: 540 reg = opcode - DW_OP_breg0; 541 svalue = addressSpace.getSLEB128(p, expressionEnd); 542 *(++sp) = registers.getRegister(reg) + svalue; 543 break; 544 545 case DW_OP_bregx: 546 reg = addressSpace.getULEB128(p, expressionEnd); 547 svalue = addressSpace.getSLEB128(p, expressionEnd); 548 *(++sp) = registers.getRegister(reg) + svalue; 549 break; 550 551 case DW_OP_deref_size: 552 // pop stack, dereference, push result 553 value = *sp--; 554 switch (addressSpace.get8(p++)) { 555 case 1: 556 value = addressSpace.get8(value); 557 break; 558 case 2: 559 value = addressSpace.get16(value); 560 break; 561 case 4: 562 value = addressSpace.get32(value); 563 break; 564 case 8: 565 value = addressSpace.get64(value); 566 break; 567 default: 568 assert(0 && "DW_OP_deref_size with bad size"); 569 } 570 *(++sp) = value; 571 break; 572 573 case DW_OP_fbreg: 574 case DW_OP_piece: 575 case DW_OP_xderef_size: 576 case DW_OP_nop: 577 case DW_OP_push_object_addres: 578 case DW_OP_call2: 579 case DW_OP_call4: 580 case DW_OP_call_ref: 581 default: 582 assert(0 && "dwarf opcode not implemented"); 583 } 584 } 585 return *sp; 586 } 587 588 } // namespace _Unwind 589 590 #endif // __DWARF_INSTRUCTIONS_HPP__ 591