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
54namespace libunwind {
55
56///
57/// Used by linker when parsing __eh_frame section
58///
59template <typename A>
60struct CFI_Reference {
61	typedef typename A::pint_t		pint_t;
62	uint8_t		encodingOfTargetAddress;
63	uint32_t	offsetInCFI;
64	pint_t		targetAddress;
65};
66template <typename A>
67struct 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
85typedef void (*WarnFunc)(void* ref, uint64_t funcAddr, const char* msg);
86
87///
88/// DwarfInstructions maps abtract dwarf unwind instructions to a particular architecture
89///
90template <typename A, typename R>
91class DwarfInstructions
92{
93public:
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
107private:
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
160template <typename A, typename R>
161const 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
280template <typename A, typename R>
281compact_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
311template <typename A, typename R>
312typename 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
336template <typename A, typename R>
337double 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
357template <typename A, typename R>
358v128 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
379template <typename A, typename R>
380int 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
427template <typename A, typename R>
428typename 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
917template <typename A, typename R>
918int 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
924template <typename A, typename R>
925bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86_64&)
926{
927	return (regNum == DW_X86_64_RET_ADDR);
928}
929
930template <typename A, typename R>
931typename 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
944template <typename A, typename R>
945compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86_64&)
946{
947	return UNWIND_X86_64_MODE_DWARF;
948}
949
950template <typename A, typename R>
951compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_x86&)
952{
953	return UNWIND_X86_MODE_DWARF;
954}
955
956
957
958template <typename A, typename R>
959uint32_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
987template <typename A, typename R>
988compact_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        #if __EXCEPTIONS
1189			try {
1190        #endif
1191				uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
1192				stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/8;
1193        #if __EXCEPTIONS
1194			}
1195			catch (...) {
1196				strcpy(warningBuffer, "stack size is large but stack subq instruction not found");
1197				return UNWIND_X86_64_MODE_DWARF;
1198			}
1199        #endif
1200			stackValue = functionContentAdjustStackIns - funcAddr;
1201			immedStackSize = false;
1202			if ( stackAdjust > 7 ) {
1203				strcpy(warningBuffer, "stack subq instruction is too different from dwarf stack size");
1204				return UNWIND_X86_64_MODE_DWARF;
1205			}
1206			encoding = UNWIND_X86_64_MODE_STACK_IND;
1207		}
1208
1209
1210		// validate that saved registers are all within 6 slots abutting return address
1211		int registers[6];
1212		for (int i=0; i < 6;++i)
1213			registers[i] = 0;
1214		if ( r15Saved ) {
1215			if ( cfaOffsetR15 < -56 ) {
1216				strcpy(warningBuffer, "r15 is saved too far from return address");
1217				return UNWIND_X86_64_MODE_DWARF;
1218			}
1219			registers[(cfaOffsetR15+56)/8] = UNWIND_X86_64_REG_R15;
1220		}
1221		if ( r14Saved ) {
1222			if ( cfaOffsetR14 < -56 ) {
1223				strcpy(warningBuffer, "r14 is saved too far from return address");
1224				return UNWIND_X86_64_MODE_DWARF;
1225			}
1226			registers[(cfaOffsetR14+56)/8] = UNWIND_X86_64_REG_R14;
1227		}
1228		if ( r13Saved ) {
1229			if ( cfaOffsetR13 < -56 ) {
1230				strcpy(warningBuffer, "r13 is saved too far from return address");
1231				return UNWIND_X86_64_MODE_DWARF;
1232			}
1233			registers[(cfaOffsetR13+56)/8] = UNWIND_X86_64_REG_R13;
1234		}
1235		if ( r12Saved ) {
1236			if ( cfaOffsetR12 < -56 ) {
1237				strcpy(warningBuffer, "r12 is saved too far from return address");
1238				return UNWIND_X86_64_MODE_DWARF;
1239			}
1240			registers[(cfaOffsetR12+56)/8] = UNWIND_X86_64_REG_R12;
1241		}
1242		if ( rbxSaved ) {
1243			if ( cfaOffsetRBX < -56 ) {
1244				strcpy(warningBuffer, "rbx is saved too far from return address");
1245				return UNWIND_X86_64_MODE_DWARF;
1246			}
1247			registers[(cfaOffsetRBX+56)/8] = UNWIND_X86_64_REG_RBX;
1248		}
1249		if ( rbpSaved ) {
1250			if ( cfaOffsetRBP < -56 ) {
1251				strcpy(warningBuffer, "rbp is saved too far from return address");
1252				return UNWIND_X86_64_MODE_DWARF;
1253			}
1254			registers[(cfaOffsetRBP+56)/8] = UNWIND_X86_64_REG_RBP;
1255		}
1256
1257		// validate that saved registers are contiguous and abut return address on stack
1258		for (int i=0; i < saveRegisterCount; ++i) {
1259			if ( registers[5-i] == 0 ) {
1260				strcpy(warningBuffer, "registers not save contiguously in stack");
1261				return UNWIND_X86_64_MODE_DWARF;
1262			}
1263		}
1264
1265		// encode register permutation
1266		// the 10-bits are encoded differently depending on the number of registers saved
1267		int renumregs[6];
1268		for (int i=6-saveRegisterCount; i < 6; ++i) {
1269			int countless = 0;
1270			for (int j=6-saveRegisterCount; j < i; ++j) {
1271				if ( registers[j] < registers[i] )
1272					++countless;
1273			}
1274			renumregs[i] = registers[i] - countless -1;
1275		}
1276		uint32_t permutationEncoding = 0;
1277		switch ( saveRegisterCount ) {
1278			case 6:
1279				permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
1280				break;
1281			case 5:
1282				permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
1283				break;
1284			case 4:
1285				permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
1286				break;
1287			case 3:
1288				permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
1289				break;
1290			case 2:
1291				permutationEncoding |= (5*renumregs[4] + renumregs[5]);
1292				break;
1293			case 1:
1294				permutationEncoding |= (renumregs[5]);
1295				break;
1296		}
1297
1298		encoding |= (stackValue << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_SIZE));
1299		encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_ADJUST));
1300		encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT));
1301		encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION));
1302		return encoding;
1303	}
1304}
1305
1306
1307
1308
1309//
1310//	x86 specific functions
1311//
1312template <typename A, typename R>
1313int DwarfInstructions<A,R>::lastRestoreReg(const Registers_x86&)
1314{
1315	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)DW_X86_RET_ADDR );
1316	return DW_X86_RET_ADDR;
1317}
1318
1319template <typename A, typename R>
1320bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_x86&)
1321{
1322	return (regNum == DW_X86_RET_ADDR);
1323}
1324
1325template <typename A, typename R>
1326typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog,
1327										const Registers_x86& registers)
1328{
1329	if ( prolog.cfaRegister != 0 )
1330		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
1331	else if ( prolog.cfaExpression != 0 )
1332		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
1333	else
1334		ABORT("getCFA(): unknown location for x86 cfa");
1335}
1336
1337
1338
1339
1340
1341template <typename A, typename R>
1342uint32_t DwarfInstructions<A,R>::getEBPEncodedRegister(uint32_t reg, int32_t regOffsetFromBaseOffset, bool& failure)
1343{
1344	if ( (regOffsetFromBaseOffset < 0) || (regOffsetFromBaseOffset > 16) ) {
1345		failure = true;
1346		return 0;
1347	}
1348	unsigned int slotIndex = regOffsetFromBaseOffset/4;
1349
1350	switch ( reg ) {
1351		case UNW_X86_EBX:
1352			return UNWIND_X86_REG_EBX << (slotIndex*3);
1353		case UNW_X86_ECX:
1354			return UNWIND_X86_REG_ECX << (slotIndex*3);
1355		case UNW_X86_EDX:
1356			return UNWIND_X86_REG_EDX << (slotIndex*3);
1357		case UNW_X86_EDI:
1358			return UNWIND_X86_REG_EDI << (slotIndex*3);
1359		case UNW_X86_ESI:
1360			return UNWIND_X86_REG_ESI << (slotIndex*3);
1361	}
1362
1363	// invalid register
1364	failure = true;
1365	return 0;
1366}
1367
1368template <typename A, typename R>
1369compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
1370												const Registers_x86& r, const typename CFI_Parser<A>::PrologInfo& prolog,
1371												char warningBuffer[1024])
1372{
1373	warningBuffer[0] = '\0';
1374
1375	if ( prolog.registerSavedTwiceInCIE == DW_X86_RET_ADDR ) {
1376		warningBuffer[0] = '\0';	// silently disable conversion to compact unwind by linker
1377		return UNWIND_X86_64_MODE_DWARF;
1378	}
1379	// don't create compact unwind info for unsupported dwarf kinds
1380	if ( prolog.registerSavedMoreThanOnce ) {
1381		strcpy(warningBuffer, "register saved more than once (might be shrink wrap)");
1382		return UNWIND_X86_MODE_DWARF;
1383	}
1384	if ( prolog.spExtraArgSize != 0 ) {
1385		strcpy(warningBuffer, "dwarf uses DW_CFA_GNU_args_size");
1386		return UNWIND_X86_MODE_DWARF;
1387	}
1388	if ( prolog.sameValueUsed ) {
1389		strcpy(warningBuffer, "dwarf uses DW_CFA_same_value");
1390		return UNWIND_X86_MODE_DWARF;
1391	}
1392
1393	// figure out which kind of frame this function uses
1394	bool standardEBPframe = (
1395		 (prolog.cfaRegister == UNW_X86_EBP)
1396	  && (prolog.cfaRegisterOffset == 8)
1397	  && (prolog.savedRegisters[UNW_X86_EBP].location == CFI_Parser<A>::kRegisterInCFA)
1398	  && (prolog.savedRegisters[UNW_X86_EBP].value == -8) );
1399	bool standardESPframe = (prolog.cfaRegister == UNW_X86_ESP);
1400	if ( !standardEBPframe && !standardESPframe ) {
1401		// no compact encoding for this
1402		strcpy(warningBuffer, "does not use EBP or ESP based frame");
1403		return UNWIND_X86_MODE_DWARF;
1404	}
1405
1406	// scan which registers are saved
1407	int saveRegisterCount = 0;
1408	bool ebxSaved = false;
1409	bool ecxSaved = false;
1410	bool edxSaved = false;
1411	bool esiSaved = false;
1412	bool ediSaved = false;
1413	bool ebpSaved = false;
1414	for (int i=0; i < 64; ++i) {
1415		if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterUnused ) {
1416			if ( prolog.savedRegisters[i].location != CFI_Parser<A>::kRegisterInCFA ) {
1417				sprintf(warningBuffer, "register %d saved somewhere other that in frame", i);
1418				return UNWIND_X86_MODE_DWARF;
1419			}
1420			switch (i) {
1421				case UNW_X86_EBX:
1422					ebxSaved = true;
1423					++saveRegisterCount;
1424					break;
1425				case UNW_X86_ECX:
1426					ecxSaved = true;
1427					++saveRegisterCount;
1428					break;
1429				case UNW_X86_EDX:
1430					edxSaved = true;
1431					++saveRegisterCount;
1432					break;
1433				case UNW_X86_ESI:
1434					esiSaved = true;
1435					++saveRegisterCount;
1436					break;
1437				case UNW_X86_EDI:
1438					ediSaved = true;
1439					++saveRegisterCount;
1440					break;
1441				case UNW_X86_EBP:
1442					ebpSaved = true;
1443					++saveRegisterCount;
1444					break;
1445				case DW_X86_RET_ADDR:
1446					break;
1447				default:
1448					sprintf(warningBuffer, "non-standard register %d being saved in prolog", i);
1449					return UNWIND_X86_MODE_DWARF;
1450			}
1451		}
1452	}
1453	const int32_t cfaOffsetEBX = prolog.savedRegisters[UNW_X86_EBX].value;
1454	const int32_t cfaOffsetECX = prolog.savedRegisters[UNW_X86_ECX].value;
1455	const int32_t cfaOffsetEDX = prolog.savedRegisters[UNW_X86_EDX].value;
1456	const int32_t cfaOffsetEDI = prolog.savedRegisters[UNW_X86_EDI].value;
1457	const int32_t cfaOffsetESI = prolog.savedRegisters[UNW_X86_ESI].value;
1458	const int32_t cfaOffsetEBP = prolog.savedRegisters[UNW_X86_EBP].value;
1459
1460	// encode standard RBP frames
1461	compact_unwind_encoding_t  encoding = 0;
1462	if ( standardEBPframe ) {
1463		//		|              |
1464		//		+--------------+   <- CFA
1465		//		|   ret addr   |
1466		//		+--------------+
1467		//		|     ebp      |
1468		//		+--------------+   <- ebp
1469		//		~              ~
1470		//		+--------------+
1471		//		|  saved reg3  |
1472		//		+--------------+   <- CFA - offset+8
1473		//		|  saved reg2  |
1474		//		+--------------+   <- CFA - offset+e
1475		//		|  saved reg1  |
1476		//		+--------------+   <- CFA - offset
1477		//		|              |
1478		//		+--------------+
1479		//		|              |
1480		//						   <- esp
1481		//
1482		encoding = UNWIND_X86_MODE_EBP_FRAME;
1483
1484		// find save location of farthest register from ebp
1485		int furthestCfaOffset = 0;
1486		if ( ebxSaved & (cfaOffsetEBX < furthestCfaOffset) )
1487			furthestCfaOffset = cfaOffsetEBX;
1488		if ( ecxSaved & (cfaOffsetECX < furthestCfaOffset) )
1489			furthestCfaOffset = cfaOffsetECX;
1490		if ( edxSaved & (cfaOffsetEDX < furthestCfaOffset) )
1491			furthestCfaOffset = cfaOffsetEDX;
1492		if ( ediSaved & (cfaOffsetEDI < furthestCfaOffset) )
1493			furthestCfaOffset = cfaOffsetEDI;
1494		if ( esiSaved & (cfaOffsetESI < furthestCfaOffset) )
1495			furthestCfaOffset = cfaOffsetESI;
1496
1497		if ( furthestCfaOffset == 0 ) {
1498			// no registers saved, nothing more to encode
1499			return encoding;
1500		}
1501
1502		// add stack offset to encoding
1503		int ebpOffset = furthestCfaOffset + 8;
1504		int encodedOffset = ebpOffset/(-4);
1505		if ( encodedOffset > 255 ) {
1506			strcpy(warningBuffer, "offset of saved registers too far to encode");
1507			return UNWIND_X86_MODE_DWARF;
1508		}
1509		encoding |= (encodedOffset << __builtin_ctz(UNWIND_X86_EBP_FRAME_OFFSET));
1510
1511		// add register saved from each stack location
1512		bool encodingFailure = false;
1513		if ( ebxSaved )
1514			encoding |= getEBPEncodedRegister(UNW_X86_EBX, cfaOffsetEBX - furthestCfaOffset, encodingFailure);
1515		if ( ecxSaved )
1516			encoding |= getEBPEncodedRegister(UNW_X86_ECX, cfaOffsetECX - furthestCfaOffset, encodingFailure);
1517		if ( edxSaved )
1518			encoding |= getEBPEncodedRegister(UNW_X86_EDX, cfaOffsetEDX - furthestCfaOffset, encodingFailure);
1519		if ( ediSaved )
1520			encoding |= getEBPEncodedRegister(UNW_X86_EDI, cfaOffsetEDI - furthestCfaOffset, encodingFailure);
1521		if ( esiSaved )
1522			encoding |= getEBPEncodedRegister(UNW_X86_ESI, cfaOffsetESI - furthestCfaOffset, encodingFailure);
1523
1524		if ( encodingFailure ){
1525			strcpy(warningBuffer, "saved registers not contiguous");
1526			return UNWIND_X86_MODE_DWARF;
1527		}
1528
1529		return encoding;
1530	}
1531	else {
1532		//		|              |
1533		//		+--------------+   <- CFA
1534		//		|   ret addr   |
1535		//		+--------------+
1536		//		|  saved reg1  |
1537		//		+--------------+   <- CFA - 8
1538		//		|  saved reg2  |
1539		//		+--------------+   <- CFA - 12
1540		//		|  saved reg3  |
1541		//		+--------------+   <- CFA - 16
1542		//		|  saved reg4  |
1543		//		+--------------+   <- CFA - 20
1544		//		|  saved reg5  |
1545		//		+--------------+   <- CFA - 24
1546		//		|  saved reg6  |
1547		//		+--------------+   <- CFA - 28
1548		//		|              |
1549		//						   <- esp
1550		//
1551
1552		// for ESP based frames we need to encode stack size in unwind info
1553		encoding = UNWIND_X86_MODE_STACK_IMMD;
1554		uint64_t stackValue = prolog.cfaRegisterOffset / 4;
1555		uint32_t stackAdjust = 0;
1556		bool immedStackSize = true;
1557		const uint32_t stackMaxImmedValue = EXTRACT_BITS(0xFFFFFFFF,UNWIND_X86_FRAMELESS_STACK_SIZE);
1558		if ( stackValue > stackMaxImmedValue ) {
1559			// stack size is too big to fit as an immediate value, so encode offset of subq instruction in function
1560			pint_t functionContentAdjustStackIns = funcAddr + prolog.codeOffsetAtStackDecrement - 4;
1561        #if __EXCEPTIONS
1562			try {
1563        #endif
1564                uint32_t stackDecrementInCode = addressSpace.get32(functionContentAdjustStackIns);
1565                stackAdjust = (prolog.cfaRegisterOffset - stackDecrementInCode)/4;
1566        #if __EXCEPTIONS
1567			}
1568			catch (...) {
1569				strcpy(warningBuffer, "stack size is large but stack subl instruction not found");
1570				return UNWIND_X86_MODE_DWARF;
1571			}
1572        #endif
1573			stackValue = functionContentAdjustStackIns - funcAddr;
1574			immedStackSize = false;
1575			if ( stackAdjust > 7 ) {
1576				strcpy(warningBuffer, "stack subl instruction is too different from dwarf stack size");
1577				return UNWIND_X86_MODE_DWARF;
1578			}
1579			encoding = UNWIND_X86_MODE_STACK_IND;
1580		}
1581
1582
1583		// validate that saved registers are all within 6 slots abutting return address
1584		int registers[6];
1585		for (int i=0; i < 6;++i)
1586			registers[i] = 0;
1587		if ( ebxSaved ) {
1588			if ( cfaOffsetEBX < -28 ) {
1589				strcpy(warningBuffer, "ebx is saved too far from return address");
1590				return UNWIND_X86_MODE_DWARF;
1591			}
1592			registers[(cfaOffsetEBX+28)/4] = UNWIND_X86_REG_EBX;
1593		}
1594		if ( ecxSaved ) {
1595			if ( cfaOffsetECX < -28 ) {
1596				strcpy(warningBuffer, "ecx is saved too far from return address");
1597				return UNWIND_X86_MODE_DWARF;
1598			}
1599			registers[(cfaOffsetECX+28)/4] = UNWIND_X86_REG_ECX;
1600		}
1601		if ( edxSaved ) {
1602			if ( cfaOffsetEDX < -28 ) {
1603				strcpy(warningBuffer, "edx is saved too far from return address");
1604				return UNWIND_X86_MODE_DWARF;
1605			}
1606			registers[(cfaOffsetEDX+28)/4] = UNWIND_X86_REG_EDX;
1607		}
1608		if ( ediSaved ) {
1609			if ( cfaOffsetEDI < -28 ) {
1610				strcpy(warningBuffer, "edi is saved too far from return address");
1611				return UNWIND_X86_MODE_DWARF;
1612			}
1613			registers[(cfaOffsetEDI+28)/4] = UNWIND_X86_REG_EDI;
1614		}
1615		if ( esiSaved ) {
1616			if ( cfaOffsetESI < -28 ) {
1617				strcpy(warningBuffer, "esi is saved too far from return address");
1618				return UNWIND_X86_MODE_DWARF;
1619			}
1620			registers[(cfaOffsetESI+28)/4] = UNWIND_X86_REG_ESI;
1621		}
1622		if ( ebpSaved ) {
1623			if ( cfaOffsetEBP < -28 ) {
1624				strcpy(warningBuffer, "ebp is saved too far from return address");
1625				return UNWIND_X86_MODE_DWARF;
1626			}
1627			registers[(cfaOffsetEBP+28)/4] = UNWIND_X86_REG_EBP;
1628		}
1629
1630		// validate that saved registers are contiguous and abut return address on stack
1631		for (int i=0; i < saveRegisterCount; ++i) {
1632			if ( registers[5-i] == 0 ) {
1633				strcpy(warningBuffer, "registers not save contiguously in stack");
1634				return UNWIND_X86_MODE_DWARF;
1635			}
1636		}
1637
1638		// encode register permutation
1639		// the 10-bits are encoded differently depending on the number of registers saved
1640		int renumregs[6];
1641		for (int i=6-saveRegisterCount; i < 6; ++i) {
1642			int countless = 0;
1643			for (int j=6-saveRegisterCount; j < i; ++j) {
1644				if ( registers[j] < registers[i] )
1645					++countless;
1646			}
1647			renumregs[i] = registers[i] - countless -1;
1648		}
1649		uint32_t permutationEncoding = 0;
1650		switch ( saveRegisterCount ) {
1651			case 6:
1652				permutationEncoding |= (120*renumregs[0] + 24*renumregs[1] + 6*renumregs[2] + 2*renumregs[3] + renumregs[4]);
1653				break;
1654			case 5:
1655				permutationEncoding |= (120*renumregs[1] + 24*renumregs[2] + 6*renumregs[3] + 2*renumregs[4] + renumregs[5]);
1656				break;
1657			case 4:
1658				permutationEncoding |= (60*renumregs[2] + 12*renumregs[3] + 3*renumregs[4] + renumregs[5]);
1659				break;
1660			case 3:
1661				permutationEncoding |= (20*renumregs[3] + 4*renumregs[4] + renumregs[5]);
1662				break;
1663			case 2:
1664				permutationEncoding |= (5*renumregs[4] + renumregs[5]);
1665				break;
1666			case 1:
1667				permutationEncoding |= (renumregs[5]);
1668				break;
1669		}
1670
1671		encoding |= (stackValue << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_SIZE));
1672		encoding |= (stackAdjust << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_ADJUST));
1673		encoding |= (saveRegisterCount << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_COUNT));
1674		encoding |= (permutationEncoding << __builtin_ctz(UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION));
1675		return encoding;
1676	}
1677}
1678
1679
1680
1681
1682
1683
1684
1685//
1686//	ppc specific functions
1687//
1688template <typename A, typename R>
1689int DwarfInstructions<A,R>::lastRestoreReg(const Registers_ppc&)
1690{
1691	COMPILE_TIME_ASSERT( (int)CFI_Parser<A>::kMaxRegisterNumber > (int)UNW_PPC_SPEFSCR );
1692	return UNW_PPC_SPEFSCR;
1693}
1694
1695template <typename A, typename R>
1696bool DwarfInstructions<A,R>::isReturnAddressRegister(int regNum, const Registers_ppc&)
1697{
1698	return (regNum == UNW_PPC_LR);
1699}
1700
1701template <typename A, typename R>
1702typename A::pint_t DwarfInstructions<A,R>::getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog,
1703										const Registers_ppc& registers)
1704{
1705	if ( prolog.cfaRegister != 0 )
1706		return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
1707	else if ( prolog.cfaExpression != 0 )
1708		return evaluateExpression(prolog.cfaExpression, addressSpace, registers, 0);
1709	else
1710		ABORT("getCFA(): unknown location for ppc cfa");
1711}
1712
1713
1714template <typename A, typename R>
1715compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_ppc&)
1716{
1717	return UNWIND_X86_MODE_DWARF;
1718}
1719
1720
1721template <typename A, typename R>
1722compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
1723												const Registers_ppc& r, const typename CFI_Parser<A>::PrologInfo& prolog,
1724												char warningBuffer[1024])
1725{
1726	warningBuffer[0] = '\0';
1727	return UNWIND_X86_MODE_DWARF;
1728}
1729
1730
1731
1732
1733} // namespace libunwind
1734
1735
1736#endif // __DWARF_INSTRUCTIONS_HPP__
1737
1738
1739
1740
1741