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