17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7257d1b4Sraf * Common Development and Distribution License (the "License"). 6*7257d1b4Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*7257d1b4Sraf 227c478bd9Sstevel@tonic-gate /* 23*7257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * interface used by unwind support to query frame descriptor info 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #ifndef _LIBCRUN_ 34*7257d1b4Sraf #include "lint.h" 357c478bd9Sstevel@tonic-gate #endif 367c478bd9Sstevel@tonic-gate #include <sys/types.h> 377c478bd9Sstevel@tonic-gate #include <limits.h> 387c478bd9Sstevel@tonic-gate #include "stack_unwind.h" 397c478bd9Sstevel@tonic-gate #include "unwind_context.h" 407c478bd9Sstevel@tonic-gate #include <dlfcn.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * CIE: 447c478bd9Sstevel@tonic-gate * UNUM32 length 457c478bd9Sstevel@tonic-gate * UNUM32 ID 467c478bd9Sstevel@tonic-gate * UNUM8 version 477c478bd9Sstevel@tonic-gate * ZTSTRING augmentation 487c478bd9Sstevel@tonic-gate * ULEB128 Code Align Factor 497c478bd9Sstevel@tonic-gate * SLEB128 Data Align Factor 507c478bd9Sstevel@tonic-gate * UNUM8 RA 517c478bd9Sstevel@tonic-gate * ULEB128 length 527c478bd9Sstevel@tonic-gate * UNUM8 personality enc 537c478bd9Sstevel@tonic-gate * ADDR personality 547c478bd9Sstevel@tonic-gate * UNUM8 code_enc 557c478bd9Sstevel@tonic-gate * UNUM8 lsda_enc 567c478bd9Sstevel@tonic-gate * 577c478bd9Sstevel@tonic-gate * FDE: 587c478bd9Sstevel@tonic-gate * UNUM32 length 597c478bd9Sstevel@tonic-gate * UNUM32 ID 607c478bd9Sstevel@tonic-gate * ADDR initial loc 617c478bd9Sstevel@tonic-gate * SIZE size 627c478bd9Sstevel@tonic-gate * ULEB128 length 637c478bd9Sstevel@tonic-gate * ADDR lsda 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate struct eh_frame_fields * 687c478bd9Sstevel@tonic-gate _Unw_Decode_FDE(struct eh_frame_fields *f, struct _Unwind_Context *ctx) 697c478bd9Sstevel@tonic-gate { 707c478bd9Sstevel@tonic-gate void *fde_data; /* location in this process of fde */ 717c478bd9Sstevel@tonic-gate void *fde_end; 727c478bd9Sstevel@tonic-gate void *data; 737c478bd9Sstevel@tonic-gate ptrdiff_t reloc; 747c478bd9Sstevel@tonic-gate uintptr_t base; 757c478bd9Sstevel@tonic-gate void *cie_data; /* location in this process of cie */ 767c478bd9Sstevel@tonic-gate void *cie_end; 777c478bd9Sstevel@tonic-gate void *cdata; 787c478bd9Sstevel@tonic-gate ptrdiff_t creloc; 797c478bd9Sstevel@tonic-gate int lsda_enc = 0; 807c478bd9Sstevel@tonic-gate int per_enc = 0; 817c478bd9Sstevel@tonic-gate int code_enc = 0; 827c478bd9Sstevel@tonic-gate char augment[8]; 837c478bd9Sstevel@tonic-gate char *p; 847c478bd9Sstevel@tonic-gate uint64_t scratch; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate uint64_t func = 0; 877c478bd9Sstevel@tonic-gate uint64_t range = 0; 887c478bd9Sstevel@tonic-gate _Unwind_Personality_Fn pfn = 0; 897c478bd9Sstevel@tonic-gate void* lsda = 0; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* here is where data mapping would happen ??REMOTE?? */ 927c478bd9Sstevel@tonic-gate fde_data = ctx->fde; 937c478bd9Sstevel@tonic-gate data = fde_data; 947c478bd9Sstevel@tonic-gate fde_end = (void *)(((intptr_t)fde_data) + 4 + 95*7257d1b4Sraf _Unw_get_val(&data, 0, UNUM32, 1, 1, 0)); 967c478bd9Sstevel@tonic-gate reloc = 0; 977c478bd9Sstevel@tonic-gate base = ((intptr_t)data) + reloc; 987c478bd9Sstevel@tonic-gate cie_data = (void *)(base - _Unw_get_val(&data, 0, UNUM32, 1, 1, 0)); 997c478bd9Sstevel@tonic-gate cdata = cie_data; 1007c478bd9Sstevel@tonic-gate cie_end = (void *)(((intptr_t)cie_data) + 4 + 101*7257d1b4Sraf _Unw_get_val(&cdata, 0, UNUM32, 1, 1, 0)); 1027c478bd9Sstevel@tonic-gate creloc = 0; 1037c478bd9Sstevel@tonic-gate /* data mapping has happened */ 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate f->cie_ops_end = cie_end; 1067c478bd9Sstevel@tonic-gate f->cie_reloc = creloc; 1077c478bd9Sstevel@tonic-gate f->fde_ops_end = fde_end; 1087c478bd9Sstevel@tonic-gate f->fde_reloc = reloc; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate (void) _Unw_get_val(&cdata, creloc, UNUM32, 1, 1, 0); 1117c478bd9Sstevel@tonic-gate (void) _Unw_get_val(&cdata, creloc, UNUM8, 1, 1, 0); 1127c478bd9Sstevel@tonic-gate /* LINTED alignment */ 1137c478bd9Sstevel@tonic-gate (*((uint64_t *)(&(augment[0])))) = 114*7257d1b4Sraf _Unw_get_val(&cdata, creloc, ZTSTRING, 1, 1, 0); 1157c478bd9Sstevel@tonic-gate f->code_align = _Unw_get_val(&cdata, creloc, ULEB128, 1, 1, 0); 1167c478bd9Sstevel@tonic-gate f->data_align = _Unw_get_val(&cdata, creloc, SLEB128, 1, 1, 0); 1177c478bd9Sstevel@tonic-gate (void) _Unw_get_val(&cdata, creloc, UNUM8, 1, 1, 0); 1187c478bd9Sstevel@tonic-gate if (augment[0] == 'z' && 1197c478bd9Sstevel@tonic-gate (scratch = _Unw_get_val(&cdata, creloc, ULEB128, 1, 1, 0)) != 0) { 1207c478bd9Sstevel@tonic-gate for (p = &(augment[1]); *p != 0; p++) { 1217c478bd9Sstevel@tonic-gate switch (*p) { 1227c478bd9Sstevel@tonic-gate case 'P': 1237c478bd9Sstevel@tonic-gate per_enc = _Unw_get_val(&cdata, creloc, 1247c478bd9Sstevel@tonic-gate UNUM8, 1, 1, 0); 1257c478bd9Sstevel@tonic-gate if (per_enc == 0) 1267c478bd9Sstevel@tonic-gate per_enc = 0x4; 1277c478bd9Sstevel@tonic-gate pfn = (_Unwind_Personality_Fn) 1287c478bd9Sstevel@tonic-gate _Unw_get_val(&cdata, creloc, 1297c478bd9Sstevel@tonic-gate ADDR, 1, 1, per_enc); 1307c478bd9Sstevel@tonic-gate break; 1317c478bd9Sstevel@tonic-gate case 'R': 1327c478bd9Sstevel@tonic-gate code_enc = _Unw_get_val(&cdata, creloc, 1337c478bd9Sstevel@tonic-gate UNUM8, 1, 1, 0); 1347c478bd9Sstevel@tonic-gate break; 1357c478bd9Sstevel@tonic-gate case 'L': 1367c478bd9Sstevel@tonic-gate lsda_enc = _Unw_get_val(&cdata, creloc, 1377c478bd9Sstevel@tonic-gate UNUM8, 1, 1, 0); 1387c478bd9Sstevel@tonic-gate break; 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate if (code_enc == 0) 1437c478bd9Sstevel@tonic-gate code_enc = 0x4; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate func = _Unw_get_val(&data, reloc, ADDR, 1, 1, code_enc); 1467c478bd9Sstevel@tonic-gate range = _Unw_get_val(&data, reloc, SIZE, 1, 1, code_enc); 1477c478bd9Sstevel@tonic-gate if ((ctx->pc < func) || (ctx->pc > (func+range))) 1487c478bd9Sstevel@tonic-gate return (0); 1497c478bd9Sstevel@tonic-gate ctx->func = func; 1507c478bd9Sstevel@tonic-gate ctx->range = range; 1517c478bd9Sstevel@tonic-gate if (augment[0] == 'z') { 1527c478bd9Sstevel@tonic-gate scratch = _Unw_get_val(&data, reloc, ULEB128, 1, 1, 0); 1537c478bd9Sstevel@tonic-gate if (scratch == 4 && lsda_enc) { 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * without the two work-arounds test would be 1567c478bd9Sstevel@tonic-gate * (scratch > 0 & lsda_enc) 1577c478bd9Sstevel@tonic-gate */ 1587c478bd9Sstevel@tonic-gate lsda = (void *)_Unw_get_val(&data, reloc, 1597c478bd9Sstevel@tonic-gate ADDR, 1, 1, lsda_enc); 1607c478bd9Sstevel@tonic-gate } else if (scratch == 4) { 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * 11/24/04 compiler is sometimes not outputing 1637c478bd9Sstevel@tonic-gate * lsda_enc 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate lsda = (void*)_Unw_get_val(&data, reloc, 1667c478bd9Sstevel@tonic-gate ADDR, 1, 1, 0x1b); 1677c478bd9Sstevel@tonic-gate } else if (scratch == 8) { 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * 11/12/04 - compiler is putting out relative 1707c478bd9Sstevel@tonic-gate * encoding byte and absolute data - inconsistancy 1717c478bd9Sstevel@tonic-gate * is caught here. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate lsda = (void *)_Unw_get_val(&data, reloc, 1747c478bd9Sstevel@tonic-gate ADDR, 1, 1, 0x4); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate } 1777c478bd9Sstevel@tonic-gate if (pfn) 1787c478bd9Sstevel@tonic-gate ctx->pfn = pfn; 1797c478bd9Sstevel@tonic-gate if (lsda) 1807c478bd9Sstevel@tonic-gate ctx->lsda = lsda; 1817c478bd9Sstevel@tonic-gate f->fde_ops = data; 1827c478bd9Sstevel@tonic-gate f->cie_ops = cdata; 1837c478bd9Sstevel@tonic-gate f->code_enc = code_enc; 1847c478bd9Sstevel@tonic-gate return (f); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate static int 1887c478bd9Sstevel@tonic-gate table_ent_log_size(int enc) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate int val = enc & 0xf; 1917c478bd9Sstevel@tonic-gate int res; 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate switch (val) { 1947c478bd9Sstevel@tonic-gate case 0x3: 1957c478bd9Sstevel@tonic-gate res = 3; 1967c478bd9Sstevel@tonic-gate break; 1977c478bd9Sstevel@tonic-gate case 0x04: 1987c478bd9Sstevel@tonic-gate res = 4; 1997c478bd9Sstevel@tonic-gate break; 2007c478bd9Sstevel@tonic-gate case 0x0b: 2017c478bd9Sstevel@tonic-gate res = 3; 2027c478bd9Sstevel@tonic-gate break; 2037c478bd9Sstevel@tonic-gate case 0x0c: 2047c478bd9Sstevel@tonic-gate res = 4; 2057c478bd9Sstevel@tonic-gate break; 2067c478bd9Sstevel@tonic-gate default: 2077c478bd9Sstevel@tonic-gate break; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate return (res); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate static void 2137c478bd9Sstevel@tonic-gate get_table_ent_val(unsigned char *data, unsigned char *data_end, 2147c478bd9Sstevel@tonic-gate int enc, ptrdiff_t reloc, uintptr_t base, 2157c478bd9Sstevel@tonic-gate uint64_t *codep, uint64_t *next_codep, void **fdep) 2167c478bd9Sstevel@tonic-gate { 2177c478bd9Sstevel@tonic-gate int val = enc & 0xf; 2187c478bd9Sstevel@tonic-gate int rel = (enc >> 4) & 0xf; 2197c478bd9Sstevel@tonic-gate unsigned char *second = data; 2207c478bd9Sstevel@tonic-gate unsigned char *third = data; 2217c478bd9Sstevel@tonic-gate uint64_t code; 2227c478bd9Sstevel@tonic-gate void *fde; 2237c478bd9Sstevel@tonic-gate uint64_t next_code; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate switch (val) { 2267c478bd9Sstevel@tonic-gate case 0x3: 2277c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2287c478bd9Sstevel@tonic-gate code = (uint64_t)(*((uint32_t *)data)); 2297c478bd9Sstevel@tonic-gate second += 4; 2307c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2317c478bd9Sstevel@tonic-gate fde = (void *)(uint64_t)(*((uint32_t *)second)); 2327c478bd9Sstevel@tonic-gate third += 8; 2337c478bd9Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 2347c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2357c478bd9Sstevel@tonic-gate (uint64_t)(*((uint32_t *)third)); 2367c478bd9Sstevel@tonic-gate break; 2377c478bd9Sstevel@tonic-gate case 0x04: 2387c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2397c478bd9Sstevel@tonic-gate code = (uint64_t)(*((uint64_t *)data)); 2407c478bd9Sstevel@tonic-gate second += 8; 2417c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2427c478bd9Sstevel@tonic-gate fde = (void *)(uint64_t)(*((uint64_t *)second)); 2437c478bd9Sstevel@tonic-gate third += 16; 2447c478bd9Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 2457c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2467c478bd9Sstevel@tonic-gate (uint64_t)(*((uint64_t *)third)); 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate case 0x0b: 2497c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2507c478bd9Sstevel@tonic-gate code = (uint64_t)(int64_t)(*((int32_t *)data)); 2517c478bd9Sstevel@tonic-gate second += 4; 2527c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2537c478bd9Sstevel@tonic-gate fde = (void *)(uint64_t)(int64_t)(*((int32_t *)second)); 2547c478bd9Sstevel@tonic-gate third += 8; 2557c478bd9Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 2567c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2577c478bd9Sstevel@tonic-gate (uint64_t)(int64_t)(*((int32_t *)third)); 2587c478bd9Sstevel@tonic-gate break; 2597c478bd9Sstevel@tonic-gate case 0x0c: 2607c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2617c478bd9Sstevel@tonic-gate code = (uint64_t)(*((int64_t *)data)); 2627c478bd9Sstevel@tonic-gate second += 8; 2637c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2647c478bd9Sstevel@tonic-gate fde = (void *)(uint64_t)(*((int64_t *)second)); 2657c478bd9Sstevel@tonic-gate third += 16; 2667c478bd9Sstevel@tonic-gate next_code = (third >= data_end)? ULONG_MAX : 2677c478bd9Sstevel@tonic-gate /* LINTED alignment */ 2687c478bd9Sstevel@tonic-gate (uint64_t)(*((int64_t *)third)); 2697c478bd9Sstevel@tonic-gate break; 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate switch (rel) { 2737c478bd9Sstevel@tonic-gate case 0: 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate case 1: 2767c478bd9Sstevel@tonic-gate code += (uint64_t)data + reloc; 2777c478bd9Sstevel@tonic-gate fde = (void *)(((uint64_t)fde) + (uint64_t)second + reloc); 2787c478bd9Sstevel@tonic-gate if (next_code != ULONG_MAX) 2797c478bd9Sstevel@tonic-gate next_code += (uint64_t)third + reloc; 2807c478bd9Sstevel@tonic-gate break; 2817c478bd9Sstevel@tonic-gate case 3: 2827c478bd9Sstevel@tonic-gate code += base; 2837c478bd9Sstevel@tonic-gate fde = (void *)(((uint64_t)fde) + base); 2847c478bd9Sstevel@tonic-gate if (next_code != ULONG_MAX) 2857c478bd9Sstevel@tonic-gate next_code += base; 2867c478bd9Sstevel@tonic-gate break; 2877c478bd9Sstevel@tonic-gate default: 2887c478bd9Sstevel@tonic-gate /* remainder not implemented */ 2897c478bd9Sstevel@tonic-gate break; 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate *codep = code; 2927c478bd9Sstevel@tonic-gate *fdep = fde; 2937c478bd9Sstevel@tonic-gate *next_codep = next_code; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate static void * 2987c478bd9Sstevel@tonic-gate locate_fde_for_pc(uint64_t pc, int enc, 2997c478bd9Sstevel@tonic-gate unsigned char *table, unsigned char *table_end, 3007c478bd9Sstevel@tonic-gate ptrdiff_t reloc, uintptr_t base); 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * Search the eh_frame info with a given pc. Return a pointer to a 3047c478bd9Sstevel@tonic-gate * FDE. The search is performed in two stages. 3057c478bd9Sstevel@tonic-gate * First rtld.so identifies the load module containing the target location. 3067c478bd9Sstevel@tonic-gate * This returns the appropiate eh_frame_hdr, and a binary search is 3077c478bd9Sstevel@tonic-gate * then performed on the eh_frame_hdr to locate the entry with 3087c478bd9Sstevel@tonic-gate * a matching pc value. 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate void * 3117c478bd9Sstevel@tonic-gate _Unw_EhfhLookup(struct _Unwind_Context *ctx) 3127c478bd9Sstevel@tonic-gate { 3137c478bd9Sstevel@tonic-gate Dl_amd64_unwindinfo dlef; 3147c478bd9Sstevel@tonic-gate void* data; 3157c478bd9Sstevel@tonic-gate void* data_end; 3167c478bd9Sstevel@tonic-gate uint64_t pc = ctx->pc; 3177c478bd9Sstevel@tonic-gate int fp_enc, fc_enc, ft_enc; 3187c478bd9Sstevel@tonic-gate unsigned char *pi, *pj; 3197c478bd9Sstevel@tonic-gate ptrdiff_t reloc; 3207c478bd9Sstevel@tonic-gate uintptr_t base; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate dlef.dlui_version = 1; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* Locate the appropiate exception_range_entry table first */ 3257c478bd9Sstevel@tonic-gate if (0 == dlamd64getunwind((void*)pc, &dlef)) { 3267c478bd9Sstevel@tonic-gate return (0); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * you now know size and position of block of data needed for 3317c478bd9Sstevel@tonic-gate * binary search ??REMOTE?? 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate data = dlef.dlui_unwindstart; 3347c478bd9Sstevel@tonic-gate if (0 == data) 3357c478bd9Sstevel@tonic-gate return (0); 3367c478bd9Sstevel@tonic-gate base = (uintptr_t)data; 3377c478bd9Sstevel@tonic-gate data_end = dlef.dlui_unwindend; 3387c478bd9Sstevel@tonic-gate reloc = 0; 3397c478bd9Sstevel@tonic-gate /* ??REMOTE?? */ 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate (void) _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 3427c478bd9Sstevel@tonic-gate fp_enc = _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 3437c478bd9Sstevel@tonic-gate fc_enc = _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 3447c478bd9Sstevel@tonic-gate ft_enc = _Unw_get_val(&data, reloc, UNUM8, 1, 1, 0); 3457c478bd9Sstevel@tonic-gate (void) _Unw_get_val(&data, reloc, ADDR, 1, 1, fp_enc); 3467c478bd9Sstevel@tonic-gate (void) _Unw_get_val(&data, reloc, SIZE, 1, 1, fc_enc); 3477c478bd9Sstevel@tonic-gate pi = data; 3487c478bd9Sstevel@tonic-gate pj = data_end; 3497c478bd9Sstevel@tonic-gate ctx->fde = locate_fde_for_pc(pc, ft_enc, pi, pj, reloc, base); 3507c478bd9Sstevel@tonic-gate return ((void *)(ctx->fde)); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate static void * 3547c478bd9Sstevel@tonic-gate locate_fde_for_pc(uint64_t pc, int enc, 3557c478bd9Sstevel@tonic-gate unsigned char *table_bg, unsigned char *table_end, 3567c478bd9Sstevel@tonic-gate ptrdiff_t reloc, uintptr_t base) 3577c478bd9Sstevel@tonic-gate { 3587c478bd9Sstevel@tonic-gate unsigned char *pi = table_bg; 3597c478bd9Sstevel@tonic-gate unsigned char *pj = table_end; 3607c478bd9Sstevel@tonic-gate uint64_t range_start, range_end; 3617c478bd9Sstevel@tonic-gate void* fde; 3627c478bd9Sstevel@tonic-gate int log_size = table_ent_log_size(enc); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * Invariant -- if there is a containing range, 3667c478bd9Sstevel@tonic-gate * it must lie in the interval [pi,pj). That is, 3677c478bd9Sstevel@tonic-gate * pi <= p < pj, if p exists. 3687c478bd9Sstevel@tonic-gate */ 3697c478bd9Sstevel@tonic-gate while (pi < pj) { 3707c478bd9Sstevel@tonic-gate unsigned char *pr = 3717c478bd9Sstevel@tonic-gate pi + (((pj - pi) >> (log_size + 1)) << log_size); 3727c478bd9Sstevel@tonic-gate /* Don't use (pi+pj)>>1 */ 3737c478bd9Sstevel@tonic-gate get_table_ent_val(pr, table_end, enc, reloc, base, 374*7257d1b4Sraf &range_start, &range_end, &fde); 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* Return fde if tpc is in this range. */ 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate if (range_start <= pc && pc < range_end) { 3797c478bd9Sstevel@tonic-gate return ((void*) fde); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if (range_start < pc) 3837c478bd9Sstevel@tonic-gate pi = pr + (1 << log_size); 3847c478bd9Sstevel@tonic-gate else 3857c478bd9Sstevel@tonic-gate pj = pr; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate return (0); 3887c478bd9Sstevel@tonic-gate } 389