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