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