xref: /illumos-gate/usr/src/lib/libc/amd64/unwind/call_frame_inst.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * interface used by unwind support to query frame descriptor info
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #ifndef _LIBCRUN_
34*7c478bd9Sstevel@tonic-gate #include "synonyms.h"
35*7c478bd9Sstevel@tonic-gate #endif
36*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
37*7c478bd9Sstevel@tonic-gate #include "stack_unwind.h"
38*7c478bd9Sstevel@tonic-gate #include "unwind_context.h"
39*7c478bd9Sstevel@tonic-gate #include "reg_num.h"
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate enum CFA_ops {
42*7c478bd9Sstevel@tonic-gate 	DW_CFA_nop = 0x00,
43*7c478bd9Sstevel@tonic-gate 	DW_CFA_set_loc = 0x01,
44*7c478bd9Sstevel@tonic-gate 	DW_CFA_advance_loc1 = 0x02,
45*7c478bd9Sstevel@tonic-gate 	DW_CFA_advance_loc2 = 0x03,
46*7c478bd9Sstevel@tonic-gate 	DW_CFA_advance_loc4 = 0x04,
47*7c478bd9Sstevel@tonic-gate 	DW_CFA_offset_extended = 0x05,
48*7c478bd9Sstevel@tonic-gate 	DW_CFA_restore_extended = 0x06,
49*7c478bd9Sstevel@tonic-gate 	DW_CFA_undefined = 0x07,
50*7c478bd9Sstevel@tonic-gate 	DW_CFA_same_value = 0x08,
51*7c478bd9Sstevel@tonic-gate 	DW_CFA_register = 0x09,
52*7c478bd9Sstevel@tonic-gate 	DW_CFA_remember_state = 0x0a,
53*7c478bd9Sstevel@tonic-gate 	DW_CFA_restore_state = 0x0b,
54*7c478bd9Sstevel@tonic-gate 	DW_CFA_def_cfa = 0x0c,
55*7c478bd9Sstevel@tonic-gate 	DW_CFA_def_cfa_register = 0x0d,
56*7c478bd9Sstevel@tonic-gate 	DW_CFA_def_cfa_offset = 0x0e,
57*7c478bd9Sstevel@tonic-gate 	DW_CFA_def_cfa_expression = 0x0f,
58*7c478bd9Sstevel@tonic-gate 	DW_CFA_expression = 0x10,
59*7c478bd9Sstevel@tonic-gate 	DW_CFA_offset_extended_sf = 0x11,
60*7c478bd9Sstevel@tonic-gate 	DW_CFA_def_cfa_sf = 0x12,
61*7c478bd9Sstevel@tonic-gate 	DW_CFA_def_cfa_offset_sf = 0x13,
62*7c478bd9Sstevel@tonic-gate 	/* skip 9 values */
63*7c478bd9Sstevel@tonic-gate 	DW_CFA_SUNW_advance_loc = 0x1d,
64*7c478bd9Sstevel@tonic-gate 	DW_CFA_SUNW_offset = 0x1e,
65*7c478bd9Sstevel@tonic-gate 	DW_CFA_SUNW_restore = 0x1f,
66*7c478bd9Sstevel@tonic-gate 	DW_CFA_advance_loc = 0x40,
67*7c478bd9Sstevel@tonic-gate 	DW_CFA_offset = 0x80,
68*7c478bd9Sstevel@tonic-gate 	DW_CFA_restore = 0xc0
69*7c478bd9Sstevel@tonic-gate };
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate struct operation_desc {
72*7c478bd9Sstevel@tonic-gate 	enum operand_desc op1;
73*7c478bd9Sstevel@tonic-gate 	enum operand_desc op2;
74*7c478bd9Sstevel@tonic-gate };
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate struct operation_desc cfa_operations[] = {
77*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},	/* DW_CFA_nop */
78*7c478bd9Sstevel@tonic-gate 	{ADDR, NO_OPR},		/* DW_CFA_set_loc - address */
79*7c478bd9Sstevel@tonic-gate 	{UNUM8, NO_OPR},	/* DW_CFA_advance_loc1 - delta */
80*7c478bd9Sstevel@tonic-gate 	{UNUM16, NO_OPR},	/* DW_CFA_advance_loc2 - delta */
81*7c478bd9Sstevel@tonic-gate 	{UNUM32, NO_OPR},	/* DW_CFA_advance_loc4 - delta */
82*7c478bd9Sstevel@tonic-gate 	{ULEB128, ULEB128_FAC},	/* DW_CFA_offset_extended - reg, */
83*7c478bd9Sstevel@tonic-gate 				/* data factored offset */
84*7c478bd9Sstevel@tonic-gate 	{ULEB128, NO_OPR},	/* DW_CFA_restore_extended - register */
85*7c478bd9Sstevel@tonic-gate 	{ULEB128, NO_OPR},	/* DW_CFA_undefined - register */
86*7c478bd9Sstevel@tonic-gate 	{ULEB128, NO_OPR},	/* DW_CFA_same_value - register */
87*7c478bd9Sstevel@tonic-gate 	{ULEB128, ULEB128_SREG}, /* DW_CFA_register - register, register */
88*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},	/* DW_CFA_remember_state */
89*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},	/* DW_CFA_restore_state */
90*7c478bd9Sstevel@tonic-gate 	{ULEB128_SREG, ULEB128}, /* DW_CFA_def_cfa - register, offset */
91*7c478bd9Sstevel@tonic-gate 	{ULEB128_SREG, NO_OPR},	/* DW_CFA_def_cfa_register - register */
92*7c478bd9Sstevel@tonic-gate 	{ULEB128, NO_OPR},	/* DW_CFA_def_cfa_offset - offset */
93*7c478bd9Sstevel@tonic-gate 	{BLOCK, NO_OPR},	/* DW_CFA_def_cfa_expression - expression */
94*7c478bd9Sstevel@tonic-gate 	{ULEB128, BLOCK},	/* DW_CFA_expression - reg, expression */
95*7c478bd9Sstevel@tonic-gate 	{ULEB128, SLEB128_FAC},	/* DW_CFA_offset_extended_sf - reg, */
96*7c478bd9Sstevel@tonic-gate 				/* data factored offset */
97*7c478bd9Sstevel@tonic-gate 	{ULEB128_SREG, SLEB128_FAC},	/* DW_CFA_def_cfa_sf - reg, */
98*7c478bd9Sstevel@tonic-gate 					/* data factored offset */
99*7c478bd9Sstevel@tonic-gate 	{SLEB128_FAC, NO_OPR},	/* DW_CFA_def_cfa_offset_sf - */
100*7c478bd9Sstevel@tonic-gate 				/* data fctored offset */
101*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
102*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
103*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
104*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
105*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
106*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
107*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
108*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
109*7c478bd9Sstevel@tonic-gate 	{NO_OPR, NO_OPR},
110*7c478bd9Sstevel@tonic-gate 	{UNUM6_CFAC, NO_OPR},	/* DW_CFA_SUNW_advance_loc - */
111*7c478bd9Sstevel@tonic-gate 				/* code factored delta */
112*7c478bd9Sstevel@tonic-gate 	{UNUM6, ULEB128_FAC},	/* DW_CFA_SUNW_offset - reg */
113*7c478bd9Sstevel@tonic-gate 				/* data factored offset */
114*7c478bd9Sstevel@tonic-gate 	{UNUM6, NO_OPR}		/* DW_CFA_SUNW_restore */
115*7c478bd9Sstevel@tonic-gate };
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate uint64_t interpret_ops(void *data, void *data_end,
118*7c478bd9Sstevel@tonic-gate 		ptrdiff_t reloc, uint64_t current_loc, uint64_t pc,
119*7c478bd9Sstevel@tonic-gate 		struct register_state f_state[],
120*7c478bd9Sstevel@tonic-gate 		struct register_state f_start_state[],
121*7c478bd9Sstevel@tonic-gate 		int daf, int caf, int enc);
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate /*
124*7c478bd9Sstevel@tonic-gate  * The entry-point state of old_ctx defines the current
125*7c478bd9Sstevel@tonic-gate  * suspended state of the caller (in new_ctx). If the old info
126*7c478bd9Sstevel@tonic-gate  * will not be refered to again, old_ctx == new_ctx is OK
127*7c478bd9Sstevel@tonic-gate  */
128*7c478bd9Sstevel@tonic-gate void
129*7c478bd9Sstevel@tonic-gate _Unw_Propagate_Registers(struct _Unwind_Context *old_ctx,
130*7c478bd9Sstevel@tonic-gate 	struct _Unwind_Context *new_ctx)
131*7c478bd9Sstevel@tonic-gate {
132*7c478bd9Sstevel@tonic-gate 	new_ctx->current_regs[SP_RSP] = old_ctx->cfa;
133*7c478bd9Sstevel@tonic-gate 	new_ctx->pc = old_ctx->ra;
134*7c478bd9Sstevel@tonic-gate 	new_ctx->current_regs[FP_RBP] = old_ctx->entry_regs[FP_RBP];
135*7c478bd9Sstevel@tonic-gate 	new_ctx->current_regs[GPR_RBX] = old_ctx->entry_regs[GPR_RBX];
136*7c478bd9Sstevel@tonic-gate 	new_ctx->current_regs[EIR_R12] = old_ctx->entry_regs[EIR_R12];
137*7c478bd9Sstevel@tonic-gate 	new_ctx->current_regs[EIR_R13] = old_ctx->entry_regs[EIR_R13];
138*7c478bd9Sstevel@tonic-gate 	new_ctx->current_regs[EIR_R14] = old_ctx->entry_regs[EIR_R14];
139*7c478bd9Sstevel@tonic-gate 	new_ctx->current_regs[EIR_R15] = old_ctx->entry_regs[EIR_R15];
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate void
143*7c478bd9Sstevel@tonic-gate fix_cfa(struct _Unwind_Context *ctx, struct register_state *rs)
144*7c478bd9Sstevel@tonic-gate {
145*7c478bd9Sstevel@tonic-gate 	switch (rs[CF_ADDR].rule) {
146*7c478bd9Sstevel@tonic-gate 	default:
147*7c478bd9Sstevel@tonic-gate 	    ctx->cfa = 0;
148*7c478bd9Sstevel@tonic-gate 		break;
149*7c478bd9Sstevel@tonic-gate 	case register_rule:	/* CFA = offset + source_reg */
150*7c478bd9Sstevel@tonic-gate 		ctx->cfa = (ctx->current_regs)[rs[CF_ADDR].source_reg] +
151*7c478bd9Sstevel@tonic-gate 			rs[CF_ADDR].offset;
152*7c478bd9Sstevel@tonic-gate 		break;
153*7c478bd9Sstevel@tonic-gate 	case constant_rule:	/* CFA = offset */
154*7c478bd9Sstevel@tonic-gate 		ctx->cfa = rs[CF_ADDR].offset;
155*7c478bd9Sstevel@tonic-gate 		break;
156*7c478bd9Sstevel@tonic-gate 	case indirect_rule:	/* CFA = *(offset + source_reg) */
157*7c478bd9Sstevel@tonic-gate 		ctx->cfa = *(uint64_t *)
158*7c478bd9Sstevel@tonic-gate 			(ctx->current_regs[rs[CF_ADDR].source_reg] +
159*7c478bd9Sstevel@tonic-gate 			rs[CF_ADDR].offset);
160*7c478bd9Sstevel@tonic-gate 		break;
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 	ctx->entry_regs[SP_RSP] = ctx->cfa;
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate void
166*7c478bd9Sstevel@tonic-gate fix_ra(struct _Unwind_Context *ctx, struct register_state *rs)
167*7c478bd9Sstevel@tonic-gate {
168*7c478bd9Sstevel@tonic-gate 	switch (rs[RET_ADD].rule) {
169*7c478bd9Sstevel@tonic-gate 	case undefined_rule:
170*7c478bd9Sstevel@tonic-gate 	default:
171*7c478bd9Sstevel@tonic-gate 	    ctx->ra = 0;
172*7c478bd9Sstevel@tonic-gate 		break;
173*7c478bd9Sstevel@tonic-gate 	case offset_rule:	/* RA = *(offset + CFA) */
174*7c478bd9Sstevel@tonic-gate 		ctx->ra = *(uint64_t *)(ctx->cfa + rs[RET_ADD].offset);
175*7c478bd9Sstevel@tonic-gate 		break;
176*7c478bd9Sstevel@tonic-gate 	case register_rule:	/* RA = offset + source_reg */
177*7c478bd9Sstevel@tonic-gate 		ctx->ra = ctx->current_regs[rs[RET_ADD].source_reg] +
178*7c478bd9Sstevel@tonic-gate 			rs[RET_ADD].offset;
179*7c478bd9Sstevel@tonic-gate 		break;
180*7c478bd9Sstevel@tonic-gate 	case indirect_rule:	/* RA = *(offset + source_reg) */
181*7c478bd9Sstevel@tonic-gate 		ctx->ra = *(uint64_t *)
182*7c478bd9Sstevel@tonic-gate 			(ctx->current_regs[rs[RET_ADD].source_reg] +
183*7c478bd9Sstevel@tonic-gate 			rs[RET_ADD].offset);
184*7c478bd9Sstevel@tonic-gate 		break;
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate void
189*7c478bd9Sstevel@tonic-gate fix_reg(struct _Unwind_Context *ctx, struct register_state *rs, int index)
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	switch (rs[index].rule) {
192*7c478bd9Sstevel@tonic-gate 	default:
193*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[index] = ctx->current_regs[index];
194*7c478bd9Sstevel@tonic-gate 		break;
195*7c478bd9Sstevel@tonic-gate 	case offset_rule:	/* target_reg = *(offset + CFA) */
196*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[index] = *(uint64_t *)
197*7c478bd9Sstevel@tonic-gate 			(ctx->cfa + rs[index].offset);
198*7c478bd9Sstevel@tonic-gate 		break;
199*7c478bd9Sstevel@tonic-gate 	case is_offset_rule:	/* target_reg = offset + CFA */
200*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[index] = ctx->cfa + rs[index].offset;
201*7c478bd9Sstevel@tonic-gate 		break;
202*7c478bd9Sstevel@tonic-gate 	case register_rule:	/* target_reg = offset + source_reg */
203*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[index] =
204*7c478bd9Sstevel@tonic-gate 			ctx->current_regs[rs[index].source_reg] +
205*7c478bd9Sstevel@tonic-gate 			rs[index].offset;
206*7c478bd9Sstevel@tonic-gate 		break;
207*7c478bd9Sstevel@tonic-gate 	case constant_rule:	/* target_reg = offset */
208*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[index] = rs[index].offset;
209*7c478bd9Sstevel@tonic-gate 		break;
210*7c478bd9Sstevel@tonic-gate 	case indirect_rule:	/* target_reg = *(offset + source_reg) */
211*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[index] = *(uint64_t *)
212*7c478bd9Sstevel@tonic-gate 			(ctx->current_regs[rs[index].source_reg] +
213*7c478bd9Sstevel@tonic-gate 			rs[index].offset);
214*7c478bd9Sstevel@tonic-gate 		break;
215*7c478bd9Sstevel@tonic-gate 	}
216*7c478bd9Sstevel@tonic-gate }
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate /*
220*7c478bd9Sstevel@tonic-gate  * Input: f->{cie_ops, cie_ops_end, fde_ops, fde_ops_end}
221*7c478bd9Sstevel@tonic-gate  *			+ location of DWARF opcodes
222*7c478bd9Sstevel@tonic-gate  *		  ctx->{current_regs, pc}
223*7c478bd9Sstevel@tonic-gate  *			+ register values and pc at point of suspension
224*7c478bd9Sstevel@tonic-gate  * Output: ctx->{entry_regs, cfa, ra}
225*7c478bd9Sstevel@tonic-gate  *			+ register values when function was entered
226*7c478bd9Sstevel@tonic-gate  *			+ Cannonical Frame Address
227*7c478bd9Sstevel@tonic-gate  *			+ return address
228*7c478bd9Sstevel@tonic-gate  */
229*7c478bd9Sstevel@tonic-gate uint64_t
230*7c478bd9Sstevel@tonic-gate _Unw_Rollback_Registers(struct eh_frame_fields *f,
231*7c478bd9Sstevel@tonic-gate 	struct _Unwind_Context *ctx)
232*7c478bd9Sstevel@tonic-gate {
233*7c478bd9Sstevel@tonic-gate 	/* GPRs, RET_ADD, and CF_ADDR */
234*7c478bd9Sstevel@tonic-gate 	struct register_state func_state[18];
235*7c478bd9Sstevel@tonic-gate 	struct register_state func_start_state[18];
236*7c478bd9Sstevel@tonic-gate 	struct register_state nop = { 0, undefined_rule, 0 };
237*7c478bd9Sstevel@tonic-gate 	int i;
238*7c478bd9Sstevel@tonic-gate 	uint64_t  first_pc;
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	if (f == 0) {
241*7c478bd9Sstevel@tonic-gate 		/*
242*7c478bd9Sstevel@tonic-gate 		 * When no FDE we assume all routines have a frame pointer
243*7c478bd9Sstevel@tonic-gate 		 * and pass back existing callee saves registers
244*7c478bd9Sstevel@tonic-gate 		 */
245*7c478bd9Sstevel@tonic-gate 		if (ctx->current_regs[FP_RBP] < ctx->current_regs[SP_RSP]) {
246*7c478bd9Sstevel@tonic-gate 			ctx->cfa = 0;
247*7c478bd9Sstevel@tonic-gate 			ctx->ra = 0;
248*7c478bd9Sstevel@tonic-gate 			ctx->pc = 0;
249*7c478bd9Sstevel@tonic-gate 			return (0);
250*7c478bd9Sstevel@tonic-gate 		}
251*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[FP_RBP] = ((uint64_t *)
252*7c478bd9Sstevel@tonic-gate 			(ctx->current_regs[FP_RBP]))[0];
253*7c478bd9Sstevel@tonic-gate 		ctx->cfa = ctx->current_regs[FP_RBP] + 16;
254*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[SP_RSP] = ctx->cfa;
255*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[GPR_RBX] = ctx->current_regs[GPR_RBX];
256*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[EIR_R12] = ctx->current_regs[EIR_R12];
257*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[EIR_R13] = ctx->current_regs[EIR_R13];
258*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[EIR_R14] = ctx->current_regs[EIR_R14];
259*7c478bd9Sstevel@tonic-gate 		ctx->entry_regs[EIR_R15] = ctx->current_regs[EIR_R15];
260*7c478bd9Sstevel@tonic-gate 		ctx->ra = ((uint64_t *)ctx->cfa)[-1];
261*7c478bd9Sstevel@tonic-gate 		return (ctx->cfa);
262*7c478bd9Sstevel@tonic-gate 	}
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 18; i++)
265*7c478bd9Sstevel@tonic-gate 		func_start_state[i] = nop;
266*7c478bd9Sstevel@tonic-gate 	first_pc = interpret_ops(f->cie_ops, f->cie_ops_end,
267*7c478bd9Sstevel@tonic-gate 		f->cie_reloc, ctx->func, ctx->pc, func_start_state, 0,
268*7c478bd9Sstevel@tonic-gate 		f->data_align, f->code_align, f->code_enc);
269*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 18; i++)
270*7c478bd9Sstevel@tonic-gate 		func_state[i] = func_start_state[i];
271*7c478bd9Sstevel@tonic-gate 	(void) interpret_ops(f->fde_ops, f->fde_ops_end,
272*7c478bd9Sstevel@tonic-gate 		f->fde_reloc, first_pc, ctx->pc, func_state, func_start_state,
273*7c478bd9Sstevel@tonic-gate 		f->data_align, f->code_align, f->code_enc);
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	fix_cfa(ctx, func_state);
276*7c478bd9Sstevel@tonic-gate 	if (ctx->cfa < ctx->current_regs[SP_RSP]) {
277*7c478bd9Sstevel@tonic-gate 		ctx->cfa = 0;
278*7c478bd9Sstevel@tonic-gate 		ctx->ra = 0;
279*7c478bd9Sstevel@tonic-gate 		ctx->pc = 0;
280*7c478bd9Sstevel@tonic-gate 		return (0);
281*7c478bd9Sstevel@tonic-gate 	}
282*7c478bd9Sstevel@tonic-gate 	fix_ra(ctx, func_state);
283*7c478bd9Sstevel@tonic-gate 	fix_reg(ctx, func_state, GPR_RBX);
284*7c478bd9Sstevel@tonic-gate 	fix_reg(ctx, func_state, FP_RBP);
285*7c478bd9Sstevel@tonic-gate 	fix_reg(ctx, func_state, EIR_R12);
286*7c478bd9Sstevel@tonic-gate 	fix_reg(ctx, func_state, EIR_R13);
287*7c478bd9Sstevel@tonic-gate 	fix_reg(ctx, func_state, EIR_R14);
288*7c478bd9Sstevel@tonic-gate 	fix_reg(ctx, func_state, EIR_R15);
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 	return (ctx->cfa);
291*7c478bd9Sstevel@tonic-gate }
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate /*
294*7c478bd9Sstevel@tonic-gate  * remap two-bit opcodes into a separate range or grab eight-bit opcode
295*7c478bd9Sstevel@tonic-gate  * and advance pointer past it.
296*7c478bd9Sstevel@tonic-gate  */
297*7c478bd9Sstevel@tonic-gate static enum CFA_ops
298*7c478bd9Sstevel@tonic-gate separate_op(void **pp)
299*7c478bd9Sstevel@tonic-gate {
300*7c478bd9Sstevel@tonic-gate 	uint8_t c = **((uint8_t **)pp);
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if (c & 0xc0) {
303*7c478bd9Sstevel@tonic-gate 		switch (c & 0xc0) {
304*7c478bd9Sstevel@tonic-gate 		case DW_CFA_advance_loc:
305*7c478bd9Sstevel@tonic-gate 			return (DW_CFA_SUNW_advance_loc);
306*7c478bd9Sstevel@tonic-gate 		case DW_CFA_offset:
307*7c478bd9Sstevel@tonic-gate 			return (DW_CFA_SUNW_offset);
308*7c478bd9Sstevel@tonic-gate 		case DW_CFA_restore:
309*7c478bd9Sstevel@tonic-gate 			return (DW_CFA_SUNW_restore);
310*7c478bd9Sstevel@tonic-gate 		}
311*7c478bd9Sstevel@tonic-gate 	} else {
312*7c478bd9Sstevel@tonic-gate 		*pp = (void *)((*(intptr_t *)pp) + 1);
313*7c478bd9Sstevel@tonic-gate 	}
314*7c478bd9Sstevel@tonic-gate 	return (c);
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate static uint64_t
318*7c478bd9Sstevel@tonic-gate extractuleb(void **datap)
319*7c478bd9Sstevel@tonic-gate {
320*7c478bd9Sstevel@tonic-gate 	uint8_t *data = *(uint8_t **)datap;
321*7c478bd9Sstevel@tonic-gate 	uint64_t res = 0;
322*7c478bd9Sstevel@tonic-gate 	int more = 1;
323*7c478bd9Sstevel@tonic-gate 	int shift = 0;
324*7c478bd9Sstevel@tonic-gate 	int val;
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	while (more) {
327*7c478bd9Sstevel@tonic-gate 		val = (*data) & 0x7f;
328*7c478bd9Sstevel@tonic-gate 		more = ((*data++) & 0x80) >> 7;
329*7c478bd9Sstevel@tonic-gate 		res = res | val << shift;
330*7c478bd9Sstevel@tonic-gate 		shift += 7;
331*7c478bd9Sstevel@tonic-gate 	}
332*7c478bd9Sstevel@tonic-gate 	*datap = (void *)data;
333*7c478bd9Sstevel@tonic-gate 	return (res);
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate static uint64_t
337*7c478bd9Sstevel@tonic-gate extractsleb(void** datap)
338*7c478bd9Sstevel@tonic-gate {
339*7c478bd9Sstevel@tonic-gate 	uint8_t *data = *datap;
340*7c478bd9Sstevel@tonic-gate 	int64_t res = 0;
341*7c478bd9Sstevel@tonic-gate 	int more = 1;
342*7c478bd9Sstevel@tonic-gate 	int shift = 0;
343*7c478bd9Sstevel@tonic-gate 	unsigned int val;
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	while (more) {
346*7c478bd9Sstevel@tonic-gate 		val = (*data) & 0x7f;
347*7c478bd9Sstevel@tonic-gate 		more = ((*data++) & 0x80) >> 7;
348*7c478bd9Sstevel@tonic-gate 		res = res | val<< shift;
349*7c478bd9Sstevel@tonic-gate 		shift += 7;
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate 	*datap = (void*) data;
352*7c478bd9Sstevel@tonic-gate 	res = (res << (64 - shift)) >> (64 - shift);
353*7c478bd9Sstevel@tonic-gate 	return (res);
354*7c478bd9Sstevel@tonic-gate }
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate static uint64_t get_encoded_val(void **datap, ptrdiff_t reloc, int enc);
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate /*
359*7c478bd9Sstevel@tonic-gate  * do all field extractions needed for CFA operands and encoded FDE
360*7c478bd9Sstevel@tonic-gate  * fields
361*7c478bd9Sstevel@tonic-gate  */
362*7c478bd9Sstevel@tonic-gate uint64_t
363*7c478bd9Sstevel@tonic-gate _Unw_get_val(void **datap, ptrdiff_t reloc,
364*7c478bd9Sstevel@tonic-gate 	enum operand_desc opr, int daf, int caf, int enc)
365*7c478bd9Sstevel@tonic-gate {
366*7c478bd9Sstevel@tonic-gate 	intptr_t data = (intptr_t)*datap;
367*7c478bd9Sstevel@tonic-gate 	uint64_t res;
368*7c478bd9Sstevel@tonic-gate 	char *dp, *rp;
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	switch (opr) {
371*7c478bd9Sstevel@tonic-gate 	case NO_OPR:
372*7c478bd9Sstevel@tonic-gate 		res = 0;
373*7c478bd9Sstevel@tonic-gate 		break;
374*7c478bd9Sstevel@tonic-gate 	case ULEB128_FAC:
375*7c478bd9Sstevel@tonic-gate 		return (daf * extractuleb(datap));
376*7c478bd9Sstevel@tonic-gate 		break;
377*7c478bd9Sstevel@tonic-gate 	case ULEB128:
378*7c478bd9Sstevel@tonic-gate 		return (extractuleb(datap));
379*7c478bd9Sstevel@tonic-gate 		break;
380*7c478bd9Sstevel@tonic-gate 	case ULEB128_SREG:
381*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(*((uint8_t *)data));
382*7c478bd9Sstevel@tonic-gate 		data += 1;
383*7c478bd9Sstevel@tonic-gate 		switch (res) {
384*7c478bd9Sstevel@tonic-gate 			/* verify that register is one which is being tracked */
385*7c478bd9Sstevel@tonic-gate 		case GPR_RBX:
386*7c478bd9Sstevel@tonic-gate 		case FP_RBP:
387*7c478bd9Sstevel@tonic-gate 		case SP_RSP:
388*7c478bd9Sstevel@tonic-gate 		case EIR_R12:
389*7c478bd9Sstevel@tonic-gate 		case EIR_R13:
390*7c478bd9Sstevel@tonic-gate 		case EIR_R14:
391*7c478bd9Sstevel@tonic-gate 		case EIR_R15:
392*7c478bd9Sstevel@tonic-gate 			break;
393*7c478bd9Sstevel@tonic-gate 		default:
394*7c478bd9Sstevel@tonic-gate 			res = BAD_REG;
395*7c478bd9Sstevel@tonic-gate 			break;
396*7c478bd9Sstevel@tonic-gate 		}
397*7c478bd9Sstevel@tonic-gate 		break;
398*7c478bd9Sstevel@tonic-gate 	case UNUM6:
399*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(0x3f & *((uint8_t *)data));
400*7c478bd9Sstevel@tonic-gate 		data += 1;
401*7c478bd9Sstevel@tonic-gate 		break;
402*7c478bd9Sstevel@tonic-gate 	case UNUM8:
403*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(*((uint8_t *)data));
404*7c478bd9Sstevel@tonic-gate 		data += 1;
405*7c478bd9Sstevel@tonic-gate 		break;
406*7c478bd9Sstevel@tonic-gate 	case UNUM16:
407*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(*((uint16_t *)data));
408*7c478bd9Sstevel@tonic-gate 		data += 2;
409*7c478bd9Sstevel@tonic-gate 		break;
410*7c478bd9Sstevel@tonic-gate 	case UNUM32:
411*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(*((uint32_t *)data));
412*7c478bd9Sstevel@tonic-gate 		data += 4;
413*7c478bd9Sstevel@tonic-gate 		break;
414*7c478bd9Sstevel@tonic-gate 	case UNUM6_CFAC:
415*7c478bd9Sstevel@tonic-gate 		res = caf * (uint64_t)(0x3f & *((uint8_t *)data));
416*7c478bd9Sstevel@tonic-gate 		data += 1;
417*7c478bd9Sstevel@tonic-gate 		break;
418*7c478bd9Sstevel@tonic-gate 	case UNUM8_CFAC:
419*7c478bd9Sstevel@tonic-gate 		res = caf * (uint64_t)(*((uint8_t *)data));
420*7c478bd9Sstevel@tonic-gate 		data += 1;
421*7c478bd9Sstevel@tonic-gate 		break;
422*7c478bd9Sstevel@tonic-gate 	case UNUM16_CFAC:
423*7c478bd9Sstevel@tonic-gate 		res = caf * (uint64_t)(*((uint16_t *)data));
424*7c478bd9Sstevel@tonic-gate 		data += 2;
425*7c478bd9Sstevel@tonic-gate 		break;
426*7c478bd9Sstevel@tonic-gate 	case UNUM32_CFAC:
427*7c478bd9Sstevel@tonic-gate 		res = caf * (uint64_t)(*((uint32_t *)data));
428*7c478bd9Sstevel@tonic-gate 		data += 4;
429*7c478bd9Sstevel@tonic-gate 		break;
430*7c478bd9Sstevel@tonic-gate 	case UNUM64:
431*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(*((uint64_t *)data));
432*7c478bd9Sstevel@tonic-gate 		data += 8;
433*7c478bd9Sstevel@tonic-gate 		break;
434*7c478bd9Sstevel@tonic-gate 	case SNUM8:
435*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(int64_t)(*((int8_t *)data));
436*7c478bd9Sstevel@tonic-gate 		data += 1;
437*7c478bd9Sstevel@tonic-gate 		break;
438*7c478bd9Sstevel@tonic-gate 	case SNUM16:
439*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(int64_t)(*((int16_t *)data));
440*7c478bd9Sstevel@tonic-gate 		data += 2;
441*7c478bd9Sstevel@tonic-gate 		break;
442*7c478bd9Sstevel@tonic-gate 	case SNUM32:
443*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(int64_t)(*((int32_t *)data));
444*7c478bd9Sstevel@tonic-gate 		data += 4;
445*7c478bd9Sstevel@tonic-gate 		break;
446*7c478bd9Sstevel@tonic-gate 	case SNUM64:
447*7c478bd9Sstevel@tonic-gate 		res = (uint64_t)(*((int64_t *)data));
448*7c478bd9Sstevel@tonic-gate 		data += 8;
449*7c478bd9Sstevel@tonic-gate 		break;
450*7c478bd9Sstevel@tonic-gate 	case SLEB128_FAC:
451*7c478bd9Sstevel@tonic-gate 		return (daf * extractsleb(datap));
452*7c478bd9Sstevel@tonic-gate 		break;
453*7c478bd9Sstevel@tonic-gate 	case SLEB128:
454*7c478bd9Sstevel@tonic-gate 		return (extractsleb(datap));
455*7c478bd9Sstevel@tonic-gate 		break;
456*7c478bd9Sstevel@tonic-gate 	case ZTSTRING:
457*7c478bd9Sstevel@tonic-gate 		/* max length of augmentation string is 4 */
458*7c478bd9Sstevel@tonic-gate 		rp = (char *)&res;
459*7c478bd9Sstevel@tonic-gate 		dp = (char *)data;
460*7c478bd9Sstevel@tonic-gate 		while (*rp++ = *dp++)
461*7c478bd9Sstevel@tonic-gate 			;
462*7c478bd9Sstevel@tonic-gate 		data = (intptr_t)dp;
463*7c478bd9Sstevel@tonic-gate 		break;
464*7c478bd9Sstevel@tonic-gate 	case ADDR:
465*7c478bd9Sstevel@tonic-gate 		return (get_encoded_val(datap, reloc, enc));
466*7c478bd9Sstevel@tonic-gate 		break;
467*7c478bd9Sstevel@tonic-gate 	case SIZE:
468*7c478bd9Sstevel@tonic-gate 		return (get_encoded_val(datap, reloc, enc & 0x7));
469*7c478bd9Sstevel@tonic-gate 	case BLOCK:
470*7c478bd9Sstevel@tonic-gate 		res = 0;  /* not implemented */
471*7c478bd9Sstevel@tonic-gate 		break;
472*7c478bd9Sstevel@tonic-gate 	}
473*7c478bd9Sstevel@tonic-gate 	*datap = (void*)data;
474*7c478bd9Sstevel@tonic-gate 	return (res);
475*7c478bd9Sstevel@tonic-gate }
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate static uint64_t
478*7c478bd9Sstevel@tonic-gate get_encoded_val(void **datap, ptrdiff_t reloc, int enc)
479*7c478bd9Sstevel@tonic-gate {
480*7c478bd9Sstevel@tonic-gate 	int val = enc & 0xf;
481*7c478bd9Sstevel@tonic-gate 	int rel = (enc >> 4) & 0xf;
482*7c478bd9Sstevel@tonic-gate 	intptr_t loc = ((intptr_t)*datap) + reloc;
483*7c478bd9Sstevel@tonic-gate 	uint64_t res = 0;
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	switch (val) {
486*7c478bd9Sstevel@tonic-gate 	case 0x01:
487*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, ULEB128, 1, 1, 0);
488*7c478bd9Sstevel@tonic-gate 		break;
489*7c478bd9Sstevel@tonic-gate 	case 0x2:
490*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, UNUM16, 1, 1, 0);
491*7c478bd9Sstevel@tonic-gate 		break;
492*7c478bd9Sstevel@tonic-gate 	case 0x3:
493*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, UNUM32, 1, 1, 0);
494*7c478bd9Sstevel@tonic-gate 		break;
495*7c478bd9Sstevel@tonic-gate 	case 0x04:
496*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, UNUM64, 1, 1, 0);
497*7c478bd9Sstevel@tonic-gate 		break;
498*7c478bd9Sstevel@tonic-gate 	case 0x09:
499*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, SLEB128, 1, 1, 0);
500*7c478bd9Sstevel@tonic-gate 		break;
501*7c478bd9Sstevel@tonic-gate 	case 0x0a:
502*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, SNUM16, 1, 1, 0);
503*7c478bd9Sstevel@tonic-gate 		break;
504*7c478bd9Sstevel@tonic-gate 	case 0x0b:
505*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, SNUM32, 1, 1, 0);
506*7c478bd9Sstevel@tonic-gate 		break;
507*7c478bd9Sstevel@tonic-gate 	case 0x0c:
508*7c478bd9Sstevel@tonic-gate 		res = _Unw_get_val(datap, reloc, SNUM64, 1, 1, 0);
509*7c478bd9Sstevel@tonic-gate 		break;
510*7c478bd9Sstevel@tonic-gate 	}
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	switch (rel) {
513*7c478bd9Sstevel@tonic-gate 	case 0:
514*7c478bd9Sstevel@tonic-gate 		break;
515*7c478bd9Sstevel@tonic-gate 	case 1:
516*7c478bd9Sstevel@tonic-gate 		if (res != 0)
517*7c478bd9Sstevel@tonic-gate 			res += loc;
518*7c478bd9Sstevel@tonic-gate 		break;
519*7c478bd9Sstevel@tonic-gate 	default:
520*7c478bd9Sstevel@tonic-gate 		/* remainder not implemented */
521*7c478bd9Sstevel@tonic-gate 		break;
522*7c478bd9Sstevel@tonic-gate 	}
523*7c478bd9Sstevel@tonic-gate 	return (res);
524*7c478bd9Sstevel@tonic-gate }
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate int interpret_op(void **datap, ptrdiff_t reloc,
528*7c478bd9Sstevel@tonic-gate 	uint64_t *reached_pc_p, uint64_t pc,
529*7c478bd9Sstevel@tonic-gate 	struct register_state f_state[],
530*7c478bd9Sstevel@tonic-gate 	struct register_state f_start_state[],
531*7c478bd9Sstevel@tonic-gate 	int daf, int caf, int enc);
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate uint64_t
534*7c478bd9Sstevel@tonic-gate interpret_ops(void *data, void *data_end,
535*7c478bd9Sstevel@tonic-gate 	ptrdiff_t reloc,
536*7c478bd9Sstevel@tonic-gate 	uint64_t start_pc, uint64_t pc,
537*7c478bd9Sstevel@tonic-gate 	struct register_state f_state[],
538*7c478bd9Sstevel@tonic-gate 	struct register_state f_start_state[],
539*7c478bd9Sstevel@tonic-gate 	int daf, int caf, int enc)
540*7c478bd9Sstevel@tonic-gate {
541*7c478bd9Sstevel@tonic-gate 	void *d = data;
542*7c478bd9Sstevel@tonic-gate 	uint64_t reached_pc = start_pc;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	while (d < data_end) {
545*7c478bd9Sstevel@tonic-gate 		if (interpret_op(&d, reloc, &reached_pc, pc,
546*7c478bd9Sstevel@tonic-gate 		    f_state, f_start_state, daf, caf, enc))
547*7c478bd9Sstevel@tonic-gate 			break;
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 	return (reached_pc);
550*7c478bd9Sstevel@tonic-gate }
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate int
553*7c478bd9Sstevel@tonic-gate interpret_op(void **datap, ptrdiff_t reloc,
554*7c478bd9Sstevel@tonic-gate 	uint64_t *reached_pc_p, uint64_t pc,
555*7c478bd9Sstevel@tonic-gate 	struct register_state f_state[],
556*7c478bd9Sstevel@tonic-gate 	struct register_state f_start_state[],
557*7c478bd9Sstevel@tonic-gate 	int daf, int caf, int enc)
558*7c478bd9Sstevel@tonic-gate {
559*7c478bd9Sstevel@tonic-gate 	enum CFA_ops op = separate_op(datap);
560*7c478bd9Sstevel@tonic-gate 	enum operand_desc opr1 = (cfa_operations[op]).op1;
561*7c478bd9Sstevel@tonic-gate 	enum operand_desc opr2 = (cfa_operations[op]).op2;
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	uint64_t val1 = _Unw_get_val(datap, reloc, opr1, daf, caf, enc);
564*7c478bd9Sstevel@tonic-gate 	uint64_t val2 = _Unw_get_val(datap, reloc, opr2, daf, caf, enc);
565*7c478bd9Sstevel@tonic-gate 	if ((opr1 == ULEB128_SREG && val1 == BAD_REG) ||
566*7c478bd9Sstevel@tonic-gate 	    (opr2 == ULEB128_SREG && val2 == BAD_REG))
567*7c478bd9Sstevel@tonic-gate 		return (0);
568*7c478bd9Sstevel@tonic-gate 	switch (op) {
569*7c478bd9Sstevel@tonic-gate 	case DW_CFA_nop:
570*7c478bd9Sstevel@tonic-gate 		break;
571*7c478bd9Sstevel@tonic-gate 	case DW_CFA_set_loc:
572*7c478bd9Sstevel@tonic-gate 		if (val1 > pc)
573*7c478bd9Sstevel@tonic-gate 			return (1);
574*7c478bd9Sstevel@tonic-gate 		*reached_pc_p = val1;
575*7c478bd9Sstevel@tonic-gate 		break;
576*7c478bd9Sstevel@tonic-gate 	case DW_CFA_advance_loc1:
577*7c478bd9Sstevel@tonic-gate 	case DW_CFA_advance_loc2:
578*7c478bd9Sstevel@tonic-gate 	case DW_CFA_advance_loc4:
579*7c478bd9Sstevel@tonic-gate 		if (*reached_pc_p + val1 > pc)
580*7c478bd9Sstevel@tonic-gate 			return (1);
581*7c478bd9Sstevel@tonic-gate 		*reached_pc_p += val1;
582*7c478bd9Sstevel@tonic-gate 		break;
583*7c478bd9Sstevel@tonic-gate 	case DW_CFA_offset_extended:
584*7c478bd9Sstevel@tonic-gate 		f_state[val1].rule = offset_rule;
585*7c478bd9Sstevel@tonic-gate 		f_state[val1].source_reg = CF_ADDR;
586*7c478bd9Sstevel@tonic-gate 		f_state[val1].offset = val2;
587*7c478bd9Sstevel@tonic-gate 		break;
588*7c478bd9Sstevel@tonic-gate 	case DW_CFA_restore_extended:
589*7c478bd9Sstevel@tonic-gate 		if (f_start_state != 0)
590*7c478bd9Sstevel@tonic-gate 			f_state[val1] = f_start_state[val1];
591*7c478bd9Sstevel@tonic-gate 		break;
592*7c478bd9Sstevel@tonic-gate 	case DW_CFA_undefined:
593*7c478bd9Sstevel@tonic-gate 		f_state[val1].rule = undefined_rule;
594*7c478bd9Sstevel@tonic-gate 		break;
595*7c478bd9Sstevel@tonic-gate 	case DW_CFA_same_value:
596*7c478bd9Sstevel@tonic-gate 		f_state[val1].rule = same_value_rule;
597*7c478bd9Sstevel@tonic-gate 		break;
598*7c478bd9Sstevel@tonic-gate 	case DW_CFA_register:
599*7c478bd9Sstevel@tonic-gate 		f_state[val1].rule = register_rule;
600*7c478bd9Sstevel@tonic-gate 		f_state[val1].source_reg = val2;
601*7c478bd9Sstevel@tonic-gate 		f_state[val1].offset = 0;
602*7c478bd9Sstevel@tonic-gate 		break;
603*7c478bd9Sstevel@tonic-gate 	case DW_CFA_remember_state:
604*7c478bd9Sstevel@tonic-gate 		break;
605*7c478bd9Sstevel@tonic-gate 	case DW_CFA_restore_state:
606*7c478bd9Sstevel@tonic-gate 		break;
607*7c478bd9Sstevel@tonic-gate 	case DW_CFA_def_cfa:
608*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].rule = register_rule;
609*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].source_reg = val1;
610*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].offset = val2;
611*7c478bd9Sstevel@tonic-gate 		break;
612*7c478bd9Sstevel@tonic-gate 	case DW_CFA_def_cfa_register:
613*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].source_reg = val1;
614*7c478bd9Sstevel@tonic-gate 		break;
615*7c478bd9Sstevel@tonic-gate 	case DW_CFA_def_cfa_offset:
616*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].offset = val1;
617*7c478bd9Sstevel@tonic-gate 		break;
618*7c478bd9Sstevel@tonic-gate 	case DW_CFA_def_cfa_expression:
619*7c478bd9Sstevel@tonic-gate 		break;
620*7c478bd9Sstevel@tonic-gate 	case DW_CFA_expression:
621*7c478bd9Sstevel@tonic-gate 		break;
622*7c478bd9Sstevel@tonic-gate 	case DW_CFA_offset_extended_sf:
623*7c478bd9Sstevel@tonic-gate 		f_state[val1].rule = offset_rule;
624*7c478bd9Sstevel@tonic-gate 		f_state[val1].source_reg = CF_ADDR;
625*7c478bd9Sstevel@tonic-gate 		f_state[val1].offset = val2;
626*7c478bd9Sstevel@tonic-gate 		break;
627*7c478bd9Sstevel@tonic-gate 	case DW_CFA_def_cfa_sf:
628*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].rule = register_rule;
629*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].source_reg = val1;
630*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].offset = val2;
631*7c478bd9Sstevel@tonic-gate 		break;
632*7c478bd9Sstevel@tonic-gate 	case DW_CFA_def_cfa_offset_sf:
633*7c478bd9Sstevel@tonic-gate 		f_state[CF_ADDR].offset = val1;
634*7c478bd9Sstevel@tonic-gate 		break;
635*7c478bd9Sstevel@tonic-gate 	case DW_CFA_SUNW_advance_loc:
636*7c478bd9Sstevel@tonic-gate 		if (*reached_pc_p + val1 > pc)
637*7c478bd9Sstevel@tonic-gate 			return (1);
638*7c478bd9Sstevel@tonic-gate 		*reached_pc_p += val1;
639*7c478bd9Sstevel@tonic-gate 		break;
640*7c478bd9Sstevel@tonic-gate 	case DW_CFA_SUNW_offset:
641*7c478bd9Sstevel@tonic-gate 		f_state[val1].rule = offset_rule;
642*7c478bd9Sstevel@tonic-gate 		f_state[val1].source_reg = CF_ADDR;
643*7c478bd9Sstevel@tonic-gate 		f_state[val1].offset = val2;
644*7c478bd9Sstevel@tonic-gate 		break;
645*7c478bd9Sstevel@tonic-gate 	case DW_CFA_SUNW_restore:
646*7c478bd9Sstevel@tonic-gate 		if (f_start_state != 0)
647*7c478bd9Sstevel@tonic-gate 			f_state[val1] = f_start_state[val1];
648*7c478bd9Sstevel@tonic-gate 		break;
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate 	return (0);
651*7c478bd9Sstevel@tonic-gate }
652