1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
 
   3  * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
 
   5  * @APPLE_LICENSE_HEADER_START@
 
   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
 
  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.
 
  22  * @APPLE_LICENSE_HEADER_END@
 
  26 // processor specific parsing of dwarf unwind instructions
 
  29 #ifndef __DWARF_INSTRUCTIONS_HPP__
 
  30 #define __DWARF_INSTRUCTIONS_HPP__
 
  39 #include <libunwind.h>
 
  40 #include <mach-o/compact_unwind_encoding.h>
 
  43 #include "AddressSpace.hpp"
 
  44 #include "Registers.hpp"
 
  45 #include "DwarfParser.hpp"
 
  46 #include "InternalMacros.h"
 
  47 //#include "CompactUnwinder.hpp"
 
  49 #define EXTRACT_BITS(value, mask) \
 
  50         ( (value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask)))-1) )
 
  52 #define CFI_INVALID_ADDRESS ((pint_t)(-1))
 
  58 /// Used by linker when parsing __eh_frame section
 
  61 struct CFI_Reference {
 
  62         typedef typename A::pint_t              pint_t; 
 
  63         uint8_t         encodingOfTargetAddress;
 
  68 struct CFI_Atom_Info {
 
  69         typedef typename A::pint_t              pint_t; 
 
  75                         CFI_Reference<A>        function;
 
  77                         CFI_Reference<A>        lsda;
 
  78                         uint32_t                compactUnwindInfo;
 
  81                         CFI_Reference<A>        personality;
 
  86 typedef void (*WarnFunc)(void* ref, uint64_t funcAddr, const char* msg);  
 
  89 /// DwarfInstructions maps abtract dwarf unwind instructions to a particular architecture
 
  91 template <typename A, typename R>
 
  92 class DwarfInstructions
 
  95         typedef typename A::pint_t              pint_t; 
 
  96         typedef typename A::sint_t              sint_t; 
 
  98         static const char* parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
 
  99                             const pint_t cuStarts[], uint32_t cuCount, 
 
 100                             bool keepDwarfWhichHasCU, bool forceDwarfConversion, bool neverConvertToCU,
 
 101                             CFI_Atom_Info<A>* infos, uint32_t& infosCount, void* ref, WarnFunc warn);
 
 104         static compact_unwind_encoding_t createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 
 
 105                                                                                                                                 pint_t* lsda, pint_t* personality,
 
 106                                                                                                                                 char warningBuffer[1024]);
 
 108         static int stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers);
 
 113                 DW_X86_64_RET_ADDR = 16
 
 120         static pint_t evaluateExpression(pint_t expression, A& addressSpace, const R& registers, pint_t initialStackValue);
 
 121         static pint_t getSavedRegister(A& addressSpace, const R& registers, pint_t cfa, 
 
 122                                                                                 const typename CFI_Parser<A>::RegisterLocation& savedReg);
 
 123         static double getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa, 
 
 124                                                                                 const typename CFI_Parser<A>::RegisterLocation& savedReg);
 
 125         static v128 getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa, 
 
 126                                                                                 const typename CFI_Parser<A>::RegisterLocation& savedReg);
 
 128         // x86 specific variants
 
 129         static int    lastRestoreReg(const Registers_x86&);
 
 130         static bool   isReturnAddressRegister(int regNum, const Registers_x86&);
 
 131         static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86&);
 
 133         static uint32_t getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure);
 
 134         static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86&);
 
 135         static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
 136                                                                                                 const Registers_x86&, const typename CFI_Parser<A>::PrologInfo& prolog,
 
 137                                                                                                 char warningBuffer[1024]);
 
 139         // x86_64 specific variants
 
 140         static int    lastRestoreReg(const Registers_x86_64&);
 
 141         static bool   isReturnAddressRegister(int regNum, const Registers_x86_64&);
 
 142         static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_x86_64&);
 
 144         static uint32_t getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure);
 
 145         static compact_unwind_encoding_t encodeToUseDwarf(const Registers_x86_64&);
 
 146         static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
 147                                                                                                 const Registers_x86_64&, const typename CFI_Parser<A>::PrologInfo& prolog,
 
 148                                                                                                 char warningBuffer[1024]);
 
 150         // ppc specific variants
 
 151         static int    lastRestoreReg(const Registers_ppc&);
 
 152         static bool   isReturnAddressRegister(int regNum, const Registers_ppc&);
 
 153         static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_ppc&);
 
 154         static compact_unwind_encoding_t encodeToUseDwarf(const Registers_ppc&);
 
 155         static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
 156                                                                                                 const Registers_ppc&, const typename CFI_Parser<A>::PrologInfo& prolog,
 
 157                                                                                                 char warningBuffer[1024]);
 
 159         // arm64 specific variants
 
 160         static bool   isReturnAddressRegister(int regNum, const Registers_arm64&);
 
 161         static int    lastRestoreReg(const Registers_arm64&);
 
 162         static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_arm64&);
 
 163         static bool checkRegisterPair(uint32_t reg, const typename CFI_Parser<A>::PrologInfo& prolog,
 
 164                                                                                                 int& offset, char warningBuffer[1024]);
 
 165         static compact_unwind_encoding_t encodeToUseDwarf(const Registers_arm64&);
 
 166         static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
 167                                                                                                 const Registers_arm64&, const typename CFI_Parser<A>::PrologInfo& prolog,
 
 168                                                                                                 char warningBuffer[1024]);
 
 175 template <typename A, typename R>
 
 176 const char* DwarfInstructions<A,R>::parseCFIs(A& addressSpace, pint_t ehSectionStart, uint32_t sectionLength, 
 
 177                                       const pint_t cuStarts[], uint32_t cuCount,  
 
 178                                       bool keepDwarfWhichHasCU,  bool forceDwarfConversion, bool neverConvertToCU,
 
 179                                       CFI_Atom_Info<A>* infos, uint32_t& infosCount, void* ref, WarnFunc warn)
 
 181         typename CFI_Parser<A>::CIE_Info cieInfo;
 
 182         CFI_Atom_Info<A>* entry = infos;
 
 183         CFI_Atom_Info<A>* end = &infos[infosCount];
 
 184         const pint_t ehSectionEnd = ehSectionStart + sectionLength;
 
 185         for (pint_t p=ehSectionStart; p < ehSectionEnd; ) {
 
 186                 pint_t currentCFI = p;
 
 187                 uint64_t cfiLength = addressSpace.get32(p);
 
 189                 if ( cfiLength == 0xffffffff ) {
 
 190                         // 0xffffffff means length is really next 8 bytes
 
 191                         cfiLength = addressSpace.get64(p);
 
 194                 if ( cfiLength == 0 ) 
 
 195                         return NULL;    // end marker
 
 197                         return "too little space allocated for parseCFIs";
 
 198                 pint_t nextCFI = p + cfiLength;
 
 199                 uint32_t id = addressSpace.get32(p);
 
 202                         const char* err = CFI_Parser<A>::parseCIE(addressSpace, currentCFI, &cieInfo);
 
 205                         entry->address = currentCFI;
 
 206                         entry->size = nextCFI - currentCFI;
 
 208                         entry->u.cieInfo.personality.targetAddress = cieInfo.personality;
 
 209                         entry->u.cieInfo.personality.offsetInCFI = cieInfo.personalityOffsetInCIE;
 
 210                         entry->u.cieInfo.personality.encodingOfTargetAddress = cieInfo.personalityEncoding;
 
 215                         entry->address = currentCFI;
 
 216                         entry->size = nextCFI - currentCFI;
 
 217                         entry->isCIE = false;
 
 218                         entry->u.fdeInfo.function.targetAddress = CFI_INVALID_ADDRESS;
 
 219                         entry->u.fdeInfo.cie.targetAddress = CFI_INVALID_ADDRESS;
 
 220                         entry->u.fdeInfo.lsda.targetAddress = CFI_INVALID_ADDRESS;
 
 221                         uint32_t ciePointer = addressSpace.get32(p);
 
 222                         pint_t cieStart = p-ciePointer;
 
 223                         // validate pointer to CIE is within section
 
 224                         if ( (cieStart < ehSectionStart) || (cieStart > ehSectionEnd) )
 
 225                                 return "FDE points to CIE outside __eh_frame section";
 
 226                         // optimize usual case where cie is same for all FDEs
 
 227                         if ( cieStart != cieInfo.cieStart ) {
 
 228                                 const char* err = CFI_Parser<A>::parseCIE(addressSpace, cieStart, &cieInfo);
 
 232                         entry->u.fdeInfo.cie.targetAddress = cieStart;
 
 233                         entry->u.fdeInfo.cie.offsetInCFI = p-currentCFI;
 
 234                         entry->u.fdeInfo.cie.encodingOfTargetAddress = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
 
 236                         // parse pc begin and range
 
 237                         pint_t offsetOfFunctionAddress = p-currentCFI;
 
 238                         pint_t pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding);
 
 239                         pint_t pcRange = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding & 0x0F);
 
 240                         //fprintf(stderr, "FDE with pcRange [0x%08llX, 0x%08llX)\n",(uint64_t)pcStart, (uint64_t)(pcStart+pcRange));
 
 241                         entry->u.fdeInfo.function.targetAddress = pcStart;
 
 242                         entry->u.fdeInfo.function.offsetInCFI = offsetOfFunctionAddress;
 
 243                         entry->u.fdeInfo.function.encodingOfTargetAddress = cieInfo.pointerEncoding;
 
 244                         // check for augmentation length
 
 245                         if ( cieInfo.fdesHaveAugmentationData ) {
 
 246                                 uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
 
 247                                 pint_t endOfAug = p + augLen;
 
 248                                 if ( cieInfo.lsdaEncoding != 0 ) {
 
 249                                         // peek at value (without indirection).  Zero means no lsda
 
 250                                         pint_t lsdaStart = p;
 
 251                                         if ( addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding & 0x0F) != 0 ) {
 
 252                                                 // reset pointer and re-parse lsda address
 
 254                                                 pint_t offsetOfLSDAAddress = p-currentCFI;
 
 255                                                 entry->u.fdeInfo.lsda.targetAddress = addressSpace.getEncodedP(p, nextCFI, cieInfo.lsdaEncoding);
 
 256                                                 entry->u.fdeInfo.lsda.offsetInCFI = offsetOfLSDAAddress;
 
 257                                                 entry->u.fdeInfo.lsda.encodingOfTargetAddress = cieInfo.lsdaEncoding;
 
 262                         // See if already is a compact unwind for this address.  
 
 263                         bool alreadyHaveCU = false;
 
 264                         for (uint32_t i=0; i < cuCount; ++i) {
 
 265                                 if (cuStarts[i] == entry->u.fdeInfo.function.targetAddress) {
 
 266                                   alreadyHaveCU = true;
 
 270                         //fprintf(stderr, "FDE for func at 0x%08X, alreadyHaveCU=%d\n", (uint32_t)entry->u.fdeInfo.function.targetAddress, alreadyHaveCU);
 
 271                         if ( alreadyHaveCU && !forceDwarfConversion ) {
 
 272                                 if ( keepDwarfWhichHasCU )
 
 276                                 if ( neverConvertToCU || ((cuCount != 0) && !forceDwarfConversion) ) {
 
 277                                         // Have some compact unwind, so this is a new .o file, therefore anything without
 
 278                                         // compact unwind must be something not expressable in compact unwind.
 
 280                                         entry->u.fdeInfo.compactUnwindInfo = encodeToUseDwarf(dummy);
 
 283                                         // compute compact unwind encoding by parsing dwarf
 
 284                                         typename CFI_Parser<A>::FDE_Info fdeInfo;
 
 285                                         fdeInfo.fdeStart = currentCFI;
 
 286                                         fdeInfo.fdeLength = nextCFI - currentCFI;
 
 287                                         fdeInfo.fdeInstructions = p;
 
 288                                         fdeInfo.pcStart = pcStart;
 
 289                                         fdeInfo.pcEnd = pcStart +  pcRange;
 
 290                                         fdeInfo.lsda = entry->u.fdeInfo.lsda.targetAddress;
 
 291                                         typename CFI_Parser<A>::PrologInfo prolog;
 
 292                                         R dummy; // for proper selection of architecture specific functions
 
 293                                         if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) {
 
 294                                                 char warningBuffer[1024];
 
 295                                                 entry->u.fdeInfo.compactUnwindInfo = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer);
 
 296                                                 if ( fdeInfo.lsda != CFI_INVALID_ADDRESS ) 
 
 297                                                         entry->u.fdeInfo.compactUnwindInfo |= UNWIND_HAS_LSDA;
 
 298                                                 if ( warningBuffer[0] != '\0' )
 
 299                                                         warn(ref, fdeInfo.pcStart, warningBuffer);
 
 302                                                 warn(ref, CFI_INVALID_ADDRESS, "dwarf unwind instructions could not be parsed");
 
 303                                                 entry->u.fdeInfo.compactUnwindInfo = encodeToUseDwarf(dummy);
 
 311         if ( entry != end ) {
 
 312                 //fprintf(stderr, "DwarfInstructions<A,R>::parseCFIs() infosCount was %d on input, now %ld\n", infosCount, entry - infos); 
 
 313                 infosCount = (entry - infos);
 
 316         return NULL; // success
 
 322 template <typename A, typename R>
 
 323 compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromFDE(A& addressSpace, pint_t fdeStart, 
 
 324                                                                                                                                                 pint_t* lsda, pint_t* personality,
 
 325                                                                                                                                                 char warningBuffer[1024])
 
 327         typename CFI_Parser<A>::FDE_Info fdeInfo;
 
 328         typename CFI_Parser<A>::CIE_Info cieInfo;
 
 329         R dummy; // for proper selection of architecture specific functions
 
 330         if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) {
 
 331                 typename CFI_Parser<A>::PrologInfo prolog;
 
 332                 if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, CFI_INVALID_ADDRESS, &prolog) ) {
 
 333                         *lsda = fdeInfo.lsda;
 
 334                         *personality = cieInfo.personality;
 
 335                         compact_unwind_encoding_t encoding;
 
 336                         encoding = createCompactEncodingFromProlog(addressSpace, fdeInfo.pcStart, dummy, prolog, warningBuffer);
 
 337                         if ( fdeInfo.lsda != 0 ) 
 
 338                                 encoding |= UNWIND_HAS_LSDA;
 
 342                         strcpy(warningBuffer, "dwarf unwind instructions could not be parsed");
 
 343                         return encodeToUseDwarf(dummy);
 
 347                 strcpy(warningBuffer, "dwarf FDE could not be parsed");
 
 348                 return encodeToUseDwarf(dummy);
 
 353 template <typename A, typename R>
 
 354 typename A::pint_t DwarfInstructions<A,R>::getSavedRegister(A& addressSpace, const R& registers, pint_t cfa,
 
 355                                                                                                         const typename CFI_Parser<A>::RegisterLocation& savedReg)
 
 357         switch ( savedReg.location ) {
 
 358                 case CFI_Parser<A>::kRegisterInCFA:
 
 359                         return addressSpace.getP(cfa + savedReg.value);
 
 361                 case CFI_Parser<A>::kRegisterAtExpression:
 
 362                         return addressSpace.getP(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
 
 364                 case CFI_Parser<A>::kRegisterIsExpression:
 
 365                         return evaluateExpression(savedReg.value, addressSpace, registers, cfa);
 
 367                 case CFI_Parser<A>::kRegisterInRegister:
 
 368                         return registers.getRegister(savedReg.value);
 
 370                 case CFI_Parser<A>::kRegisterUnused:
 
 371                 case CFI_Parser<A>::kRegisterOffsetFromCFA:
 
 375         ABORT("unsupported restore location for register");
 
 378 template <typename A, typename R>
 
 379 double DwarfInstructions<A,R>::getSavedFloatRegister(A& addressSpace, const R& registers, pint_t cfa,
 
 380                                                                                                         const typename CFI_Parser<A>::RegisterLocation& savedReg)
 
 382         switch ( savedReg.location ) {
 
 383                 case CFI_Parser<A>::kRegisterInCFA:
 
 384                         return addressSpace.getDouble(cfa + savedReg.value);
 
 386                 case CFI_Parser<A>::kRegisterAtExpression:
 
 387                         return addressSpace.getDouble(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
 
 389                 case CFI_Parser<A>::kRegisterIsExpression:
 
 390                 case CFI_Parser<A>::kRegisterUnused:
 
 391                 case CFI_Parser<A>::kRegisterOffsetFromCFA:
 
 392                 case CFI_Parser<A>::kRegisterInRegister:
 
 396         ABORT("unsupported restore location for float register");
 
 399 template <typename A, typename R>
 
 400 v128 DwarfInstructions<A,R>::getSavedVectorRegister(A& addressSpace, const R& registers, pint_t cfa,
 
 401                                                                                                         const typename CFI_Parser<A>::RegisterLocation& savedReg)
 
 403         switch ( savedReg.location ) {
 
 404                 case CFI_Parser<A>::kRegisterInCFA:
 
 405                         return addressSpace.getVector(cfa + savedReg.value);
 
 407                 case CFI_Parser<A>::kRegisterAtExpression:
 
 408                         return addressSpace.getVector(evaluateExpression(savedReg.value, addressSpace, registers, cfa));
 
 410                 case CFI_Parser<A>::kRegisterIsExpression:
 
 411                 case CFI_Parser<A>::kRegisterUnused:
 
 412                 case CFI_Parser<A>::kRegisterOffsetFromCFA:
 
 413                 case CFI_Parser<A>::kRegisterInRegister:
 
 417         ABORT("unsupported restore location for vector register");
 
 421 template <typename A, typename R>
 
 422 int DwarfInstructions<A,R>::stepWithDwarf(A& addressSpace, pint_t pc, pint_t fdeStart, R& registers)
 
 424         //fprintf(stderr, "stepWithDwarf(pc=0x%0llX, fdeStart=0x%0llX)\n", (uint64_t)pc, (uint64_t)fdeStart);
 
 425         typename CFI_Parser<A>::FDE_Info fdeInfo;
 
 426         typename CFI_Parser<A>::CIE_Info cieInfo;
 
 427         if ( CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL ) {
 
 428                 typename CFI_Parser<A>::PrologInfo prolog;
 
 429                 if ( CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &prolog) ) {
 
 430                         R newRegisters = registers;
 
 432                         // get pointer to cfa (architecture specific)
 
 433                         pint_t cfa = getCFA(addressSpace, prolog, registers);
 
 435                         // restore registers that dwarf says were saved
 
 436                         pint_t returnAddress = 0;
 
 437                         for (int i=0; i <= lastRestoreReg(newRegisters); ++i) {
 
 438                                 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
 
 439                                         if ( registers.validFloatRegister(i) )
 
 440                                                 newRegisters.setFloatRegister(i, getSavedFloatRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
 
 441                                         else if ( registers.validVectorRegister(i) )
 
 442                                                 newRegisters.setVectorRegister(i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
 
 443                                         else if ( isReturnAddressRegister(i, registers) )
 
 444                                                 returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]);
 
 445                                         else if ( registers.validRegister(i) )
 
 446                                                 newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]));
 
 452                         // by definition the CFA is the stack pointer at the call site, so restoring SP means setting it to CFA
 
 453                         newRegisters.setSP(cfa);
 
 455                         // return address is address after call site instruction, so setting IP to that does a return
 
 456                         newRegisters.setIP(returnAddress);
 
 458                         // do the actual step by replacing the register set with the new ones
 
 459                         registers = newRegisters;
 
 461                         return UNW_STEP_SUCCESS;
 
 464         return UNW_EBADFRAME;
 
 469 template <typename A, typename R>
 
 470 typename A::pint_t DwarfInstructions<A,R>::evaluateExpression(pint_t expression, A& addressSpace, 
 
 471                                                                                                                 const R& registers, pint_t initialStackValue)
 
 473         const bool log = false;
 
 474         pint_t p = expression;
 
 475         pint_t expressionEnd = expression+20; // just need something until length is read
 
 476         uint64_t length = addressSpace.getULEB128(p, expressionEnd);
 
 477         expressionEnd = p + length;
 
 478         if (log) fprintf(stderr, "evaluateExpression(): length=%llu\n", length);
 
 481         *(++sp) = initialStackValue;
 
 483         while ( p < expressionEnd ) {
 
 485                         for(pint_t* t = sp; t > stack; --t) {
 
 486                                 fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
 
 489                 uint8_t opcode = addressSpace.get8(p++);
 
 495                                 // push immediate address sized value
 
 496                                 value = addressSpace.getP(p);
 
 499                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
 
 503                                 // pop stack, dereference, push result
 
 505                                 *(++sp) = addressSpace.getP(value);
 
 506                                 if (log) fprintf(stderr, "dereference 0x%llX\n", (uint64_t)value);
 
 510                                 // push immediate 1 byte value
 
 511                                 value = addressSpace.get8(p);
 
 514                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
 
 518                                 // push immediate 1 byte signed value
 
 519                                 svalue = (int8_t)addressSpace.get8(p);
 
 522                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
 
 526                                 // push immediate 2 byte value
 
 527                                 value = addressSpace.get16(p);
 
 530                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
 
 534                                 // push immediate 2 byte signed value
 
 535                                 svalue = (int16_t)addressSpace.get16(p);
 
 538                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
 
 542                                 // push immediate 4 byte value
 
 543                                 value = addressSpace.get32(p);
 
 546                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
 
 550                                 // push immediate 4 byte signed value
 
 551                                 svalue = (int32_t)addressSpace.get32(p);
 
 554                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
 
 558                                 // push immediate 8 byte value
 
 559                                 value = addressSpace.get64(p);
 
 562                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
 
 566                                 // push immediate 8 byte signed value
 
 567                                 value = (int32_t)addressSpace.get64(p);
 
 570                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
 
 574                                 // push immediate ULEB128 value
 
 575                                 value = addressSpace.getULEB128(p, expressionEnd);
 
 577                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)value);
 
 581                                 // push immediate SLEB128 value
 
 582                                 svalue = addressSpace.getSLEB128(p, expressionEnd);
 
 584                                 if (log) fprintf(stderr, "push 0x%llX\n", (uint64_t)svalue);
 
 591                                 if (log) fprintf(stderr, "duplicate top of stack\n");
 
 597                                 if (log) fprintf(stderr, "pop top of stack\n");
 
 604                                 if (log) fprintf(stderr, "duplicate second in stack\n");
 
 609                                 reg = addressSpace.get8(p);
 
 613                                 if (log) fprintf(stderr, "duplicate %d in stack\n", reg);
 
 621                                 if (log) fprintf(stderr, "swap top of stack\n");
 
 630                                 if (log) fprintf(stderr, "rotate top three of stack\n");
 
 634                                 // pop stack, dereference, push result
 
 636                                 *sp = *((uint64_t*)value);
 
 637                                 if (log) fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t)value);
 
 644                                 if (log) fprintf(stderr, "abs\n");
 
 650                                 if (log) fprintf(stderr, "and\n");
 
 656                                 if (log) fprintf(stderr, "div\n");
 
 662                                 if (log) fprintf(stderr, "minus\n");
 
 668                                 if (log) fprintf(stderr, "module\n");
 
 674                                 if (log) fprintf(stderr, "mul\n");
 
 679                                 if (log) fprintf(stderr, "neg\n");
 
 685                                 if (log) fprintf(stderr, "not\n");
 
 691                                 if (log) fprintf(stderr, "or\n");
 
 697                                 if (log) fprintf(stderr, "plus\n");
 
 700                         case DW_OP_plus_uconst:
 
 701                                 // pop stack, add uelb128 constant, push result
 
 702                                 *sp += addressSpace.getULEB128(p, expressionEnd);
 
 703                                 if (log) fprintf(stderr, "add constant\n");
 
 709                                 if (log) fprintf(stderr, "shift left\n");
 
 715                                 if (log) fprintf(stderr, "shift left\n");
 
 721                                 *sp = svalue >> value;
 
 722                                 if (log) fprintf(stderr, "shift left arithmetric\n");
 
 728                                 if (log) fprintf(stderr, "xor\n");
 
 732                                 svalue = (int16_t)addressSpace.get16(p);
 
 735                                 if (log) fprintf(stderr, "skip %lld\n", (uint64_t)svalue);
 
 739                                 svalue = (int16_t)addressSpace.get16(p);
 
 743                                 if (log) fprintf(stderr, "bra %lld\n", (uint64_t)svalue);
 
 748                                 *sp = (*sp == value);
 
 749                                 if (log) fprintf(stderr, "eq\n");
 
 754                                 *sp = (*sp >= value);
 
 755                                 if (log) fprintf(stderr, "ge\n");
 
 761                                 if (log) fprintf(stderr, "gt\n");
 
 766                                 *sp = (*sp <= value);
 
 767                                 if (log) fprintf(stderr, "le\n");
 
 773                                 if (log) fprintf(stderr, "lt\n");
 
 778                                 *sp = (*sp != value);
 
 779                                 if (log) fprintf(stderr, "ne\n");
 
 814                                 value = opcode - DW_OP_lit0;
 
 816                                 if (log) fprintf(stderr, "push literal 0x%llX\n", (uint64_t)value);
 
 851                                 reg = opcode - DW_OP_reg0;
 
 852                                 *(++sp) = registers.getRegister(reg);
 
 853                                 if (log) fprintf(stderr, "push reg %d\n", reg);
 
 857                                 reg = addressSpace.getULEB128(p, expressionEnd);
 
 858                                 *(++sp) = registers.getRegister(reg);
 
 859                                 if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
 
 894                                 reg = opcode - DW_OP_breg0;
 
 895                                 svalue = addressSpace.getSLEB128(p, expressionEnd);
 
 896                                 *(++sp) = registers.getRegister(reg) + svalue;
 
 897                                 if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
 
 901                                 reg = addressSpace.getULEB128(p, expressionEnd);
 
 902                                 svalue = addressSpace.getSLEB128(p, expressionEnd);
 
 903                                 *(++sp) = registers.getRegister(reg) + svalue;
 
 904                                 if (log) fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t)svalue);
 
 908                                 ABORT("DW_OP_fbreg not implemented");
 
 912                                 ABORT("DW_OP_piece not implemented");
 
 915                         case DW_OP_deref_size:
 
 916                                 // pop stack, dereference, push result
 
 918                                 switch ( addressSpace.get8(p++) ) {
 
 920                                                 value = addressSpace.get8(value);
 
 923                                                 value = addressSpace.get16(value);
 
 926                                                 value = addressSpace.get32(value);
 
 929                                                 value = addressSpace.get64(value);
 
 932                                                 ABORT("DW_OP_deref_size with bad size");
 
 935                                 if (log) fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t)value);
 
 938                         case DW_OP_xderef_size:
 
 940                         case DW_OP_push_object_addres:
 
 945                                 ABORT("dwarf opcode not implemented");
 
 949         if (log) fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t)*sp);
 
 956 //      x86_64 specific functions
 
 959 template <typename A, typename R>
 
 960 int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86_64&) 
 
 962         COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_64_RET_ADDR );
 
 963         return DW_X86_64_RET_ADDR; 
 
 966 template <typename A, typename R>
 
 967 bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86_64&) 
 
 969         return (regNum == DW_X86_64_RET_ADDR); 
 
 972 template <typename A, typename R>
 
 973 typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
 
 974                                                                                 const Registers_x86_64& registers)
 
 976         if ( prolog.cfaRegister != 0 )
 
 977                 return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
 
 978         else if ( prolog.cfaExpression != 0 )
 
 979                 return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
 
 981                 ABORT("getCFA(): unknown location for x86_64 cfa");
 
 986 template <typename A, typename R>
 
 987 compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86_64&) 
 
 989         return UNWIND_X86_64_MODE_DWARF;
 
 992 template <typename A, typename R>
 
 993 compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86&) 
 
 995         return UNWIND_X86_MODE_DWARF;
 
1000 template <typename A, typename R>
 
1001 uint32_t DwarfInstructions<A,R>::getRBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure)
 
1003         if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 32) ) {
 
1007         unsigned int slotIndex = regOffsetFromBaseOffset/8;
 
1010                 case UNW_X86_64_RBX:
 
1011                         return UNWIND_X86_64_REG_RBX << (slotIndex*3);
 
1012                 case UNW_X86_64_R12:
 
1013                         return UNWIND_X86_64_REG_R12 << (slotIndex*3);
 
1014                 case UNW_X86_64_R13:
 
1015                         return UNWIND_X86_64_REG_R13 << (slotIndex*3);
 
1016                 case UNW_X86_64_R14:
 
1017                         return UNWIND_X86_64_REG_R14 << (slotIndex*3);
 
1018                 case UNW_X86_64_R15:
 
1019                         return UNWIND_X86_64_REG_R15 << (slotIndex*3);
 
1029 template <typename A, typename R>
 
1030 compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
1031                                                                                                 const Registers_x86_64& r, const typename CFI_Parser<A>::PrologInfo& prolog,
 
1032                                                                                                 char warningBuffer[1024])
 
1034         warningBuffer[0] = '\0';
 
1036         if ( prolog.registerSavedTwiceInCIE == DW_X86_64_RET_ADDR ) {
 
1037                 warningBuffer[0] = '\0';        // silently disable conversion to compact unwind by linker
 
1038                 return UNWIND_X86_64_MODE_DWARF;
 
1040         // don't create compact unwind info for unsupported dwarf kinds
 
1041         if ( prolog.registerSavedMoreThanOnce ) {
 
1042                 strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
 
1043                 return UNWIND_X86_64_MODE_DWARF;
 
1045         if ( prolog.cfaOffsetWasNegative ) {
 
1046                 strcpy(warningBuffer, "cfa had negative offset (dwarf might contain epilog)");
 
1047                 return UNWIND_X86_64_MODE_DWARF;
 
1049         if ( prolog.spExtraArgSize != 0 ) {
 
1050                 strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
 
1051                 return UNWIND_X86_64_MODE_DWARF;
 
1053         if ( prolog.sameValueUsed ) {
 
1054                 strcpy(warningBuffer, "dwarf uses DW_CFA_same_value");
 
1055                 return UNWIND_X86_64_MODE_DWARF;
 
1058         // figure out which kind of frame this function uses
 
1059         bool standardRBPframe = ( 
 
1060                  (prolog.cfaRegister == UNW_X86_64_RBP) 
 
1061           && (prolog.cfaRegisterOffset == 16)
 
1062           && (prolog.savedRegisters[UNW_X86_64_RBP].location == CFI_Parser<A>::kRegisterInCFA)
 
1063           && (prolog.savedRegisters[UNW_X86_64_RBP].value == -16) );
 
1064         bool standardRSPframe = (prolog.cfaRegister == UNW_X86_64_RSP);
 
1065         if ( !standardRBPframe && !standardRSPframe ) {
 
1066                 // no compact encoding for this
 
1067                 strcpy(warningBuffer, "does not use RBP or RSP based frame");
 
1068                 return UNWIND_X86_64_MODE_DWARF;
 
1071         // scan which registers are saved
 
1072         int saveRegisterCount = 0;
 
1073         bool rbxSaved = false;
 
1074         bool r12Saved = false;
 
1075         bool r13Saved = false;
 
1076         bool r14Saved = false;
 
1077         bool r15Saved = false;
 
1078         bool rbpSaved = false;
 
1079         for (int i=0; i < 64; ++i) {
 
1080                 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
 
1081                         if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) {
 
1082                                 sprintf(warningBuffer, "register %d saved somewhere other than in frame", i);
 
1083                                 return UNWIND_X86_64_MODE_DWARF;
 
1086                                 case UNW_X86_64_RBX:
 
1088                                         ++saveRegisterCount;
 
1090                                 case UNW_X86_64_R12:
 
1092                                         ++saveRegisterCount;
 
1094                                 case UNW_X86_64_R13:
 
1096                                         ++saveRegisterCount;
 
1098                                 case UNW_X86_64_R14:
 
1100                                         ++saveRegisterCount;
 
1102                                 case UNW_X86_64_R15:
 
1104                                         ++saveRegisterCount;
 
1106                                 case UNW_X86_64_RBP:
 
1108                                         ++saveRegisterCount;
 
1110                                 case DW_X86_64_RET_ADDR:
 
1113                                         sprintf(warningBuffer, "non-standard register %d being saved in prolog", i);
 
1114                                         return UNWIND_X86_64_MODE_DWARF;
 
1118         const int64_t cfaOffsetRBX = prolog.savedRegisters[UNW_X86_64_RBX].value;
 
1119         const int64_t cfaOffsetR12 = prolog.savedRegisters[UNW_X86_64_R12].value;
 
1120         const int64_t cfaOffsetR13 = prolog.savedRegisters[UNW_X86_64_R13].value;
 
1121         const int64_t cfaOffsetR14 = prolog.savedRegisters[UNW_X86_64_R14].value;
 
1122         const int64_t cfaOffsetR15 = prolog.savedRegisters[UNW_X86_64_R15].value;
 
1123         const int64_t cfaOffsetRBP = prolog.savedRegisters[UNW_X86_64_RBP].value;
 
1125         // encode standard RBP frames
 
1126         compact_unwind_encoding_t  encoding = 0;
 
1127         if ( standardRBPframe ) {
 
1129                 //              +--------------+   <- CFA
 
1133                 //              +--------------+   <- rbp
 
1137                 //              +--------------+   <- CFA - offset+16
 
1139                 //              +--------------+   <- CFA - offset+8
 
1141                 //              +--------------+   <- CFA - offset
 
1147                 encoding = UNWIND_X86_64_MODE_RBP_FRAME;
 
1149                 // find save location of farthest register from rbp
 
1150                 int furthestCfaOffset = 0;
 
1151                 if ( rbxSaved & (cfaOffsetRBX < furthestCfaOffset) )
 
1152                         furthestCfaOffset = cfaOffsetRBX;
 
1153                 if ( r12Saved & (cfaOffsetR12 < furthestCfaOffset) )
 
1154                         furthestCfaOffset = cfaOffsetR12;
 
1155                 if ( r13Saved & (cfaOffsetR13 < furthestCfaOffset) )
 
1156                         furthestCfaOffset = cfaOffsetR13;
 
1157                 if ( r14Saved & (cfaOffsetR14 < furthestCfaOffset) )
 
1158                         furthestCfaOffset = cfaOffsetR14;
 
1159                 if ( r15Saved & (cfaOffsetR15 < furthestCfaOffset) )
 
1160                         furthestCfaOffset = cfaOffsetR15;
 
1162                 if ( furthestCfaOffset == 0 ) {
 
1163                         // no registers saved, nothing more to encode
 
1167                 // add stack offset to encoding
 
1168                 int rbpOffset = furthestCfaOffset + 16;
 
1169                 int encodedOffset = rbpOffset/(-8);
 
1170                 if ( encodedOffset > 255 ) {
 
1171                         strcpy(warningBuffer, "offset of saved registers too far to encode");
 
1172                         return UNWIND_X86_64_MODE_DWARF;
 
1174                 encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_64_RBP_FRAME_OFFSET));
 
1176                 // add register saved from each stack location
 
1177                 bool encodingFailure = false;
 
1179                         encoding |= getRBPEncodedRegister(UNW_X86_64_RBX, cfaOffsetRBX - furthestCfaOffset, encodingFailure);
 
1181                         encoding |= getRBPEncodedRegister(UNW_X86_64_R12, cfaOffsetR12 - furthestCfaOffset, encodingFailure);
 
1183                         encoding |= getRBPEncodedRegister(UNW_X86_64_R13, cfaOffsetR13 - furthestCfaOffset, encodingFailure);
 
1185                         encoding |= getRBPEncodedRegister(UNW_X86_64_R14, cfaOffsetR14 - furthestCfaOffset, encodingFailure);
 
1187                         encoding |= getRBPEncodedRegister(UNW_X86_64_R15, cfaOffsetR15 - furthestCfaOffset, encodingFailure);
 
1189                 if ( encodingFailure ){
 
1190                         strcpy(warningBuffer, "saved registers not contiguous");
 
1191                         return UNWIND_X86_64_MODE_DWARF;
 
1198                 //              +--------------+   <- CFA
 
1202                 //              +--------------+   <- CFA - 16
 
1204                 //              +--------------+   <- CFA - 24
 
1206                 //              +--------------+   <- CFA - 32
 
1208                 //              +--------------+   <- CFA - 40
 
1210                 //              +--------------+   <- CFA - 48
 
1212                 //              +--------------+   <- CFA - 56
 
1217                 // for RSP based frames we need to encode stack size in unwind info
 
1218                 encoding = UNWIND_X86_64_MODE_STACK_IMMD;
 
1219                 uint64_t stackValue = prolog.cfaRegisterOffset / 8;
 
1220                 uint32_t stackAdjust = 0;
 
1221                 bool immedStackSize = true;
 
1222                 const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_64_FRAMELESS_STACK_SIZE);
 
1223                 if ( stackValue > stackMaxImmedValue ) {
 
1224                         // stack size is too big to fit as an immediate value, so encode offset of subq instruction in function
 
1225                         if      ( prolog.codeOffsetAtStackDecrement == 0 ) {
 
1226                                 strcpy(warningBuffer, "stack size is large but stack subq instruction not found");
 
1227                                 return UNWIND_X86_64_MODE_DWARF;
 
1229                         pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4;
 
1233                                 uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
 
1234                                 stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/8;
 
1238                                 strcpy(warningBuffer, "stack size is large but stack subq instruction not found");
 
1239                                 return UNWIND_X86_64_MODE_DWARF;
 
1242                         stackValue = functionContentAdjustStackIns - funcAddr;
 
1243                         immedStackSize = false;
 
1244                         if ( stackAdjust > 7 ) {
 
1245                                 strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size");
 
1246                                 return UNWIND_X86_64_MODE_DWARF;
 
1248                         encoding = UNWIND_X86_64_MODE_STACK_IND;
 
1252                 // validate that saved registers are all within 6 slots abutting return address
 
1254                 for (int i=0; i < 6;++i)
 
1257                         if ( cfaOffsetR15 < -56 ) {
 
1258                                 strcpy(warningBuffer, "r15 is saved too far from return address");
 
1259                                 return UNWIND_X86_64_MODE_DWARF;
 
1261                         registers[(cfaOffsetR15+56)/8] = UNWIND_X86_64_REG_R15;
 
1264                         if ( cfaOffsetR14 < -56 ) {
 
1265                                 strcpy(warningBuffer, "r14 is saved too far from return address");
 
1266                                 return UNWIND_X86_64_MODE_DWARF;
 
1268                         registers[(cfaOffsetR14+56)/8] = UNWIND_X86_64_REG_R14;
 
1271                         if ( cfaOffsetR13 < -56 ) {
 
1272                                 strcpy(warningBuffer, "r13 is saved too far from return address");
 
1273                                 return UNWIND_X86_64_MODE_DWARF;
 
1275                         registers[(cfaOffsetR13+56)/8] = UNWIND_X86_64_REG_R13;
 
1278                         if ( cfaOffsetR12 < -56 ) {
 
1279                                 strcpy(warningBuffer, "r12 is saved too far from return address");
 
1280                                 return UNWIND_X86_64_MODE_DWARF;
 
1282                         registers[(cfaOffsetR12+56)/8] = UNWIND_X86_64_REG_R12;
 
1285                         if ( cfaOffsetRBX < -56 ) {
 
1286                                 strcpy(warningBuffer, "rbx is saved too far from return address");
 
1287                                 return UNWIND_X86_64_MODE_DWARF;
 
1289                         registers[(cfaOffsetRBX+56)/8] = UNWIND_X86_64_REG_RBX;
 
1292                         if ( cfaOffsetRBP < -56 ) {
 
1293                                 strcpy(warningBuffer, "rbp is saved too far from return address");
 
1294                                 return UNWIND_X86_64_MODE_DWARF;
 
1296                         registers[(cfaOffsetRBP+56)/8] = UNWIND_X86_64_REG_RBP;
 
1299                 // validate that saved registers are contiguous and abut return address on stack
 
1300                 for (int i=0; i < saveRegisterCount; ++i) {
 
1301                         if ( registers[5-i] == 0 ) {
 
1302                                 strcpy(warningBuffer, "registers not save contiguously in stack");
 
1303                                 return UNWIND_X86_64_MODE_DWARF;
 
1307                 // encode register permutation
 
1308                 // the 10-bits are encoded differently depending on the number of registers saved
 
1310                 for (int i=6-saveRegisterCount; i < 6; ++i) {
 
1312                         for (int j=6-saveRegisterCount; j < i; ++j) {
 
1313                                 if ( registers[j] < registers[i] )
 
1316                         renumregs[i] = registers[i] - countless -1;
 
1318                 uint32_t permutationEncoding = 0;
 
1319                 switch ( saveRegisterCount ) {
 
1321                                 permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
 
1324                                 permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
 
1327                                 permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
 
1330                                 permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
 
1333                                 permutationEncoding |= (5*renumregs[4] + renumregs[5]);
 
1336                                 permutationEncoding |= (renumregs[5]);
 
1340                 encoding |= (stackValue << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_SIZE));
 
1341                 encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_ADJUST));
 
1342                 encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT));
 
1343                 encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION));
 
1352 //      x86 specific functions
 
1354 template <typename A, typename R>
 
1355 int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86&) 
 
1357         COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_RET_ADDR );
 
1358         return DW_X86_RET_ADDR; 
 
1361 template <typename A, typename R>
 
1362 bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86&) 
 
1364         return (regNum == DW_X86_RET_ADDR); 
 
1367 template <typename A, typename R>
 
1368 typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
 
1369                                                                                 const Registers_x86& registers)
 
1371         if ( prolog.cfaRegister != 0 )
 
1372                 return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
 
1373         else if ( prolog.cfaExpression != 0 )
 
1374                 return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
 
1376                 ABORT("getCFA(): unknown location for x86 cfa");
 
1383 template <typename A, typename R>
 
1384 uint32_t DwarfInstructions<A,R>::getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure)
 
1386         if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 16) ) {
 
1390         unsigned int slotIndex = regOffsetFromBaseOffset/4;
 
1394                         return UNWIND_X86_REG_EBX << (slotIndex*3);
 
1396                         return UNWIND_X86_REG_ECX << (slotIndex*3);
 
1398                         return UNWIND_X86_REG_EDX << (slotIndex*3);
 
1400                         return UNWIND_X86_REG_EDI << (slotIndex*3);
 
1402                         return UNWIND_X86_REG_ESI << (slotIndex*3);
 
1410 template <typename A, typename R>
 
1411 compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
1412                                                                                                 const Registers_x86& r, const typename CFI_Parser<A>::PrologInfo& prolog,
 
1413                                                                                                 char warningBuffer[1024])
 
1415         warningBuffer[0] = '\0';
 
1417         if ( prolog.registerSavedTwiceInCIE == DW_X86_RET_ADDR ) {
 
1418                 warningBuffer[0] = '\0';        // silently disable conversion to compact unwind by linker
 
1419                 return UNWIND_X86_64_MODE_DWARF;
 
1421         // don't create compact unwind info for unsupported dwarf kinds
 
1422         if ( prolog.registerSavedMoreThanOnce ) {
 
1423                 strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
 
1424                 return UNWIND_X86_MODE_DWARF;
 
1426         if ( prolog.spExtraArgSize != 0 ) {
 
1427                 strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
 
1428                 return UNWIND_X86_MODE_DWARF;
 
1430         if ( prolog.sameValueUsed ) {
 
1431                 strcpy(warningBuffer, "dwarf uses DW_CFA_same_value");
 
1432                 return UNWIND_X86_MODE_DWARF;
 
1435         // figure out which kind of frame this function uses
 
1436         bool standardEBPframe = ( 
 
1437                  (prolog.cfaRegister == UNW_X86_EBP) 
 
1438           && (prolog.cfaRegisterOffset == 8)
 
1439           && (prolog.savedRegisters[UNW_X86_EBP].location == CFI_Parser<A>::kRegisterInCFA)
 
1440           && (prolog.savedRegisters[UNW_X86_EBP].value == -8) );
 
1441         bool standardESPframe = (prolog.cfaRegister == UNW_X86_ESP);
 
1442         if ( !standardEBPframe && !standardESPframe ) {
 
1443                 // no compact encoding for this
 
1444                 strcpy(warningBuffer, "does not use EBP or ESP based frame");
 
1445                 return UNWIND_X86_MODE_DWARF;
 
1448         // scan which registers are saved
 
1449         int saveRegisterCount = 0;
 
1450         bool ebxSaved = false;
 
1451         bool ecxSaved = false;
 
1452         bool edxSaved = false;
 
1453         bool esiSaved = false;
 
1454         bool ediSaved = false;
 
1455         bool ebpSaved = false;
 
1456         for (int i=0; i < 64; ++i) {
 
1457                 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
 
1458                         if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) {
 
1459                                 sprintf(warningBuffer, "register %d saved somewhere other than in frame", i);
 
1460                                 return UNWIND_X86_MODE_DWARF;
 
1465                                         ++saveRegisterCount;
 
1469                                         ++saveRegisterCount;
 
1473                                         ++saveRegisterCount;
 
1477                                         ++saveRegisterCount;
 
1481                                         ++saveRegisterCount;
 
1485                                         ++saveRegisterCount;
 
1487                                 case DW_X86_RET_ADDR:
 
1490                                         sprintf(warningBuffer, "non-standard register %d being saved in prolog", i);
 
1491                                         return UNWIND_X86_MODE_DWARF;
 
1495         const int32_t cfaOffsetEBX = prolog.savedRegisters[UNW_X86_EBX].value;
 
1496         const int32_t cfaOffsetECX = prolog.savedRegisters[UNW_X86_ECX].value;
 
1497         const int32_t cfaOffsetEDX = prolog.savedRegisters[UNW_X86_EDX].value;
 
1498         const int32_t cfaOffsetEDI = prolog.savedRegisters[UNW_X86_EDI].value;
 
1499         const int32_t cfaOffsetESI = prolog.savedRegisters[UNW_X86_ESI].value;
 
1500         const int32_t cfaOffsetEBP = prolog.savedRegisters[UNW_X86_EBP].value;
 
1502         // encode standard RBP frames
 
1503         compact_unwind_encoding_t  encoding = 0;
 
1504         if ( standardEBPframe ) {
 
1506                 //              +--------------+   <- CFA
 
1510                 //              +--------------+   <- ebp
 
1514                 //              +--------------+   <- CFA - offset+8
 
1516                 //              +--------------+   <- CFA - offset+e
 
1518                 //              +--------------+   <- CFA - offset
 
1524                 encoding = UNWIND_X86_MODE_EBP_FRAME;
 
1526                 // find save location of farthest register from ebp
 
1527                 int furthestCfaOffset = 0;
 
1528                 if ( ebxSaved & (cfaOffsetEBX < furthestCfaOffset) )
 
1529                         furthestCfaOffset = cfaOffsetEBX;
 
1530                 if ( ecxSaved & (cfaOffsetECX < furthestCfaOffset) )
 
1531                         furthestCfaOffset = cfaOffsetECX;
 
1532                 if ( edxSaved & (cfaOffsetEDX < furthestCfaOffset) )
 
1533                         furthestCfaOffset = cfaOffsetEDX;
 
1534                 if ( ediSaved & (cfaOffsetEDI < furthestCfaOffset) )
 
1535                         furthestCfaOffset = cfaOffsetEDI;
 
1536                 if ( esiSaved & (cfaOffsetESI < furthestCfaOffset) )
 
1537                         furthestCfaOffset = cfaOffsetESI;
 
1539                 if ( furthestCfaOffset == 0 ) {
 
1540                         // no registers saved, nothing more to encode
 
1544                 // add stack offset to encoding
 
1545                 int ebpOffset = furthestCfaOffset + 8;
 
1546                 int encodedOffset = ebpOffset/(-4);
 
1547                 if ( encodedOffset > 255 ) {
 
1548                         strcpy(warningBuffer, "offset of saved registers too far to encode");
 
1549                         return UNWIND_X86_MODE_DWARF;
 
1551                 encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_EBP_FRAME_OFFSET));
 
1553                 // add register saved from each stack location
 
1554                 bool encodingFailure = false;
 
1556                         encoding |= getEBPEncodedRegister(UNW_X86_EBX, cfaOffsetEBX - furthestCfaOffset, encodingFailure);
 
1558                         encoding |= getEBPEncodedRegister(UNW_X86_ECX, cfaOffsetECX - furthestCfaOffset, encodingFailure);
 
1560                         encoding |= getEBPEncodedRegister(UNW_X86_EDX, cfaOffsetEDX - furthestCfaOffset, encodingFailure);
 
1562                         encoding |= getEBPEncodedRegister(UNW_X86_EDI, cfaOffsetEDI - furthestCfaOffset, encodingFailure);
 
1564                         encoding |= getEBPEncodedRegister(UNW_X86_ESI, cfaOffsetESI - furthestCfaOffset, encodingFailure);
 
1566                 if ( encodingFailure ){
 
1567                         strcpy(warningBuffer, "saved registers not contiguous");
 
1568                         return UNWIND_X86_MODE_DWARF;
 
1575                 //              +--------------+   <- CFA
 
1579                 //              +--------------+   <- CFA - 8
 
1581                 //              +--------------+   <- CFA - 12
 
1583                 //              +--------------+   <- CFA - 16
 
1585                 //              +--------------+   <- CFA - 20
 
1587                 //              +--------------+   <- CFA - 24
 
1589                 //              +--------------+   <- CFA - 28
 
1594                 // for ESP based frames we need to encode stack size in unwind info
 
1595                 encoding = UNWIND_X86_MODE_STACK_IMMD;
 
1596                 uint64_t stackValue = prolog.cfaRegisterOffset / 4;
 
1597                 uint32_t stackAdjust = 0;
 
1598                 bool immedStackSize = true;
 
1599                 const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_FRAMELESS_STACK_SIZE);
 
1600                 if ( stackValue > stackMaxImmedValue ) {
 
1601                         // stack size is too big to fit as an immediate value, so encode offset of subq instruction in function
 
1602                         pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4;                
 
1606                 uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
 
1607                 stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/4;
 
1611                                 strcpy(warningBuffer, "stack size is large but stack subl instruction not found");
 
1612                                 return UNWIND_X86_MODE_DWARF;
 
1615                         stackValue = functionContentAdjustStackIns - funcAddr;
 
1616                         immedStackSize = false;
 
1617                         if ( stackAdjust > 7 ) {
 
1618                                 strcpy(warningBuffer, "stack subl instruction is too different from dwarf stack size");
 
1619                                 return UNWIND_X86_MODE_DWARF;
 
1621                         encoding = UNWIND_X86_MODE_STACK_IND;
 
1625                 // validate that saved registers are all within 6 slots abutting return address
 
1627                 for (int i=0; i < 6;++i)
 
1630                         if ( cfaOffsetEBX < -28 ) {
 
1631                                 strcpy(warningBuffer, "ebx is saved too far from return address");
 
1632                                 return UNWIND_X86_MODE_DWARF;
 
1634                         registers[(cfaOffsetEBX+28)/4] = UNWIND_X86_REG_EBX;
 
1637                         if ( cfaOffsetECX < -28 ) {
 
1638                                 strcpy(warningBuffer, "ecx is saved too far from return address");
 
1639                                 return UNWIND_X86_MODE_DWARF;
 
1641                         registers[(cfaOffsetECX+28)/4] = UNWIND_X86_REG_ECX;
 
1644                         if ( cfaOffsetEDX < -28 ) {
 
1645                                 strcpy(warningBuffer, "edx is saved too far from return address");
 
1646                                 return UNWIND_X86_MODE_DWARF;
 
1648                         registers[(cfaOffsetEDX+28)/4] = UNWIND_X86_REG_EDX;
 
1651                         if ( cfaOffsetEDI < -28 ) {
 
1652                                 strcpy(warningBuffer, "edi is saved too far from return address");
 
1653                                 return UNWIND_X86_MODE_DWARF;
 
1655                         registers[(cfaOffsetEDI+28)/4] = UNWIND_X86_REG_EDI;
 
1658                         if ( cfaOffsetESI < -28 ) {
 
1659                                 strcpy(warningBuffer, "esi is saved too far from return address");
 
1660                                 return UNWIND_X86_MODE_DWARF;
 
1662                         registers[(cfaOffsetESI+28)/4] = UNWIND_X86_REG_ESI;
 
1665                         if ( cfaOffsetEBP < -28 ) {
 
1666                                 strcpy(warningBuffer, "ebp is saved too far from return address");
 
1667                                 return UNWIND_X86_MODE_DWARF;
 
1669                         registers[(cfaOffsetEBP+28)/4] = UNWIND_X86_REG_EBP;
 
1672                 // validate that saved registers are contiguous and abut return address on stack
 
1673                 for (int i=0; i < saveRegisterCount; ++i) {
 
1674                         if ( registers[5-i] == 0 ) {
 
1675                                 strcpy(warningBuffer, "registers not save contiguously in stack");
 
1676                                 return UNWIND_X86_MODE_DWARF;
 
1680                 // encode register permutation
 
1681                 // the 10-bits are encoded differently depending on the number of registers saved
 
1683                 for (int i=6-saveRegisterCount; i < 6; ++i) {
 
1685                         for (int j=6-saveRegisterCount; j < i; ++j) {
 
1686                                 if ( registers[j] < registers[i] )
 
1689                         renumregs[i] = registers[i] - countless -1;
 
1691                 uint32_t permutationEncoding = 0;
 
1692                 switch ( saveRegisterCount ) {
 
1694                                 permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
 
1697                                 permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
 
1700                                 permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
 
1703                                 permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
 
1706                                 permutationEncoding |= (5*renumregs[4] + renumregs[5]);
 
1709                                 permutationEncoding |= (renumregs[5]);
 
1713                 encoding |= (stackValue << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_SIZE));
 
1714                 encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_ADJUST));
 
1715                 encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_COUNT));
 
1716                 encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION));
 
1728 //      ppc specific functions
 
1730 template <typename A, typename R>
 
1731 int DwarfInstructions<A,R>::lastRestoreReg(const Registers_ppc&) 
 
1733         COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)UNW_PPC_SPEFSCR );
 
1734         return UNW_PPC_SPEFSCR; 
 
1737 template <typename A, typename R>
 
1738 bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_ppc&) 
 
1740         return (regNum == UNW_PPC_LR); 
 
1743 template <typename A, typename R>
 
1744 typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
 
1745                                                                                 const Registers_ppc& registers)
 
1747         if ( prolog.cfaRegister != 0 )
 
1748                 return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
 
1749         else if ( prolog.cfaExpression != 0 )
 
1750                 return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
 
1752                 ABORT("getCFA(): unknown location for ppc cfa");
 
1756 template <typename A, typename R>
 
1757 compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_ppc&) 
 
1759         return UNWIND_X86_MODE_DWARF;
 
1763 template <typename A, typename R>
 
1764 compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
1765                                                                                                 const Registers_ppc& r, const typename CFI_Parser<A>::PrologInfo& prolog,
 
1766                                                                                                 char warningBuffer[1024])
 
1768         warningBuffer[0] = '\0';
 
1769         return UNWIND_X86_MODE_DWARF;
 
1775 // arm64 specific functions
 
1778 template <typename A, typename R>
 
1779 compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_arm64&) 
 
1781         return UNWIND_ARM64_MODE_DWARF;
 
1784 template <typename A, typename R>
 
1785 bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_arm64&) 
 
1787         return (regNum == UNW_ARM64_LR); 
 
1790 template <typename A, typename R>
 
1791 int DwarfInstructions<A,R>::lastRestoreReg(const Registers_arm64&) 
 
1793         COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)UNW_ARM64_D31 );
 
1794         return UNW_ARM64_D31; 
 
1798 template <typename A, typename R>
 
1799 typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, 
 
1800                                                                                const Registers_arm64& registers)
 
1802         if ( prolog.cfaRegister != 0 )
 
1803                 return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
 
1805                 ABORT("getCFA(): unsupported location for arm64 cfa");
 
1808 template <typename A, typename R>
 
1809 bool DwarfInstructions<A,R>::checkRegisterPair(uint32_t reg, const typename CFI_Parser<A>::PrologInfo& prolog,
 
1810                                                                                                 int& offset, char warningBuffer[1024])
 
1812         if ( (prolog.savedRegisters[reg].location != CFI_Parser<A>::kRegisterUnused)
 
1813           || (prolog.savedRegisters[reg+1].location != CFI_Parser<A>::kRegisterUnused) ) {
 
1814                 if ( prolog.savedRegisters[reg].location != CFI_Parser<A>::kRegisterInCFA ) {
 
1815                         sprintf(warningBuffer, "register %d saved somewhere other than in frame", reg);
 
1818                 if ( prolog.savedRegisters[reg+1].location != CFI_Parser<A>::kRegisterInCFA ) {
 
1819                         sprintf(warningBuffer, "register %d saved somewhere other than in frame", reg+1);
 
1822                 if ( prolog.savedRegisters[reg].value != prolog.savedRegisters[reg+1].value + 8 ) {
 
1823                         sprintf(warningBuffer, "registers %d and %d not saved contiguously in frame", reg, reg+1);
 
1826                 if ( prolog.savedRegisters[reg].value != offset ) {
 
1827                         sprintf(warningBuffer, "registers %d not saved contiguously in frame", reg);
 
1837 template <typename A, typename R>
 
1838 compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
 
1839                                                                                                 const Registers_arm64& r, const typename CFI_Parser<A>::PrologInfo& prolog,
 
1840                                                                                                 char warningBuffer[1024])
 
1842         warningBuffer[0] = '\0';
 
1844         if ( prolog.registerSavedTwiceInCIE == UNW_ARM64_LR ) {
 
1845                 warningBuffer[0] = '\0';        // silently disable conversion to compact unwind by linker
 
1846                 return UNWIND_ARM64_MODE_DWARF;
 
1848         // don't create compact unwind info for unsupported dwarf kinds
 
1849         if ( prolog.registerSavedMoreThanOnce ) {
 
1850                 strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
 
1851                 return UNWIND_ARM64_MODE_DWARF;
 
1853         if ( prolog.spExtraArgSize != 0 ) {
 
1854                 strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
 
1855                 return UNWIND_ARM64_MODE_DWARF;
 
1857         if ( prolog.sameValueUsed ) {
 
1858                 strcpy(warningBuffer, "dwarf uses DW_CFA_same_value");
 
1859                 return UNWIND_ARM64_MODE_DWARF;
 
1862         compact_unwind_encoding_t encoding = 0;
 
1865         // figure out which kind of frame this function uses
 
1866         bool standardFPframe = ( 
 
1867                  (prolog.cfaRegister == UNW_ARM64_FP) 
 
1868           && (prolog.cfaRegisterOffset == 16)
 
1869           && (prolog.savedRegisters[UNW_ARM64_FP].location == CFI_Parser<A>::kRegisterInCFA)
 
1870           && (prolog.savedRegisters[UNW_ARM64_FP].value == -16) 
 
1871           && (prolog.savedRegisters[UNW_ARM64_LR].location == CFI_Parser<A>::kRegisterInCFA)
 
1872           && (prolog.savedRegisters[UNW_ARM64_LR].value == -8) );
 
1874         bool standardFrameless = ( prolog.cfaRegister == UNW_ARM64_SP );
 
1876         if ( standardFrameless ) {
 
1877                 // verify enough space for registers saved
 
1879                 for (int i=0; i < 96; ++i) {
 
1880                         if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) 
 
1883                 if ( count * 8 > prolog.cfaRegisterOffset ) {
 
1884                         strcpy(warningBuffer, "saved registers do not fit in stack size");
 
1885                         return UNWIND_ARM64_MODE_DWARF;
 
1887                 if ( (prolog.cfaRegisterOffset % 16) != 0 ) {
 
1888                         strcpy(warningBuffer, "stack size is not 16-byte multiple");
 
1889                         return UNWIND_ARM64_MODE_DWARF;
 
1891                 const int32_t maxStack = (UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK >> __builtin_ctz(UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK));
 
1892                 if ( (prolog.cfaRegisterOffset / 16) > maxStack ) {
 
1893                         strcpy(warningBuffer, "stack size is too large for frameless function");
 
1894                         return UNWIND_ARM64_MODE_DWARF;
 
1896                 encoding = UNWIND_ARM64_MODE_FRAMELESS | ((prolog.cfaRegisterOffset/16) << __builtin_ctz(UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK));
 
1899         else if ( standardFPframe  ) {
 
1900                 encoding = UNWIND_ARM64_MODE_FRAME;
 
1904                 // no compact encoding for this
 
1905                 strcpy(warningBuffer, "does not use standard frame");
 
1906                 return UNWIND_ARM64_MODE_DWARF;
 
1909         // make sure no volatile registers are saved
 
1910         for (int i=UNW_ARM64_X0; i < UNW_ARM64_X19; ++i) {
 
1911                 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
 
1912                         sprintf(warningBuffer, "non standard register %d saved in frame", i);
 
1913                         return UNWIND_ARM64_MODE_DWARF;
 
1916         for (int i=UNW_ARM64_SP+1; i < UNW_ARM64_D8; ++i) {
 
1917                 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
 
1918                         sprintf(warningBuffer, "non standard register %d saved in frame", i);
 
1919                         return UNWIND_ARM64_MODE_DWARF;
 
1922         for (int i=UNW_ARM64_D16; i < UNW_ARM64_D31+1; ++i) {
 
1923                 if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
 
1924                         sprintf(warningBuffer, "non standard register %d saved in frame", i);
 
1925                         return UNWIND_ARM64_MODE_DWARF;
 
1930         bool X19_X20_saved = checkRegisterPair(UNW_ARM64_X19, prolog, offset, warningBuffer);
 
1931         bool X21_X22_saved = checkRegisterPair(UNW_ARM64_X21, prolog, offset, warningBuffer);
 
1932         bool X23_X24_saved = checkRegisterPair(UNW_ARM64_X23, prolog, offset, warningBuffer);
 
1933         bool X25_X26_saved = checkRegisterPair(UNW_ARM64_X25, prolog, offset, warningBuffer);
 
1934         bool X27_X28_saved = checkRegisterPair(UNW_ARM64_X27, prolog, offset, warningBuffer);
 
1935         bool D8_D9_saved   = checkRegisterPair(UNW_ARM64_D8,  prolog, offset, warningBuffer);
 
1936         bool D10_D11_saved = checkRegisterPair(UNW_ARM64_D10, prolog, offset, warningBuffer);
 
1937         bool D12_D13_saved = checkRegisterPair(UNW_ARM64_D12, prolog, offset, warningBuffer);
 
1938         bool D14_D15_saved = checkRegisterPair(UNW_ARM64_D14, prolog, offset, warningBuffer);
 
1939         if ( warningBuffer[0] != '\0' )
 
1940                 return UNWIND_ARM64_MODE_DWARF;
 
1942         if ( X19_X20_saved )
 
1943                 encoding |= UNWIND_ARM64_FRAME_X19_X20_PAIR;
 
1944         if ( X21_X22_saved )
 
1945                 encoding |= UNWIND_ARM64_FRAME_X21_X22_PAIR;
 
1946         if ( X23_X24_saved )
 
1947                 encoding |= UNWIND_ARM64_FRAME_X23_X24_PAIR;
 
1948         if ( X25_X26_saved )
 
1949                 encoding |= UNWIND_ARM64_FRAME_X25_X26_PAIR;
 
1950         if ( X27_X28_saved )
 
1951                 encoding |= UNWIND_ARM64_FRAME_X27_X28_PAIR;
 
1953                 encoding |= UNWIND_ARM64_FRAME_D8_D9_PAIR;
 
1954         if ( D10_D11_saved )
 
1955                 encoding |= UNWIND_ARM64_FRAME_D10_D11_PAIR;
 
1956         if ( D12_D13_saved )
 
1957                 encoding |= UNWIND_ARM64_FRAME_D12_D13_PAIR;
 
1958         if ( D14_D15_saved )
 
1959                 encoding |= UNWIND_ARM64_FRAME_D14_D15_PAIR;
 
1965 } // namespace libunwind
 
1968 #endif // __DWARF_INSTRUCTIONS_HPP__