1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * interface used by unwind support to query frame descriptor info 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #ifndef _LIBCRUN_ 34*0Sstevel@tonic-gate #include "synonyms.h" 35*0Sstevel@tonic-gate #endif 36*0Sstevel@tonic-gate #include <sys/types.h> 37*0Sstevel@tonic-gate #include <limits.h> 38*0Sstevel@tonic-gate #include "stack_unwind.h" 39*0Sstevel@tonic-gate #include "unwind_context.h" 40*0Sstevel@tonic-gate #include <dlfcn.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * CIE: 44*0Sstevel@tonic-gate * UNUM32 length 45*0Sstevel@tonic-gate * UNUM32 ID 46*0Sstevel@tonic-gate * UNUM8 version 47*0Sstevel@tonic-gate * ZTSTRING augmentation 48*0Sstevel@tonic-gate * ULEB128 Code Align Factor 49*0Sstevel@tonic-gate * SLEB128 Data Align Factor 50*0Sstevel@tonic-gate * UNUM8 RA 51*0Sstevel@tonic-gate * ULEB128 length 52*0Sstevel@tonic-gate * UNUM8 personality enc 53*0Sstevel@tonic-gate * ADDR personality 54*0Sstevel@tonic-gate * UNUM8 code_enc 55*0Sstevel@tonic-gate * UNUM8 lsda_enc 56*0Sstevel@tonic-gate * 57*0Sstevel@tonic-gate * FDE: 58*0Sstevel@tonic-gate * UNUM32 length 59*0Sstevel@tonic-gate * UNUM32 ID 60*0Sstevel@tonic-gate * ADDR initial loc 61*0Sstevel@tonic-gate * SIZE size 62*0Sstevel@tonic-gate * ULEB128 length 63*0Sstevel@tonic-gate * ADDR lsda 64*0Sstevel@tonic-gate */ 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate struct eh_frame_fields * 68*0Sstevel@tonic-gate _Unw_Decode_FDE(struct eh_frame_fields *f, struct _Unwind_Context *ctx) 69*0Sstevel@tonic-gate { 70*0Sstevel@tonic-gate void *fde_data; /* location in this process of fde */ 71*0Sstevel@tonic-gate void *fde_end; 72*0Sstevel@tonic-gate void *data; 73*0Sstevel@tonic-gate ptrdiff_t reloc; 74*0Sstevel@tonic-gate uintptr_t base; 75*0Sstevel@tonic-gate void *cie_data; /* location in this process of cie */ 76*0Sstevel@tonic-gate void *cie_end; 77*0Sstevel@tonic-gate void *cdata; 78*0Sstevel@tonic-gate ptrdiff_t creloc; 79*0Sstevel@tonic-gate int lsda_enc = 0; 80*0Sstevel@tonic-gate int per_enc = 0; 81*0Sstevel@tonic-gate int code_enc = 0; 82*0Sstevel@tonic-gate char augment[8]; 83*0Sstevel@tonic-gate char *p; 84*0Sstevel@tonic-gate uint64_t scratch; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate uint64_t func = 0; 87*0Sstevel@tonic-gate uint64_t range = 0; 88*0Sstevel@tonic-gate _Unwind_Personality_Fn pfn = 0; 89*0Sstevel@tonic-gate void* lsda = 0; 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate /* here is where data mapping would happen ??REMOTE?? */ 92*0Sstevel@tonic-gate fde_data = ctx->fde; 93*0Sstevel@tonic-gate data = fde_data; 94*0Sstevel@tonic-gate fde_end = (void *)(((intptr_t)fde_data) + 4 + 95*0Sstevel@tonic-gate _Unw_get_val(&data, 0, UNUM32, 1, 1, 0)); 96*0Sstevel@tonic-gate reloc = 0; 97*0Sstevel@tonic-gate base = ((intptr_t)data) + reloc; 98*0Sstevel@tonic-gate cie_data = (void *)(base - _Unw_get_val(&data, 0, UNUM32, 1, 1, 0)); 99*0Sstevel@tonic-gate cdata = cie_data; 100*0Sstevel@tonic-gate cie_end = (void *)(((intptr_t)cie_data) + 4 + 101*0Sstevel@tonic-gate _Unw_get_val(&cdata, 0, UNUM32, 1, 1, 0)); 102*0Sstevel@tonic-gate creloc = 0; 103*0Sstevel@tonic-gate /* data mapping has happened */ 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate f->cie_ops_end = cie_end; 106*0Sstevel@tonic-gate f->cie_reloc = creloc; 107*0Sstevel@tonic-gate f->fde_ops_end = fde_end; 108*0Sstevel@tonic-gate f->fde_reloc = reloc; 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate (void) _Unw_get_val(&cdata, creloc, UNUM32, 1, 1, 0); 111*0Sstevel@tonic-gate (void) _Unw_get_val(&cdata, creloc, UNUM8, 1, 1, 0); 112*0Sstevel@tonic-gate /* LINTED alignment */ 113*0Sstevel@tonic-gate (*((uint64_t *)(&(augment[0])))) = 114*0Sstevel@tonic-gate _Unw_get_val(&cdata, creloc, ZTSTRING, 1, 1, 0); 115*0Sstevel@tonic-gate f->code_align = _Unw_get_val(&cdata, creloc, ULEB128, 1, 1, 0); 116*0Sstevel@tonic-gate f->data_align = _Unw_get_val(&cdata, creloc, SLEB128, 1, 1, 0); 117*0Sstevel@tonic-gate (void) _Unw_get_val(&cdata, creloc, UNUM8, 1, 1, 0); 118*0Sstevel@tonic-gate if (augment[0] == 'z' && 119*0Sstevel@tonic-gate (scratch = _Unw_get_val(&cdata, creloc, ULEB128, 1, 1, 0)) != 0) { 120*0Sstevel@tonic-gate for (p = &(augment[1]); *p != 0; p++) { 121*0Sstevel@tonic-gate switch (*p) { 122*0Sstevel@tonic-gate case 'P': 123*0Sstevel@tonic-gate per_enc = _Unw_get_val(&cdata, creloc, 124*0Sstevel@tonic-gate UNUM8, 1, 1, 0); 125*0Sstevel@tonic-gate if (per_enc == 0) 126*0Sstevel@tonic-gate per_enc = 0x4; 127*0Sstevel@tonic-gate pfn = (_Unwind_Personality_Fn) 128*0Sstevel@tonic-gate _Unw_get_val(&cdata, creloc, 129*0Sstevel@tonic-gate ADDR, 1, 1, per_enc); 130*0Sstevel@tonic-gate break; 131*0Sstevel@tonic-gate case 'R': 132*0Sstevel@tonic-gate code_enc = _Unw_get_val(&cdata, creloc, 133*0Sstevel@tonic-gate UNUM8, 1, 1, 0); 134*0Sstevel@tonic-gate break; 135*0Sstevel@tonic-gate case 'L': 136*0Sstevel@tonic-gate lsda_enc = _Unw_get_val(&cdata, creloc, 137*0Sstevel@tonic-gate UNUM8, 1, 1, 0); 138*0Sstevel@tonic-gate break; 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate if (code_enc == 0) 143*0Sstevel@tonic-gate code_enc = 0x4; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate func = _Unw_get_val(&data, reloc, ADDR, 1, 1, code_enc); 146*0Sstevel@tonic-gate range = _Unw_get_val(&data, reloc, SIZE, 1, 1, code_enc); 147*0Sstevel@tonic-gate if ((ctx->pc < func) || (ctx->pc > (func+range))) 148*0Sstevel@tonic-gate return (0); 149*0Sstevel@tonic-gate ctx->func = func; 150*0Sstevel@tonic-gate ctx->range = range; 151*0Sstevel@tonic-gate if (augment[0] == 'z') { 152*0Sstevel@tonic-gate scratch = _Unw_get_val(&data, reloc, ULEB128, 1, 1, 0); 153*0Sstevel@tonic-gate if (scratch == 4 && lsda_enc) { 154*0Sstevel@tonic-gate /* 155*0Sstevel@tonic-gate * without the two work-arounds test would be 156*0Sstevel@tonic-gate * (scratch > 0 & lsda_enc) 157*0Sstevel@tonic-gate */ 158*0Sstevel@tonic-gate lsda = (void *)_Unw_get_val(&data, reloc, 159*0Sstevel@tonic-gate ADDR, 1, 1, lsda_enc); 160*0Sstevel@tonic-gate } else if (scratch == 4) { 161*0Sstevel@tonic-gate /* 162*0Sstevel@tonic-gate * 11/24/04 compiler is sometimes not outputing 163*0Sstevel@tonic-gate * lsda_enc 164*0Sstevel@tonic-gate */ 165*0Sstevel@tonic-gate lsda = (void*)_Unw_get_val(&data, reloc, 166*0Sstevel@tonic-gate ADDR, 1, 1, 0x1b); 167*0Sstevel@tonic-gate } else if (scratch == 8) { 168*0Sstevel@tonic-gate /* 169*0Sstevel@tonic-gate * 11/12/04 - compiler is putting out relative 170*0Sstevel@tonic-gate * encoding byte and absolute data - inconsistancy 171*0Sstevel@tonic-gate * is caught here. 172*0Sstevel@tonic-gate */ 173*0Sstevel@tonic-gate lsda = (void *)_Unw_get_val(&data, reloc, 174*0Sstevel@tonic-gate ADDR, 1, 1, 0x4); 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate if (pfn) 178*0Sstevel@tonic-gate ctx->pfn = pfn; 179*0Sstevel@tonic-gate if (lsda) 180*0Sstevel@tonic-gate ctx->lsda = lsda; 181*0Sstevel@tonic-gate f->fde_ops = data; 182*0Sstevel@tonic-gate f->cie_ops = cdata; 183*0Sstevel@tonic-gate f->code_enc = code_enc; 184*0Sstevel@tonic-gate return (f); 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate static int 188*0Sstevel@tonic-gate table_ent_log_size(int enc) 189*0Sstevel@tonic-gate { 190*0Sstevel@tonic-gate int val = enc & 0xf; 191*0Sstevel@tonic-gate int res; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate switch (val) { 194*0Sstevel@tonic-gate case 0x3: 195*0Sstevel@tonic-gate res = 3; 196*0Sstevel@tonic-gate break; 197*0Sstevel@tonic-gate case 0x04: 198*0Sstevel@tonic-gate res = 4; 199*0Sstevel@tonic-gate break; 200*0Sstevel@tonic-gate case 0x0b: 201*0Sstevel@tonic-gate res = 3; 202*0Sstevel@tonic-gate break; 203*0Sstevel@tonic-gate case 0x0c: 204*0Sstevel@tonic-gate res = 4; 205*0Sstevel@tonic-gate break; 206*0Sstevel@tonic-gate default: 207*0Sstevel@tonic-gate break; 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate return (res); 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate static void 213*0Sstevel@tonic-gate get_table_ent_val(unsigned char *data, unsigned char *data_end, 214*0Sstevel@tonic-gate int enc, ptrdiff_t reloc, uintptr_t base, 215*0Sstevel@tonic-gate uint64_t *codep, uint64_t *next_codep, void **fdep) 216*0Sstevel@tonic-gate { 217*0Sstevel@tonic-gate int val = enc & 0xf; 218*0Sstevel@tonic-gate int rel = (enc >> 4) & 0xf; 219*0Sstevel@tonic-gate unsigned char *second = data; 220*0Sstevel@tonic-gate unsigned char *third = data; 221*0Sstevel@tonic-gate uint64_t code; 222*0Sstevel@tonic-gate void *fde; 223*0Sstevel@tonic-gate uint64_t next_code; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate switch (val) { 226*0Sstevel@tonic-gate case 0x3: 227*0Sstevel@tonic-gate /* LINTED alignment */ 228*0Sstevel@tonic-gate code = (uint64_t)(*((uint32_t *)data)); 229*0Sstevel@tonic-gate second += 4; 230*0Sstevel@tonic-gate /* LINTED alignment */ 231*0Sstevel@tonic-gate fde = (void *)(uint64_t)(*((uint32_t *)second)); 232*0Sstevel@tonic-gate third += 8; 233*0Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 234*0Sstevel@tonic-gate /* LINTED alignment */ 235*0Sstevel@tonic-gate (uint64_t)(*((uint32_t *)third)); 236*0Sstevel@tonic-gate break; 237*0Sstevel@tonic-gate case 0x04: 238*0Sstevel@tonic-gate /* LINTED alignment */ 239*0Sstevel@tonic-gate code = (uint64_t)(*((uint64_t *)data)); 240*0Sstevel@tonic-gate second += 8; 241*0Sstevel@tonic-gate /* LINTED alignment */ 242*0Sstevel@tonic-gate fde = (void *)(uint64_t)(*((uint64_t *)second)); 243*0Sstevel@tonic-gate third += 16; 244*0Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 245*0Sstevel@tonic-gate /* LINTED alignment */ 246*0Sstevel@tonic-gate (uint64_t)(*((uint64_t *)third)); 247*0Sstevel@tonic-gate break; 248*0Sstevel@tonic-gate case 0x0b: 249*0Sstevel@tonic-gate /* LINTED alignment */ 250*0Sstevel@tonic-gate code = (uint64_t)(int64_t)(*((int32_t *)data)); 251*0Sstevel@tonic-gate second += 4; 252*0Sstevel@tonic-gate /* LINTED alignment */ 253*0Sstevel@tonic-gate fde = (void *)(uint64_t)(int64_t)(*((int32_t *)second)); 254*0Sstevel@tonic-gate third += 8; 255*0Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 256*0Sstevel@tonic-gate /* LINTED alignment */ 257*0Sstevel@tonic-gate (uint64_t)(int64_t)(*((int32_t *)third)); 258*0Sstevel@tonic-gate break; 259*0Sstevel@tonic-gate case 0x0c: 260*0Sstevel@tonic-gate /* LINTED alignment */ 261*0Sstevel@tonic-gate code = (uint64_t)(*((int64_t *)data)); 262*0Sstevel@tonic-gate second += 8; 263*0Sstevel@tonic-gate /* LINTED alignment */ 264*0Sstevel@tonic-gate fde = (void *)(uint64_t)(*((int64_t *)second)); 265*0Sstevel@tonic-gate third += 16; 266*0Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 267*0Sstevel@tonic-gate /* LINTED alignment */ 268*0Sstevel@tonic-gate (uint64_t)(*((int64_t *)third)); 269*0Sstevel@tonic-gate break; 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate switch (rel) { 273*0Sstevel@tonic-gate case 0: 274*0Sstevel@tonic-gate break; 275*0Sstevel@tonic-gate case 1: 276*0Sstevel@tonic-gate code += (uint64_t)data + reloc; 277*0Sstevel@tonic-gate fde = (void *)(((uint64_t)fde) + (uint64_t)second + reloc); 278*0Sstevel@tonic-gate if (next_code != ULONG_MAX) 279*0Sstevel@tonic-gate next_code += (uint64_t)third + reloc; 280*0Sstevel@tonic-gate break; 281*0Sstevel@tonic-gate case 3: 282*0Sstevel@tonic-gate code += base; 283*0Sstevel@tonic-gate fde = (void *)(((uint64_t)fde) + base); 284*0Sstevel@tonic-gate if (next_code != ULONG_MAX) 285*0Sstevel@tonic-gate next_code += base; 286*0Sstevel@tonic-gate break; 287*0Sstevel@tonic-gate default: 288*0Sstevel@tonic-gate /* remainder not implemented */ 289*0Sstevel@tonic-gate break; 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate *codep = code; 292*0Sstevel@tonic-gate *fdep = fde; 293*0Sstevel@tonic-gate *next_codep = next_code; 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate static void * 298*0Sstevel@tonic-gate locate_fde_for_pc(uint64_t pc, int enc, 299*0Sstevel@tonic-gate unsigned char *table, unsigned char *table_end, 300*0Sstevel@tonic-gate ptrdiff_t reloc, uintptr_t base); 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate /* 303*0Sstevel@tonic-gate * Search the eh_frame info with a given pc. Return a pointer to a 304*0Sstevel@tonic-gate * FDE. The search is performed in two stages. 305*0Sstevel@tonic-gate * First rtld.so identifies the load module containing the target location. 306*0Sstevel@tonic-gate * This returns the appropiate eh_frame_hdr, and a binary search is 307*0Sstevel@tonic-gate * then performed on the eh_frame_hdr to locate the entry with 308*0Sstevel@tonic-gate * a matching pc value. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate void * 311*0Sstevel@tonic-gate _Unw_EhfhLookup(struct _Unwind_Context *ctx) 312*0Sstevel@tonic-gate { 313*0Sstevel@tonic-gate Dl_amd64_unwindinfo dlef; 314*0Sstevel@tonic-gate void* data; 315*0Sstevel@tonic-gate void* data_end; 316*0Sstevel@tonic-gate uint64_t pc = ctx->pc; 317*0Sstevel@tonic-gate int fp_enc, fc_enc, ft_enc; 318*0Sstevel@tonic-gate unsigned char *pi, *pj; 319*0Sstevel@tonic-gate ptrdiff_t reloc; 320*0Sstevel@tonic-gate uintptr_t base; 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate dlef.dlui_version = 1; 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate /* Locate the appropiate exception_range_entry table first */ 325*0Sstevel@tonic-gate if (0 == dlamd64getunwind((void*)pc, &dlef)) { 326*0Sstevel@tonic-gate return (0); 327*0Sstevel@tonic-gate } 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate /* 330*0Sstevel@tonic-gate * you now know size and position of block of data needed for 331*0Sstevel@tonic-gate * binary search ??REMOTE?? 332*0Sstevel@tonic-gate */ 333*0Sstevel@tonic-gate data = dlef.dlui_unwindstart; 334*0Sstevel@tonic-gate if (0 == data) 335*0Sstevel@tonic-gate return (0); 336*0Sstevel@tonic-gate base = (uintptr_t)data; 337*0Sstevel@tonic-gate data_end = dlef.dlui_unwindend; 338*0Sstevel@tonic-gate reloc = 0; 339*0Sstevel@tonic-gate /* ??REMOTE?? */ 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate (void) _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 342*0Sstevel@tonic-gate fp_enc = _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 343*0Sstevel@tonic-gate fc_enc = _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 344*0Sstevel@tonic-gate ft_enc = _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 345*0Sstevel@tonic-gate (void) _Unw_get_val(&data, reloc, ADDR, 1, 1, fp_enc); 346*0Sstevel@tonic-gate (void) _Unw_get_val(&data, reloc, SIZE, 1, 1, fc_enc); 347*0Sstevel@tonic-gate pi = data; 348*0Sstevel@tonic-gate pj = data_end; 349*0Sstevel@tonic-gate ctx->fde = locate_fde_for_pc(pc, ft_enc, pi, pj, reloc, base); 350*0Sstevel@tonic-gate return ((void *)(ctx->fde)); 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate static void * 354*0Sstevel@tonic-gate locate_fde_for_pc(uint64_t pc, int enc, 355*0Sstevel@tonic-gate unsigned char *table_bg, unsigned char *table_end, 356*0Sstevel@tonic-gate ptrdiff_t reloc, uintptr_t base) 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate unsigned char *pi = table_bg; 359*0Sstevel@tonic-gate unsigned char *pj = table_end; 360*0Sstevel@tonic-gate uint64_t range_start, range_end; 361*0Sstevel@tonic-gate void* fde; 362*0Sstevel@tonic-gate int log_size = table_ent_log_size(enc); 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate /* 365*0Sstevel@tonic-gate * Invariant -- if there is a containing range, 366*0Sstevel@tonic-gate * it must lie in the interval [pi,pj). That is, 367*0Sstevel@tonic-gate * pi <= p < pj, if p exists. 368*0Sstevel@tonic-gate */ 369*0Sstevel@tonic-gate while (pi < pj) { 370*0Sstevel@tonic-gate unsigned char *pr = 371*0Sstevel@tonic-gate pi + (((pj - pi) >> (log_size + 1)) << log_size); 372*0Sstevel@tonic-gate /* Don't use (pi+pj)>>1 */ 373*0Sstevel@tonic-gate get_table_ent_val(pr, table_end, enc, reloc, base, 374*0Sstevel@tonic-gate &range_start, &range_end, &fde); 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate /* Return fde if tpc is in this range. */ 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate if (range_start <= pc && pc < range_end) { 379*0Sstevel@tonic-gate return ((void*) fde); 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate if (range_start < pc) 383*0Sstevel@tonic-gate pi = pr + (1 << log_size); 384*0Sstevel@tonic-gate else 385*0Sstevel@tonic-gate pj = pr; 386*0Sstevel@tonic-gate } 387*0Sstevel@tonic-gate return (0); 388*0Sstevel@tonic-gate } 389