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