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