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