1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 2 * 3 * Copyright (c) 2008 Apple Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25// 26// processor specific parsing of dwarf unwind instructions 27// 28 29#ifndef __DWARF_INSTRUCTIONS_HPP__ 30#define __DWARF_INSTRUCTIONS_HPP__ 31 32#include <stdint.h> 33#include <stdio.h> 34#include <stdlib.h> 35 36#include <algorithm> 37#include <vector> 38 39#include <libunwind.h> 40#include <mach-o/compact_unwind_encoding.h> 41 42#include "dwarf2.h" 43#include "AddressSpace.hpp" 44#include "Registers.hpp" 45#include "DwarfParser.hpp" 46#include "InternalMacros.h" 47//#include "CompactUnwinder.hpp" 48 49#define EXTRACT_BITS(value, mask) \ 50 ( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) ) 51 52#define CFI_INVALID_ADDRESS ((pint_t)(-1)) 53 54namespace libunwind { 55 56/// 57/// Used by linker when parsing __eh_frame section 58/// 59template <typename A> 60struct CFI_Reference { 61 typedef typename A::pint_t pint_t; 62 uint8_t encodingOfTargetAddress; 63 uint32_t offsetInCFI; 64 pint_t targetAddress; 65}; 66template <typename A> 67struct CFI_Atom_Info { 68 typedef typename A::pint_t pint_t; 69 pint_t address; 70 uint32_t size; 71 bool isCIE; 72 union { 73 struct { 74 CFI_Reference<A> function; 75 CFI_Reference<A> cie; 76 CFI_Reference<A> lsda; 77 uint32_t compactUnwindInfo; 78 } fdeInfo; 79 struct { 80 CFI_Reference<A> personality; 81 } cieInfo; 82 } u; 83}; 84 85typedef void (*WarnFunc)(void* ref, uint64_t funcAddr, const char* msg); 86 87/// 88/// DwarfInstructions maps abtract dwarf unwind instructions to a particular architecture 89/// 90template <typename A, typename R> 91class DwarfInstructions 92{ 93public: 94 typedef typename A::pint_t pint_t; 95 typedef typename A::sint_t sint_t; 96 97 static const char* parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 98 CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn); 99 100 101 static compact_unwind_encoding_t createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 102 pint_t* lsda, pint_t* personality, 103 char warningBuffer[1024]); 104 105 static int stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers); 106 107private: 108 109 enum { 110 DW_X86_64_RET_ADDR = 16 111 }; 112 113 enum { 114 DW_X86_RET_ADDR = 8 115 }; 116 117 static pint_t evaluateExpression(pint_t expression, A& addressSpace, const R& registers, pint_t initialStackValue); 118 static pint_t getSavedRegister(A& addressSpace, const R& registers, pint_t cfa, 119 const typename CFI_Parser<A>::RegisterLocation& savedReg); 120 static double getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa, 121 const typename CFI_Parser<A>::RegisterLocation& savedReg); 122 static v128 getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa, 123 const typename CFI_Parser<A>::RegisterLocation& savedReg); 124 125 // x86 specific variants 126 static int lastRestoreReg(const Registers_x86&); 127 static bool isReturnAddressRegister(int regNum, const Registers_x86&); 128 static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86&); 129 130 static uint32_t getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure); 131 static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86&); 132 static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, 133 const Registers_x86&, const typename CFI_Parser<A>::PrologInfo& prolog, 134 char warningBuffer[1024]); 135 136 // x86_64 specific variants 137 static int lastRestoreReg(const Registers_x86_64&); 138 static bool isReturnAddressRegister(int regNum, const Registers_x86_64&); 139 static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86_64&); 140 141 static uint32_t getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure); 142 static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86_64&); 143 static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, 144 const Registers_x86_64&, const typename CFI_Parser<A>::PrologInfo& prolog, 145 char warningBuffer[1024]); 146 147 // ppc specific variants 148 static int lastRestoreReg(const Registers_ppc&); 149 static bool isReturnAddressRegister(int regNum, const Registers_ppc&); 150 static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_ppc&); 151 static compact_unwind_encoding_t encodeToUseDwarf(const Registers_ppc&); 152 static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, 153 const Registers_ppc&, const typename CFI_Parser<A>::PrologInfo& prolog, 154 char warningBuffer[1024]); 155}; 156 157 158 159 160template <typename A, typename R> 161const char* DwarfInstructions<A,R>::parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 162 CFI_Atom_Info<A>* infos, uint32_t infosCount, void* ref, WarnFunc warn) 163{ 164 typename CFI_Parser<A>::CIE_Info cieInfo; 165 CFI_Atom_Info<A>* entry = infos; 166 CFI_Atom_Info<A>* end = &infos[infosCount]; 167 const pint_t ehSectionEnd = ehSectionStart + sectionLength; 168 for (pint_t p=ehSectionStart; p < ehSectionEnd; ) { 169 pint_t currentCFI = p; 170 uint64_t cfiLength = addressSpace.get32(p); 171 p += 4; 172 if ( cfiLength == 0xffffffff ) { 173 // 0xffffffff means length is really next 8 bytes 174 cfiLength = addressSpace.get64(p); 175 p += 8; 176 } 177 if ( cfiLength == 0 ) 178 return NULL; // end marker 179 if ( entry >= end ) 180 return "too little space allocated for parseCFIs"; 181 pint_t nextCFI = p + cfiLength; 182 uint32_t id = addressSpace.get32(p); 183 if ( id == 0 ) { 184 // is CIE 185 const char* err = CFI_Parser<A>::parseCIE(addressSpace, currentCFI, &cieInfo); 186 if ( err != NULL ) 187 return err; 188 entry->address = currentCFI; 189 entry->size = nextCFI - currentCFI; 190 entry->isCIE = true; 191 entry->u.cieInfo.personality.targetAddress = cieInfo.personality; 192 entry->u.cieInfo.personality.offsetInCFI = cieInfo.personalityOffsetInCIE; 193 entry->u.cieInfo.personality.encodingOfTargetAddress = cieInfo.personalityEncoding; 194 ++entry; 195 } 196 else { 197 // is FDE 198 entry->address = currentCFI; 199 entry->size = nextCFI - currentCFI; 200 entry->isCIE = false; 201 entry->u.fdeInfo.function.targetAddress = CFI_INVALID_ADDRESS; 202 entry->u.fdeInfo.cie.targetAddress = CFI_INVALID_ADDRESS; 203 entry->u.fdeInfo.lsda.targetAddress = CFI_INVALID_ADDRESS; 204 uint32_t ciePointer = addressSpace.get32(p); 205 pint_t cieStart = p-ciePointer; 206 // validate pointer to CIE is within section 207 if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) ) 208 return "FDE points to CIE outside __eh_frame section"; 209 // optimize usual case where cie is same for all FDEs 210 if ( cieStart != cieInfo.cieStart ) { 211 const char* err = CFI_Parser<A>::parseCIE(addressSpace, cieStart, &cieInfo); 212 if ( err != NULL ) 213 return err; 214 } 215 entry->u.fdeInfo.cie.targetAddress = cieStart; 216 entry->u.fdeInfo.cie.offsetInCFI = p-currentCFI; 217 entry->u.fdeInfo.cie.encodingOfTargetAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel; 218 p += 4; 219 // parse pc begin and range 220 pint_t offsetOfFunctionAddress = p-currentCFI; 221 pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding); 222 pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F); 223 //fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange)); 224 // test if pc is within the function this FDE covers 225 entry->u.fdeInfo.function.targetAddress = pcStart; 226 entry->u.fdeInfo.function.offsetInCFI = offsetOfFunctionAddress; 227 entry->u.fdeInfo.function.encodingOfTargetAddress = cieInfo.pointerEncoding; 228 // check for augmentation length 229 if ( cieInfo.fdesHaveAugmentationData ) { 230 uintptr_t augLen = addressSpace.getULEB128(p, nextCFI); 231 pint_t endOfAug = p + augLen; 232 if ( cieInfo.lsdaEncoding != 0 ) { 233 // peek at value (without indirection). Zero means no lsda 234 pint_t lsdaStart = p; 235 if ( addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding & 0x0F) != 0 ) { 236 // reset pointer and re-parse lsda address 237 p = lsdaStart; 238 pint_t offsetOfLSDAAddress = p-currentCFI; 239 entry->u.fdeInfo.lsda.targetAddress = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding); 240 entry->u.fdeInfo.lsda.offsetInCFI = offsetOfLSDAAddress; 241 entry->u.fdeInfo.lsda.encodingOfTargetAddress = cieInfo.lsdaEncoding; 242 } 243 } 244 p = endOfAug; 245 } 246 // compute compact unwind encoding 247 typename CFI_Parser<A>::FDE_Info fdeInfo; 248 fdeInfo.fdeStart = currentCFI; 249 fdeInfo.fdeLength = nextCFI - currentCFI; 250 fdeInfo.fdeInstructions = p; 251 fdeInfo.pcStart = pcStart; 252 fdeInfo.pcEnd = pcStart + pcRange; 253 fdeInfo.lsda = entry->u.fdeInfo.lsda.targetAddress; 254 typename CFI_Parser<A>::PrologInfo prolog; 255 R dummy; // for proper selection of architecture specific functions 256 if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) { 257 char warningBuffer[1024]; 258 entry->u.fdeInfo.compactUnwindInfo = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer); 259 if ( fdeInfo.lsda != CFI_INVALID_ADDRESS ) 260 entry->u.fdeInfo.compactUnwindInfo |= UNWIND_HAS_LSDA; 261 if ( warningBuffer[0] != '\0' ) 262 warn(ref, fdeInfo.pcStart, warningBuffer); 263 } 264 else { 265 warn(ref, CFI_INVALID_ADDRESS, "dwarf unwind instructions could not be parsed"); 266 entry->u.fdeInfo.compactUnwindInfo = encodeToUseDwarf(dummy); 267 } 268 ++entry; 269 } 270 p = nextCFI; 271 } 272 if ( entry != end ) 273 return "wrong entry count for parseCFIs"; 274 return NULL; // success 275} 276 277 278 279 280template <typename A, typename R> 281compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 282 pint_t* lsda, pint_t* personality, 283 char warningBuffer[1024]) 284{ 285 typename CFI_Parser<A>::FDE_Info fdeInfo; 286 typename CFI_Parser<A>::CIE_Info cieInfo; 287 R dummy; // for proper selection of architecture specific functions 288 if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) { 289 typename CFI_Parser<A>::PrologInfo prolog; 290 if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) { 291 *lsda = fdeInfo.lsda; 292 *personality = cieInfo.personality; 293 compact_unwind_encoding_t encoding; 294 encoding = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer); 295 if ( fdeInfo.lsda != 0 ) 296 encoding |= UNWIND_HAS_LSDA; 297 return encoding; 298 } 299 else { 300 strcpy(warningBuffer, "dwarf unwind instructions could not be parsed"); 301 return encodeToUseDwarf(dummy); 302 } 303 } 304 else { 305 strcpy(warningBuffer, "dwarf FDE could not be parsed"); 306 return encodeToUseDwarf(dummy); 307 } 308} 309 310 311template <typename A, typename R> 312typename A::pint_t DwarfInstructions<A,R>::getSavedRegister(A& addressSpace, const R& registers, pint_t cfa, 313 const typename CFI_Parser<A>::RegisterLocation& savedReg) 314{ 315 switch ( savedReg.location ) { 316 case CFI_Parser<A>::kRegisterInCFA: 317 return addressSpace.getP(cfa + savedReg.value); 318 319 case CFI_Parser<A>::kRegisterAtExpression: 320 return addressSpace.getP(evaluateExpression(savedReg.value, addressSpace, registers, cfa)); 321 322 case CFI_Parser<A>::kRegisterIsExpression: 323 return evaluateExpression(savedReg.value, addressSpace, registers, cfa); 324 325 case CFI_Parser<A>::kRegisterInRegister: 326 return registers.getRegister(savedReg.value); 327 328 case CFI_Parser<A>::kRegisterUnused: 329 case CFI_Parser<A>::kRegisterOffsetFromCFA: 330 // FIX ME 331 break; 332 } 333 ABORT("unsupported restore location for register"); 334} 335 336template <typename A, typename R> 337double DwarfInstructions<A,R>::getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa, 338 const typename CFI_Parser<A>::RegisterLocation& savedReg) 339{ 340 switch ( savedReg.location ) { 341 case CFI_Parser<A>::kRegisterInCFA: 342 return addressSpace.getDouble(cfa + savedReg.value); 343 344 case CFI_Parser<A>::kRegisterAtExpression: 345 return addressSpace.getDouble(evaluateExpression(savedReg.value, addressSpace, registers, cfa)); 346 347 case CFI_Parser<A>::kRegisterIsExpression: 348 case CFI_Parser<A>::kRegisterUnused: 349 case CFI_Parser<A>::kRegisterOffsetFromCFA: 350 case CFI_Parser<A>::kRegisterInRegister: 351 // FIX ME 352 break; 353 } 354 ABORT("unsupported restore location for float register"); 355} 356 357template <typename A, typename R> 358v128 DwarfInstructions<A,R>::getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa, 359 const typename CFI_Parser<A>::RegisterLocation& savedReg) 360{ 361 switch ( savedReg.location ) { 362 case CFI_Parser<A>::kRegisterInCFA: 363 return addressSpace.getVector(cfa + savedReg.value); 364 365 case CFI_Parser<A>::kRegisterAtExpression: 366 return addressSpace.getVector(evaluateExpression(savedReg.value, addressSpace, registers, cfa)); 367 368 case CFI_Parser<A>::kRegisterIsExpression: 369 case CFI_Parser<A>::kRegisterUnused: 370 case CFI_Parser<A>::kRegisterOffsetFromCFA: 371 case CFI_Parser<A>::kRegisterInRegister: 372 // FIX ME 373 break; 374 } 375 ABORT("unsupported restore location for vector register"); 376} 377 378 379template <typename A, typename R> 380int DwarfInstructions<A,R>::stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers) 381{ 382 //fprintf(stderr, "stepWithDwarf(pc=0x%0llX, fdeStart=0x%0llX)\n", (uint64_t)pc, (uint64_t)fdeStart); 383 typename CFI_Parser<A>::FDE_Info fdeInfo; 384 typename CFI_Parser<A>::CIE_Info cieInfo; 385 if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) { 386 typename CFI_Parser<A>::PrologInfo prolog; 387 if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &prolog) ) { 388 R newRegisters = registers; 389 390 // get pointer to cfa (architecture specific) 391 pint_t cfa = getCFA(addressSpace, prolog, registers); 392 393 // restore registers that dwarf says were saved 394 pint_t returnAddress = 0; 395 for (int i=0; i <= lastRestoreReg(newRegisters); ++i) { 396 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) { 397 if ( registers.validFloatRegister(i) ) 398 newRegisters.setFloatRegister(i, getSavedFloatRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); 399 else if ( registers.validVectorRegister(i) ) 400 newRegisters.setVectorRegister(i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); 401 else if ( isReturnAddressRegister(i, registers) ) 402 returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]); 403 else if ( registers.validRegister(i) ) 404 newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); 405 else 406 return UNW_EBADREG; 407 } 408 } 409 410 // by definition the CFA is the stack pointer at the call site, so restoring SP means setting it to CFA 411 newRegisters.setSP(cfa); 412 413 // return address is address after call site instruction, so setting IP to that does a return 414 newRegisters.setIP(returnAddress); 415 416 // do the actual step by replacing the register set with the new ones 417 registers = newRegisters; 418 419 return UNW_STEP_SUCCESS; 420 } 421 } 422 return UNW_EBADFRAME; 423} 424 425 426 427template <typename A, typename R> 428typename A::pint_t DwarfInstructions<A,R>::evaluateExpression(pint_t expression, A& addressSpace, 429 const R& registers, pint_t initialStackValue) 430{ 431 const bool log = false; 432 pint_t p = expression; 433 pint_t expressionEnd = expression+20; // just need something until length is read 434 uint64_t length = addressSpace.getULEB128(p, expressionEnd); 435 expressionEnd = p + length; 436 if (log) fprintf(stderr, "evaluateExpression(): length=%llu\n", length); 437 pint_t stack[100]; 438 pint_t* sp = stack; 439 *(++sp) = initialStackValue; 440 441 while ( p < expressionEnd ) { 442 if (log) { 443 for(pint_t* t = sp; t > stack; --t) { 444 fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t)); 445 } 446 } 447 uint8_t opcode = addressSpace.get8(p++); 448 sint_t svalue; 449 pint_t value; 450 uint32_t reg; 451 switch (opcode) { 452 case DW_OP_addr: 453 // push immediate address sized value 454 value = addressSpace.getP(p); 455 p += sizeof(pint_t); 456 *(++sp) = value; 457 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); 458 break; 459 460 case DW_OP_deref: 461 // pop stack, dereference, push result 462 value = *sp--; 463 *(++sp) = addressSpace.getP(value); 464 if (log) fprintf(stderr, "dereference 0x%llX\n", (uint64_t)value); 465 break; 466 467 case DW_OP_const1u: 468 // push immediate 1 byte value 469 value = addressSpace.get8(p); 470 p += 1; 471 *(++sp) = value; 472 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); 473 break; 474 475 case DW_OP_const1s: 476 // push immediate 1 byte signed value 477 svalue = (int8_t)addressSpace.get8(p); 478 p += 1; 479 *(++sp) = svalue; 480 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); 481 break; 482 483 case DW_OP_const2u: 484 // push immediate 2 byte value 485 value = addressSpace.get16(p); 486 p += 2; 487 *(++sp) = value; 488 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); 489 break; 490 491 case DW_OP_const2s: 492 // push immediate 2 byte signed value 493 svalue = (int16_t)addressSpace.get16(p); 494 p += 2; 495 *(++sp) = svalue; 496 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); 497 break; 498 499 case DW_OP_const4u: 500 // push immediate 4 byte value 501 value = addressSpace.get32(p); 502 p += 4; 503 *(++sp) = value; 504 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); 505 break; 506 507 case DW_OP_const4s: 508 // push immediate 4 byte signed value 509 svalue = (int32_t)addressSpace.get32(p); 510 p += 4; 511 *(++sp) = svalue; 512 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); 513 break; 514 515 case DW_OP_const8u: 516 // push immediate 8 byte value 517 value = addressSpace.get64(p); 518 p += 8; 519 *(++sp) = value; 520 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); 521 break; 522 523 case DW_OP_const8s: 524 // push immediate 8 byte signed value 525 value = (int32_t)addressSpace.get64(p); 526 p += 8; 527 *(++sp) = value; 528 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); 529 break; 530 531 case DW_OP_constu: 532 // push immediate ULEB128 value 533 value = addressSpace.getULEB128(p, expressionEnd); 534 *(++sp) = value; 535 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value); 536 break; 537 538 case DW_OP_consts: 539 // push immediate SLEB128 value 540 svalue = addressSpace.getSLEB128(p, expressionEnd); 541 *(++sp) = svalue; 542 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue); 543 break; 544 545 case DW_OP_dup: 546 // push top of stack 547 value = *sp; 548 *(++sp) = value; 549 if (log) fprintf(stderr, "duplicate top of stack\n"); 550 break; 551 552 case DW_OP_drop: 553 // pop 554 --sp; 555 if (log) fprintf(stderr, "pop top of stack\n"); 556 break; 557 558 case DW_OP_over: 559 // dup second 560 value = sp[-1]; 561 *(++sp) = value; 562 if (log) fprintf(stderr, "duplicate second in stack\n"); 563 break; 564 565 case DW_OP_pick: 566 // pick from 567 reg = addressSpace.get8(p); 568 p += 1; 569 value = sp[-reg]; 570 *(++sp) = value; 571 if (log) fprintf(stderr, "duplicate %d in stack\n", reg); 572 break; 573 574 case DW_OP_swap: 575 // swap top two 576 value = sp[0]; 577 sp[0] = sp[-1]; 578 sp[-1] = value; 579 if (log) fprintf(stderr, "swap top of stack\n"); 580 break; 581 582 case DW_OP_rot: 583 // rotate top three 584 value = sp[0]; 585 sp[0] = sp[-1]; 586 sp[-1] = sp[-2]; 587 sp[-2] = value; 588 if (log) fprintf(stderr, "rotate top three of stack\n"); 589 break; 590 591 case DW_OP_xderef: 592 // pop stack, dereference, push result 593 value = *sp--; 594 *sp = *((uint64_t*)value); 595 if (log) fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t)value); 596 break; 597 598 case DW_OP_abs: 599 svalue = *sp; 600 if ( svalue < 0 ) 601 *sp = -svalue; 602 if (log) fprintf(stderr, "abs\n"); 603 break; 604 605 case DW_OP_and: 606 value = *sp--; 607 *sp &= value; 608 if (log) fprintf(stderr, "and\n"); 609 break; 610 611 case DW_OP_div: 612 svalue = *sp--; 613 *sp = *sp / svalue; 614 if (log) fprintf(stderr, "div\n"); 615 break; 616 617 case DW_OP_minus: 618 svalue = *sp--; 619 *sp = *sp - svalue; 620 if (log) fprintf(stderr, "minus\n"); 621 break; 622 623 case DW_OP_mod: 624 svalue = *sp--; 625 *sp = *sp % svalue; 626 if (log) fprintf(stderr, "module\n"); 627 break; 628 629 case DW_OP_mul: 630 svalue = *sp--; 631 *sp = *sp * svalue; 632 if (log) fprintf(stderr, "mul\n"); 633 break; 634 635 case DW_OP_neg: 636 *sp = 0 - *sp; 637 if (log) fprintf(stderr, "neg\n"); 638 break; 639 640 case DW_OP_not: 641 svalue = *sp; 642 *sp = ~svalue; 643 if (log) fprintf(stderr, "not\n"); 644 break; 645 646 case DW_OP_or: 647 value = *sp--; 648 *sp |= value; 649 if (log) fprintf(stderr, "or\n"); 650 break; 651 652 case DW_OP_plus: 653 value = *sp--; 654 *sp += value; 655 if (log) fprintf(stderr, "plus\n"); 656 break; 657 658 case DW_OP_plus_uconst: 659 // pop stack, add uelb128 constant, push result 660 *sp += addressSpace.getULEB128(p, expressionEnd); 661 if (log) fprintf(stderr, "add constant\n"); 662 break; 663 664 case DW_OP_shl: 665 value = *sp--; 666 *sp = *sp << value; 667 if (log) fprintf(stderr, "shift left\n"); 668 break; 669 670 case DW_OP_shr: 671 value = *sp--; 672 *sp = *sp >> value; 673 if (log) fprintf(stderr, "shift left\n"); 674 break; 675 676 case DW_OP_shra: 677 value = *sp--; 678 svalue = *sp; 679 *sp = svalue >> value; 680 if (log) fprintf(stderr, "shift left arithmetric\n"); 681 break; 682 683 case DW_OP_xor: 684 value = *sp--; 685 *sp ^= value; 686 if (log) fprintf(stderr, "xor\n"); 687 break; 688 689 case DW_OP_skip: 690 svalue = (int16_t)addressSpace.get16(p); 691 p += 2; 692 p += svalue; 693 if (log) fprintf(stderr, "skip %lld\n", (uint64_t)svalue); 694 break; 695 696 case DW_OP_bra: 697 svalue = (int16_t)addressSpace.get16(p); 698 p += 2; 699 if ( *sp-- ) 700 p += svalue; 701 if (log) fprintf(stderr, "bra %lld\n", (uint64_t)svalue); 702 break; 703 704 case DW_OP_eq: 705 value = *sp--; 706 *sp = (*sp == value); 707 if (log) fprintf(stderr, "eq\n"); 708 break; 709 710 case DW_OP_ge: 711 value = *sp--; 712 *sp = (*sp >= value); 713 if (log) fprintf(stderr, "ge\n"); 714 break; 715 716 case DW_OP_gt: 717 value = *sp--; 718 *sp = (*sp > value); 719 if (log) fprintf(stderr, "gt\n"); 720 break; 721 722 case DW_OP_le: 723 value = *sp--; 724 *sp = (*sp <= value); 725 if (log) fprintf(stderr, "le\n"); 726 break; 727 728 case DW_OP_lt: 729 value = *sp--; 730 *sp = (*sp < value); 731 if (log) fprintf(stderr, "lt\n"); 732 break; 733 734 case DW_OP_ne: 735 value = *sp--; 736 *sp = (*sp != value); 737 if (log) fprintf(stderr, "ne\n"); 738 break; 739 740 case DW_OP_lit0: 741 case DW_OP_lit1: 742 case DW_OP_lit2: 743 case DW_OP_lit3: 744 case DW_OP_lit4: 745 case DW_OP_lit5: 746 case DW_OP_lit6: 747 case DW_OP_lit7: 748 case DW_OP_lit8: 749 case DW_OP_lit9: 750 case DW_OP_lit10: 751 case DW_OP_lit11: 752 case DW_OP_lit12: 753 case DW_OP_lit13: 754 case DW_OP_lit14: 755 case DW_OP_lit15: 756 case DW_OP_lit16: 757 case DW_OP_lit17: 758 case DW_OP_lit18: 759 case DW_OP_lit19: 760 case DW_OP_lit20: 761 case DW_OP_lit21: 762 case DW_OP_lit22: 763 case DW_OP_lit23: 764 case DW_OP_lit24: 765 case DW_OP_lit25: 766 case DW_OP_lit26: 767 case DW_OP_lit27: 768 case DW_OP_lit28: 769 case DW_OP_lit29: 770 case DW_OP_lit30: 771 case DW_OP_lit31: 772 value = opcode - DW_OP_lit0; 773 *(++sp) = value; 774 if (log) fprintf(stderr, "push literal 0x%llX\n", (uint64_t)value); 775 break; 776 777 case DW_OP_reg0: 778 case DW_OP_reg1: 779 case DW_OP_reg2: 780 case DW_OP_reg3: 781 case DW_OP_reg4: 782 case DW_OP_reg5: 783 case DW_OP_reg6: 784 case DW_OP_reg7: 785 case DW_OP_reg8: 786 case DW_OP_reg9: 787 case DW_OP_reg10: 788 case DW_OP_reg11: 789 case DW_OP_reg12: 790 case DW_OP_reg13: 791 case DW_OP_reg14: 792 case DW_OP_reg15: 793 case DW_OP_reg16: 794 case DW_OP_reg17: 795 case DW_OP_reg18: 796 case DW_OP_reg19: 797 case DW_OP_reg20: 798 case DW_OP_reg21: 799 case DW_OP_reg22: 800 case DW_OP_reg23: 801 case DW_OP_reg24: 802 case DW_OP_reg25: 803 case DW_OP_reg26: 804 case DW_OP_reg27: 805 case DW_OP_reg28: 806 case DW_OP_reg29: 807 case DW_OP_reg30: 808 case DW_OP_reg31: 809 reg = opcode - DW_OP_reg0; 810 *(++sp) = registers.getRegister(reg); 811 if (log) fprintf(stderr, "push reg %d\n", reg); 812 break; 813 814 case DW_OP_regx: 815 reg = addressSpace.getULEB128(p, expressionEnd); 816 *(++sp) = registers.getRegister(reg); 817 if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue); 818 break; 819 820 case DW_OP_breg0: 821 case DW_OP_breg1: 822 case DW_OP_breg2: 823 case DW_OP_breg3: 824 case DW_OP_breg4: 825 case DW_OP_breg5: 826 case DW_OP_breg6: 827 case DW_OP_breg7: 828 case DW_OP_breg8: 829 case DW_OP_breg9: 830 case DW_OP_breg10: 831 case DW_OP_breg11: 832 case DW_OP_breg12: 833 case DW_OP_breg13: 834 case DW_OP_breg14: 835 case DW_OP_breg15: 836 case DW_OP_breg16: 837 case DW_OP_breg17: 838 case DW_OP_breg18: 839 case DW_OP_breg19: 840 case DW_OP_breg20: 841 case DW_OP_breg21: 842 case DW_OP_breg22: 843 case DW_OP_breg23: 844 case DW_OP_breg24: 845 case DW_OP_breg25: 846 case DW_OP_breg26: 847 case DW_OP_breg27: 848 case DW_OP_breg28: 849 case DW_OP_breg29: 850 case DW_OP_breg30: 851 case DW_OP_breg31: 852 reg = opcode - DW_OP_breg0; 853 svalue = addressSpace.getSLEB128(p, expressionEnd); 854 *(++sp) = registers.getRegister(reg) + svalue; 855 if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue); 856 break; 857 858 case DW_OP_bregx: 859 reg = addressSpace.getULEB128(p, expressionEnd); 860 svalue = addressSpace.getSLEB128(p, expressionEnd); 861 *(++sp) = registers.getRegister(reg) + svalue; 862 if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue); 863 break; 864 865 case DW_OP_fbreg: 866 ABORT("DW_OP_fbreg not implemented"); 867 break; 868 869 case DW_OP_piece: 870 ABORT("DW_OP_piece not implemented"); 871 break; 872 873 case DW_OP_deref_size: 874 // pop stack, dereference, push result 875 value = *sp--; 876 switch ( addressSpace.get8(p++) ) { 877 case 1: 878 value = addressSpace.get8(value); 879 break; 880 case 2: 881 value = addressSpace.get16(value); 882 break; 883 case 4: 884 value = addressSpace.get32(value); 885 break; 886 case 8: 887 value = addressSpace.get64(value); 888 break; 889 default: 890 ABORT("DW_OP_deref_size with bad size"); 891 } 892 *(++sp) = value; 893 if (log) fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t)value); 894 break; 895 896 case DW_OP_xderef_size: 897 case DW_OP_nop: 898 case DW_OP_push_object_addres: 899 case DW_OP_call2: 900 case DW_OP_call4: 901 case DW_OP_call_ref: 902 default: 903 ABORT("dwarf opcode not implemented"); 904 } 905 906 } 907 if (log) fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t)*sp); 908 return *sp; 909} 910 911 912 913// 914// x86_64 specific functions 915// 916 917template <typename A, typename R> 918int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86_64&) 919{ 920 COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_64_RET_ADDR ); 921 return DW_X86_64_RET_ADDR; 922} 923 924template <typename A, typename R> 925bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86_64&) 926{ 927 return (regNum == DW_X86_64_RET_ADDR); 928} 929 930template <typename A, typename R> 931typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 932 const Registers_x86_64& registers) 933{ 934 if ( prolog.cfaRegister != 0 ) 935 return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset; 936 else if ( prolog.cfaExpression != 0 ) 937 return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0); 938 else 939 ABORT("getCFA(): unknown location for x86_64 cfa"); 940} 941 942 943 944template <typename A, typename R> 945compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86_64&) 946{ 947 return UNWIND_X86_64_MODE_DWARF; 948} 949 950template <typename A, typename R> 951compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86&) 952{ 953 return UNWIND_X86_MODE_DWARF; 954} 955 956 957 958template <typename A, typename R> 959uint32_t DwarfInstructions<A,R>::getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure) 960{ 961 if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 32) ) { 962 failure = true; 963 return 0; 964 } 965 unsigned int slotIndex = regOffsetFromBaseOffset/8; 966 967 switch ( reg ) { 968 case UNW_X86_64_RBX: 969 return UNWIND_X86_64_REG_RBX << (slotIndex*3); 970 case UNW_X86_64_R12: 971 return UNWIND_X86_64_REG_R12 << (slotIndex*3); 972 case UNW_X86_64_R13: 973 return UNWIND_X86_64_REG_R13 << (slotIndex*3); 974 case UNW_X86_64_R14: 975 return UNWIND_X86_64_REG_R14 << (slotIndex*3); 976 case UNW_X86_64_R15: 977 return UNWIND_X86_64_REG_R15 << (slotIndex*3); 978 } 979 980 // invalid register 981 failure = true; 982 return 0; 983} 984 985 986 987template <typename A, typename R> 988compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, 989 const Registers_x86_64& r, const typename CFI_Parser<A>::PrologInfo& prolog, 990 char warningBuffer[1024]) 991{ 992 warningBuffer[0] = '\0'; 993 994 if ( prolog.registerSavedTwiceInCIE == DW_X86_64_RET_ADDR ) { 995 warningBuffer[0] = '\0'; // silently disable conversion to compact unwind by linker 996 return UNWIND_X86_64_MODE_DWARF; 997 } 998 // don't create compact unwind info for unsupported dwarf kinds 999 if ( prolog.registerSavedMoreThanOnce ) { 1000 strcpy(warningBuffer, "register saved more than once (might be shrink wrap)"); 1001 return UNWIND_X86_64_MODE_DWARF; 1002 } 1003 if ( prolog.cfaOffsetWasNegative ) { 1004 strcpy(warningBuffer, "cfa had negative offset (dwarf might contain epilog)"); 1005 return UNWIND_X86_64_MODE_DWARF; 1006 } 1007 if ( prolog.spExtraArgSize != 0 ) { 1008 strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size"); 1009 return UNWIND_X86_64_MODE_DWARF; 1010 } 1011 if ( prolog.sameValueUsed ) { 1012 strcpy(warningBuffer, "dwarf uses DW_CFA_same_value"); 1013 return UNWIND_X86_64_MODE_DWARF; 1014 } 1015 1016 // figure out which kind of frame this function uses 1017 bool standardRBPframe = ( 1018 (prolog.cfaRegister == UNW_X86_64_RBP) 1019 && (prolog.cfaRegisterOffset == 16) 1020 && (prolog.savedRegisters[UNW_X86_64_RBP].location == CFI_Parser<A>::kRegisterInCFA) 1021 && (prolog.savedRegisters[UNW_X86_64_RBP].value == -16) ); 1022 bool standardRSPframe = (prolog.cfaRegister == UNW_X86_64_RSP); 1023 if ( !standardRBPframe && !standardRSPframe ) { 1024 // no compact encoding for this 1025 strcpy(warningBuffer, "does not use RBP or RSP based frame"); 1026 return UNWIND_X86_64_MODE_DWARF; 1027 } 1028 1029 // scan which registers are saved 1030 int saveRegisterCount = 0; 1031 bool rbxSaved = false; 1032 bool r12Saved = false; 1033 bool r13Saved = false; 1034 bool r14Saved = false; 1035 bool r15Saved = false; 1036 bool rbpSaved = false; 1037 for (int i=0; i < 64; ++i) { 1038 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) { 1039 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) { 1040 sprintf(warningBuffer, "register %d saved somewhere other that in frame", i); 1041 return UNWIND_X86_64_MODE_DWARF; 1042 } 1043 switch (i) { 1044 case UNW_X86_64_RBX: 1045 rbxSaved = true; 1046 ++saveRegisterCount; 1047 break; 1048 case UNW_X86_64_R12: 1049 r12Saved = true; 1050 ++saveRegisterCount; 1051 break; 1052 case UNW_X86_64_R13: 1053 r13Saved = true; 1054 ++saveRegisterCount; 1055 break; 1056 case UNW_X86_64_R14: 1057 r14Saved = true; 1058 ++saveRegisterCount; 1059 break; 1060 case UNW_X86_64_R15: 1061 r15Saved = true; 1062 ++saveRegisterCount; 1063 break; 1064 case UNW_X86_64_RBP: 1065 rbpSaved = true; 1066 ++saveRegisterCount; 1067 break; 1068 case DW_X86_64_RET_ADDR: 1069 break; 1070 default: 1071 sprintf(warningBuffer, "non-standard register %d being saved in prolog", i); 1072 return UNWIND_X86_64_MODE_DWARF; 1073 } 1074 } 1075 } 1076 const int64_t cfaOffsetRBX = prolog.savedRegisters[UNW_X86_64_RBX].value; 1077 const int64_t cfaOffsetR12 = prolog.savedRegisters[UNW_X86_64_R12].value; 1078 const int64_t cfaOffsetR13 = prolog.savedRegisters[UNW_X86_64_R13].value; 1079 const int64_t cfaOffsetR14 = prolog.savedRegisters[UNW_X86_64_R14].value; 1080 const int64_t cfaOffsetR15 = prolog.savedRegisters[UNW_X86_64_R15].value; 1081 const int64_t cfaOffsetRBP = prolog.savedRegisters[UNW_X86_64_RBP].value; 1082 1083 // encode standard RBP frames 1084 compact_unwind_encoding_t encoding = 0; 1085 if ( standardRBPframe ) { 1086 // | | 1087 // +--------------+ <- CFA 1088 // | ret addr | 1089 // +--------------+ 1090 // | rbp | 1091 // +--------------+ <- rbp 1092 // ~ ~ 1093 // +--------------+ 1094 // | saved reg3 | 1095 // +--------------+ <- CFA - offset+16 1096 // | saved reg2 | 1097 // +--------------+ <- CFA - offset+8 1098 // | saved reg1 | 1099 // +--------------+ <- CFA - offset 1100 // | | 1101 // +--------------+ 1102 // | | 1103 // <- rsp 1104 // 1105 encoding = UNWIND_X86_64_MODE_RBP_FRAME; 1106 1107 // find save location of farthest register from rbp 1108 int furthestCfaOffset = 0; 1109 if ( rbxSaved & (cfaOffsetRBX < furthestCfaOffset) ) 1110 furthestCfaOffset = cfaOffsetRBX; 1111 if ( r12Saved & (cfaOffsetR12 < furthestCfaOffset) ) 1112 furthestCfaOffset = cfaOffsetR12; 1113 if ( r13Saved & (cfaOffsetR13 < furthestCfaOffset) ) 1114 furthestCfaOffset = cfaOffsetR13; 1115 if ( r14Saved & (cfaOffsetR14 < furthestCfaOffset) ) 1116 furthestCfaOffset = cfaOffsetR14; 1117 if ( r15Saved & (cfaOffsetR15 < furthestCfaOffset) ) 1118 furthestCfaOffset = cfaOffsetR15; 1119 1120 if ( furthestCfaOffset == 0 ) { 1121 // no registers saved, nothing more to encode 1122 return encoding; 1123 } 1124 1125 // add stack offset to encoding 1126 int rbpOffset = furthestCfaOffset + 16; 1127 int encodedOffset = rbpOffset/(-8); 1128 if ( encodedOffset > 255 ) { 1129 strcpy(warningBuffer, "offset of saved registers too far to encode"); 1130 return UNWIND_X86_64_MODE_DWARF; 1131 } 1132 encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_64_RBP_FRAME_OFFSET)); 1133 1134 // add register saved from each stack location 1135 bool encodingFailure = false; 1136 if ( rbxSaved ) 1137 encoding |= getRBPEncodedRegister(UNW_X86_64_RBX, cfaOffsetRBX - furthestCfaOffset, encodingFailure); 1138 if ( r12Saved ) 1139 encoding |= getRBPEncodedRegister(UNW_X86_64_R12, cfaOffsetR12 - furthestCfaOffset, encodingFailure); 1140 if ( r13Saved ) 1141 encoding |= getRBPEncodedRegister(UNW_X86_64_R13, cfaOffsetR13 - furthestCfaOffset, encodingFailure); 1142 if ( r14Saved ) 1143 encoding |= getRBPEncodedRegister(UNW_X86_64_R14, cfaOffsetR14 - furthestCfaOffset, encodingFailure); 1144 if ( r15Saved ) 1145 encoding |= getRBPEncodedRegister(UNW_X86_64_R15, cfaOffsetR15 - furthestCfaOffset, encodingFailure); 1146 1147 if ( encodingFailure ){ 1148 strcpy(warningBuffer, "saved registers not contiguous"); 1149 return UNWIND_X86_64_MODE_DWARF; 1150 } 1151 1152 return encoding; 1153 } 1154 else { 1155 // | | 1156 // +--------------+ <- CFA 1157 // | ret addr | 1158 // +--------------+ 1159 // | saved reg1 | 1160 // +--------------+ <- CFA - 16 1161 // | saved reg2 | 1162 // +--------------+ <- CFA - 24 1163 // | saved reg3 | 1164 // +--------------+ <- CFA - 32 1165 // | saved reg4 | 1166 // +--------------+ <- CFA - 40 1167 // | saved reg5 | 1168 // +--------------+ <- CFA - 48 1169 // | saved reg6 | 1170 // +--------------+ <- CFA - 56 1171 // | | 1172 // <- esp 1173 // 1174 1175 // for RSP based frames we need to encode stack size in unwind info 1176 encoding = UNWIND_X86_64_MODE_STACK_IMMD; 1177 uint64_t stackValue = prolog.cfaRegisterOffset / 8; 1178 uint32_t stackAdjust = 0; 1179 bool immedStackSize = true; 1180 const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_64_FRAMELESS_STACK_SIZE); 1181 if ( stackValue > stackMaxImmedValue ) { 1182 // stack size is too big to fit as an immediate value, so encode offset of subq instruction in function 1183 if ( prolog.codeOffsetAtStackDecrement == 0 ) { 1184 strcpy(warningBuffer, "stack size is large but stack subq instruction not found"); 1185 return UNWIND_X86_64_MODE_DWARF; 1186 } 1187 pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4; 1188 #if __EXCEPTIONS 1189 try { 1190 #endif 1191 uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns); 1192 stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/8; 1193 #if __EXCEPTIONS 1194 } 1195 catch (...) { 1196 strcpy(warningBuffer, "stack size is large but stack subq instruction not found"); 1197 return UNWIND_X86_64_MODE_DWARF; 1198 } 1199 #endif 1200 stackValue = functionContentAdjustStackIns - funcAddr; 1201 immedStackSize = false; 1202 if ( stackAdjust > 7 ) { 1203 strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size"); 1204 return UNWIND_X86_64_MODE_DWARF; 1205 } 1206 encoding = UNWIND_X86_64_MODE_STACK_IND; 1207 } 1208 1209 1210 // validate that saved registers are all within 6 slots abutting return address 1211 int registers[6]; 1212 for (int i=0; i < 6;++i) 1213 registers[i] = 0; 1214 if ( r15Saved ) { 1215 if ( cfaOffsetR15 < -56 ) { 1216 strcpy(warningBuffer, "r15 is saved too far from return address"); 1217 return UNWIND_X86_64_MODE_DWARF; 1218 } 1219 registers[(cfaOffsetR15+56)/8] = UNWIND_X86_64_REG_R15; 1220 } 1221 if ( r14Saved ) { 1222 if ( cfaOffsetR14 < -56 ) { 1223 strcpy(warningBuffer, "r14 is saved too far from return address"); 1224 return UNWIND_X86_64_MODE_DWARF; 1225 } 1226 registers[(cfaOffsetR14+56)/8] = UNWIND_X86_64_REG_R14; 1227 } 1228 if ( r13Saved ) { 1229 if ( cfaOffsetR13 < -56 ) { 1230 strcpy(warningBuffer, "r13 is saved too far from return address"); 1231 return UNWIND_X86_64_MODE_DWARF; 1232 } 1233 registers[(cfaOffsetR13+56)/8] = UNWIND_X86_64_REG_R13; 1234 } 1235 if ( r12Saved ) { 1236 if ( cfaOffsetR12 < -56 ) { 1237 strcpy(warningBuffer, "r12 is saved too far from return address"); 1238 return UNWIND_X86_64_MODE_DWARF; 1239 } 1240 registers[(cfaOffsetR12+56)/8] = UNWIND_X86_64_REG_R12; 1241 } 1242 if ( rbxSaved ) { 1243 if ( cfaOffsetRBX < -56 ) { 1244 strcpy(warningBuffer, "rbx is saved too far from return address"); 1245 return UNWIND_X86_64_MODE_DWARF; 1246 } 1247 registers[(cfaOffsetRBX+56)/8] = UNWIND_X86_64_REG_RBX; 1248 } 1249 if ( rbpSaved ) { 1250 if ( cfaOffsetRBP < -56 ) { 1251 strcpy(warningBuffer, "rbp is saved too far from return address"); 1252 return UNWIND_X86_64_MODE_DWARF; 1253 } 1254 registers[(cfaOffsetRBP+56)/8] = UNWIND_X86_64_REG_RBP; 1255 } 1256 1257 // validate that saved registers are contiguous and abut return address on stack 1258 for (int i=0; i < saveRegisterCount; ++i) { 1259 if ( registers[5-i] == 0 ) { 1260 strcpy(warningBuffer, "registers not save contiguously in stack"); 1261 return UNWIND_X86_64_MODE_DWARF; 1262 } 1263 } 1264 1265 // encode register permutation 1266 // the 10-bits are encoded differently depending on the number of registers saved 1267 int renumregs[6]; 1268 for (int i=6-saveRegisterCount; i < 6; ++i) { 1269 int countless = 0; 1270 for (int j=6-saveRegisterCount; j < i; ++j) { 1271 if ( registers[j] < registers[i] ) 1272 ++countless; 1273 } 1274 renumregs[i] = registers[i] - countless -1; 1275 } 1276 uint32_t permutationEncoding = 0; 1277 switch ( saveRegisterCount ) { 1278 case 6: 1279 permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]); 1280 break; 1281 case 5: 1282 permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]); 1283 break; 1284 case 4: 1285 permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]); 1286 break; 1287 case 3: 1288 permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]); 1289 break; 1290 case 2: 1291 permutationEncoding |= (5*renumregs[4] + renumregs[5]); 1292 break; 1293 case 1: 1294 permutationEncoding |= (renumregs[5]); 1295 break; 1296 } 1297 1298 encoding |= (stackValue << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_SIZE)); 1299 encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_ADJUST)); 1300 encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT)); 1301 encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION)); 1302 return encoding; 1303 } 1304} 1305 1306 1307 1308 1309// 1310// x86 specific functions 1311// 1312template <typename A, typename R> 1313int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86&) 1314{ 1315 COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_RET_ADDR ); 1316 return DW_X86_RET_ADDR; 1317} 1318 1319template <typename A, typename R> 1320bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86&) 1321{ 1322 return (regNum == DW_X86_RET_ADDR); 1323} 1324 1325template <typename A, typename R> 1326typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 1327 const Registers_x86& registers) 1328{ 1329 if ( prolog.cfaRegister != 0 ) 1330 return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset; 1331 else if ( prolog.cfaExpression != 0 ) 1332 return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0); 1333 else 1334 ABORT("getCFA(): unknown location for x86 cfa"); 1335} 1336 1337 1338 1339 1340 1341template <typename A, typename R> 1342uint32_t DwarfInstructions<A,R>::getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure) 1343{ 1344 if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 16) ) { 1345 failure = true; 1346 return 0; 1347 } 1348 unsigned int slotIndex = regOffsetFromBaseOffset/4; 1349 1350 switch ( reg ) { 1351 case UNW_X86_EBX: 1352 return UNWIND_X86_REG_EBX << (slotIndex*3); 1353 case UNW_X86_ECX: 1354 return UNWIND_X86_REG_ECX << (slotIndex*3); 1355 case UNW_X86_EDX: 1356 return UNWIND_X86_REG_EDX << (slotIndex*3); 1357 case UNW_X86_EDI: 1358 return UNWIND_X86_REG_EDI << (slotIndex*3); 1359 case UNW_X86_ESI: 1360 return UNWIND_X86_REG_ESI << (slotIndex*3); 1361 } 1362 1363 // invalid register 1364 failure = true; 1365 return 0; 1366} 1367 1368template <typename A, typename R> 1369compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, 1370 const Registers_x86& r, const typename CFI_Parser<A>::PrologInfo& prolog, 1371 char warningBuffer[1024]) 1372{ 1373 warningBuffer[0] = '\0'; 1374 1375 if ( prolog.registerSavedTwiceInCIE == DW_X86_RET_ADDR ) { 1376 warningBuffer[0] = '\0'; // silently disable conversion to compact unwind by linker 1377 return UNWIND_X86_64_MODE_DWARF; 1378 } 1379 // don't create compact unwind info for unsupported dwarf kinds 1380 if ( prolog.registerSavedMoreThanOnce ) { 1381 strcpy(warningBuffer, "register saved more than once (might be shrink wrap)"); 1382 return UNWIND_X86_MODE_DWARF; 1383 } 1384 if ( prolog.spExtraArgSize != 0 ) { 1385 strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size"); 1386 return UNWIND_X86_MODE_DWARF; 1387 } 1388 if ( prolog.sameValueUsed ) { 1389 strcpy(warningBuffer, "dwarf uses DW_CFA_same_value"); 1390 return UNWIND_X86_MODE_DWARF; 1391 } 1392 1393 // figure out which kind of frame this function uses 1394 bool standardEBPframe = ( 1395 (prolog.cfaRegister == UNW_X86_EBP) 1396 && (prolog.cfaRegisterOffset == 8) 1397 && (prolog.savedRegisters[UNW_X86_EBP].location == CFI_Parser<A>::kRegisterInCFA) 1398 && (prolog.savedRegisters[UNW_X86_EBP].value == -8) ); 1399 bool standardESPframe = (prolog.cfaRegister == UNW_X86_ESP); 1400 if ( !standardEBPframe && !standardESPframe ) { 1401 // no compact encoding for this 1402 strcpy(warningBuffer, "does not use EBP or ESP based frame"); 1403 return UNWIND_X86_MODE_DWARF; 1404 } 1405 1406 // scan which registers are saved 1407 int saveRegisterCount = 0; 1408 bool ebxSaved = false; 1409 bool ecxSaved = false; 1410 bool edxSaved = false; 1411 bool esiSaved = false; 1412 bool ediSaved = false; 1413 bool ebpSaved = false; 1414 for (int i=0; i < 64; ++i) { 1415 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) { 1416 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) { 1417 sprintf(warningBuffer, "register %d saved somewhere other that in frame", i); 1418 return UNWIND_X86_MODE_DWARF; 1419 } 1420 switch (i) { 1421 case UNW_X86_EBX: 1422 ebxSaved = true; 1423 ++saveRegisterCount; 1424 break; 1425 case UNW_X86_ECX: 1426 ecxSaved = true; 1427 ++saveRegisterCount; 1428 break; 1429 case UNW_X86_EDX: 1430 edxSaved = true; 1431 ++saveRegisterCount; 1432 break; 1433 case UNW_X86_ESI: 1434 esiSaved = true; 1435 ++saveRegisterCount; 1436 break; 1437 case UNW_X86_EDI: 1438 ediSaved = true; 1439 ++saveRegisterCount; 1440 break; 1441 case UNW_X86_EBP: 1442 ebpSaved = true; 1443 ++saveRegisterCount; 1444 break; 1445 case DW_X86_RET_ADDR: 1446 break; 1447 default: 1448 sprintf(warningBuffer, "non-standard register %d being saved in prolog", i); 1449 return UNWIND_X86_MODE_DWARF; 1450 } 1451 } 1452 } 1453 const int32_t cfaOffsetEBX = prolog.savedRegisters[UNW_X86_EBX].value; 1454 const int32_t cfaOffsetECX = prolog.savedRegisters[UNW_X86_ECX].value; 1455 const int32_t cfaOffsetEDX = prolog.savedRegisters[UNW_X86_EDX].value; 1456 const int32_t cfaOffsetEDI = prolog.savedRegisters[UNW_X86_EDI].value; 1457 const int32_t cfaOffsetESI = prolog.savedRegisters[UNW_X86_ESI].value; 1458 const int32_t cfaOffsetEBP = prolog.savedRegisters[UNW_X86_EBP].value; 1459 1460 // encode standard RBP frames 1461 compact_unwind_encoding_t encoding = 0; 1462 if ( standardEBPframe ) { 1463 // | | 1464 // +--------------+ <- CFA 1465 // | ret addr | 1466 // +--------------+ 1467 // | ebp | 1468 // +--------------+ <- ebp 1469 // ~ ~ 1470 // +--------------+ 1471 // | saved reg3 | 1472 // +--------------+ <- CFA - offset+8 1473 // | saved reg2 | 1474 // +--------------+ <- CFA - offset+e 1475 // | saved reg1 | 1476 // +--------------+ <- CFA - offset 1477 // | | 1478 // +--------------+ 1479 // | | 1480 // <- esp 1481 // 1482 encoding = UNWIND_X86_MODE_EBP_FRAME; 1483 1484 // find save location of farthest register from ebp 1485 int furthestCfaOffset = 0; 1486 if ( ebxSaved & (cfaOffsetEBX < furthestCfaOffset) ) 1487 furthestCfaOffset = cfaOffsetEBX; 1488 if ( ecxSaved & (cfaOffsetECX < furthestCfaOffset) ) 1489 furthestCfaOffset = cfaOffsetECX; 1490 if ( edxSaved & (cfaOffsetEDX < furthestCfaOffset) ) 1491 furthestCfaOffset = cfaOffsetEDX; 1492 if ( ediSaved & (cfaOffsetEDI < furthestCfaOffset) ) 1493 furthestCfaOffset = cfaOffsetEDI; 1494 if ( esiSaved & (cfaOffsetESI < furthestCfaOffset) ) 1495 furthestCfaOffset = cfaOffsetESI; 1496 1497 if ( furthestCfaOffset == 0 ) { 1498 // no registers saved, nothing more to encode 1499 return encoding; 1500 } 1501 1502 // add stack offset to encoding 1503 int ebpOffset = furthestCfaOffset + 8; 1504 int encodedOffset = ebpOffset/(-4); 1505 if ( encodedOffset > 255 ) { 1506 strcpy(warningBuffer, "offset of saved registers too far to encode"); 1507 return UNWIND_X86_MODE_DWARF; 1508 } 1509 encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_EBP_FRAME_OFFSET)); 1510 1511 // add register saved from each stack location 1512 bool encodingFailure = false; 1513 if ( ebxSaved ) 1514 encoding |= getEBPEncodedRegister(UNW_X86_EBX, cfaOffsetEBX - furthestCfaOffset, encodingFailure); 1515 if ( ecxSaved ) 1516 encoding |= getEBPEncodedRegister(UNW_X86_ECX, cfaOffsetECX - furthestCfaOffset, encodingFailure); 1517 if ( edxSaved ) 1518 encoding |= getEBPEncodedRegister(UNW_X86_EDX, cfaOffsetEDX - furthestCfaOffset, encodingFailure); 1519 if ( ediSaved ) 1520 encoding |= getEBPEncodedRegister(UNW_X86_EDI, cfaOffsetEDI - furthestCfaOffset, encodingFailure); 1521 if ( esiSaved ) 1522 encoding |= getEBPEncodedRegister(UNW_X86_ESI, cfaOffsetESI - furthestCfaOffset, encodingFailure); 1523 1524 if ( encodingFailure ){ 1525 strcpy(warningBuffer, "saved registers not contiguous"); 1526 return UNWIND_X86_MODE_DWARF; 1527 } 1528 1529 return encoding; 1530 } 1531 else { 1532 // | | 1533 // +--------------+ <- CFA 1534 // | ret addr | 1535 // +--------------+ 1536 // | saved reg1 | 1537 // +--------------+ <- CFA - 8 1538 // | saved reg2 | 1539 // +--------------+ <- CFA - 12 1540 // | saved reg3 | 1541 // +--------------+ <- CFA - 16 1542 // | saved reg4 | 1543 // +--------------+ <- CFA - 20 1544 // | saved reg5 | 1545 // +--------------+ <- CFA - 24 1546 // | saved reg6 | 1547 // +--------------+ <- CFA - 28 1548 // | | 1549 // <- esp 1550 // 1551 1552 // for ESP based frames we need to encode stack size in unwind info 1553 encoding = UNWIND_X86_MODE_STACK_IMMD; 1554 uint64_t stackValue = prolog.cfaRegisterOffset / 4; 1555 uint32_t stackAdjust = 0; 1556 bool immedStackSize = true; 1557 const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_FRAMELESS_STACK_SIZE); 1558 if ( stackValue > stackMaxImmedValue ) { 1559 // stack size is too big to fit as an immediate value, so encode offset of subq instruction in function 1560 pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4; 1561 #if __EXCEPTIONS 1562 try { 1563 #endif 1564 uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns); 1565 stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/4; 1566 #if __EXCEPTIONS 1567 } 1568 catch (...) { 1569 strcpy(warningBuffer, "stack size is large but stack subl instruction not found"); 1570 return UNWIND_X86_MODE_DWARF; 1571 } 1572 #endif 1573 stackValue = functionContentAdjustStackIns - funcAddr; 1574 immedStackSize = false; 1575 if ( stackAdjust > 7 ) { 1576 strcpy(warningBuffer, "stack subl instruction is too different from dwarf stack size"); 1577 return UNWIND_X86_MODE_DWARF; 1578 } 1579 encoding = UNWIND_X86_MODE_STACK_IND; 1580 } 1581 1582 1583 // validate that saved registers are all within 6 slots abutting return address 1584 int registers[6]; 1585 for (int i=0; i < 6;++i) 1586 registers[i] = 0; 1587 if ( ebxSaved ) { 1588 if ( cfaOffsetEBX < -28 ) { 1589 strcpy(warningBuffer, "ebx is saved too far from return address"); 1590 return UNWIND_X86_MODE_DWARF; 1591 } 1592 registers[(cfaOffsetEBX+28)/4] = UNWIND_X86_REG_EBX; 1593 } 1594 if ( ecxSaved ) { 1595 if ( cfaOffsetECX < -28 ) { 1596 strcpy(warningBuffer, "ecx is saved too far from return address"); 1597 return UNWIND_X86_MODE_DWARF; 1598 } 1599 registers[(cfaOffsetECX+28)/4] = UNWIND_X86_REG_ECX; 1600 } 1601 if ( edxSaved ) { 1602 if ( cfaOffsetEDX < -28 ) { 1603 strcpy(warningBuffer, "edx is saved too far from return address"); 1604 return UNWIND_X86_MODE_DWARF; 1605 } 1606 registers[(cfaOffsetEDX+28)/4] = UNWIND_X86_REG_EDX; 1607 } 1608 if ( ediSaved ) { 1609 if ( cfaOffsetEDI < -28 ) { 1610 strcpy(warningBuffer, "edi is saved too far from return address"); 1611 return UNWIND_X86_MODE_DWARF; 1612 } 1613 registers[(cfaOffsetEDI+28)/4] = UNWIND_X86_REG_EDI; 1614 } 1615 if ( esiSaved ) { 1616 if ( cfaOffsetESI < -28 ) { 1617 strcpy(warningBuffer, "esi is saved too far from return address"); 1618 return UNWIND_X86_MODE_DWARF; 1619 } 1620 registers[(cfaOffsetESI+28)/4] = UNWIND_X86_REG_ESI; 1621 } 1622 if ( ebpSaved ) { 1623 if ( cfaOffsetEBP < -28 ) { 1624 strcpy(warningBuffer, "ebp is saved too far from return address"); 1625 return UNWIND_X86_MODE_DWARF; 1626 } 1627 registers[(cfaOffsetEBP+28)/4] = UNWIND_X86_REG_EBP; 1628 } 1629 1630 // validate that saved registers are contiguous and abut return address on stack 1631 for (int i=0; i < saveRegisterCount; ++i) { 1632 if ( registers[5-i] == 0 ) { 1633 strcpy(warningBuffer, "registers not save contiguously in stack"); 1634 return UNWIND_X86_MODE_DWARF; 1635 } 1636 } 1637 1638 // encode register permutation 1639 // the 10-bits are encoded differently depending on the number of registers saved 1640 int renumregs[6]; 1641 for (int i=6-saveRegisterCount; i < 6; ++i) { 1642 int countless = 0; 1643 for (int j=6-saveRegisterCount; j < i; ++j) { 1644 if ( registers[j] < registers[i] ) 1645 ++countless; 1646 } 1647 renumregs[i] = registers[i] - countless -1; 1648 } 1649 uint32_t permutationEncoding = 0; 1650 switch ( saveRegisterCount ) { 1651 case 6: 1652 permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]); 1653 break; 1654 case 5: 1655 permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]); 1656 break; 1657 case 4: 1658 permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]); 1659 break; 1660 case 3: 1661 permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]); 1662 break; 1663 case 2: 1664 permutationEncoding |= (5*renumregs[4] + renumregs[5]); 1665 break; 1666 case 1: 1667 permutationEncoding |= (renumregs[5]); 1668 break; 1669 } 1670 1671 encoding |= (stackValue << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_SIZE)); 1672 encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_ADJUST)); 1673 encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_COUNT)); 1674 encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION)); 1675 return encoding; 1676 } 1677} 1678 1679 1680 1681 1682 1683 1684 1685// 1686// ppc specific functions 1687// 1688template <typename A, typename R> 1689int DwarfInstructions<A,R>::lastRestoreReg(const Registers_ppc&) 1690{ 1691 COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)UNW_PPC_SPEFSCR ); 1692 return UNW_PPC_SPEFSCR; 1693} 1694 1695template <typename A, typename R> 1696bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_ppc&) 1697{ 1698 return (regNum == UNW_PPC_LR); 1699} 1700 1701template <typename A, typename R> 1702typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 1703 const Registers_ppc& registers) 1704{ 1705 if ( prolog.cfaRegister != 0 ) 1706 return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset; 1707 else if ( prolog.cfaExpression != 0 ) 1708 return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0); 1709 else 1710 ABORT("getCFA(): unknown location for ppc cfa"); 1711} 1712 1713 1714template <typename A, typename R> 1715compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_ppc&) 1716{ 1717 return UNWIND_X86_MODE_DWARF; 1718} 1719 1720 1721template <typename A, typename R> 1722compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr, 1723 const Registers_ppc& r, const typename CFI_Parser<A>::PrologInfo& prolog, 1724 char warningBuffer[1024]) 1725{ 1726 warningBuffer[0] = '\0'; 1727 return UNWIND_X86_MODE_DWARF; 1728} 1729 1730 1731 1732 1733} // namespace libunwind 1734 1735 1736#endif // __DWARF_INSTRUCTIONS_HPP__ 1737 1738 1739 1740 1741