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