1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1998 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Search routines for processing new-style mon.out files. 30 */ 31 32 #include "profv.h" 33 34 /* 35 * Look up an address in a sorted-by-address namelist; this deals with 36 * misses by mapping them to the next lower entry point. 37 */ 38 nltype * 39 nllookup(mod_info_t *module, Address address, Address *nxtsym_val) 40 { 41 size_t low = 0, middle, high = module->nfuncs - 1; 42 nltype *nl = module->nl; 43 Address keyval; 44 45 /* 46 * If this is the program executable in which we are looking up 47 * a symbol, then the actual load address will be the same as the 48 * address specified in the ELF file. For shared objects, the 49 * load address may differ from what is specified in the file. In 50 * this case, we may need to look for a different value altogether. 51 */ 52 keyval = module->txt_origin + (address - module->load_base); 53 54 if (keyval < nl[low].value) { 55 if (nxtsym_val) { 56 *nxtsym_val = module->load_base + 57 (nl[low].value - module->txt_origin); 58 } 59 return (NULL); 60 } 61 62 if (keyval >= nl[high].value) { 63 if (nxtsym_val) 64 *nxtsym_val = module->load_end; 65 return (&nl[high]); 66 } 67 68 while (low != high) { 69 middle = (high + low) >> 1; 70 71 if ((nl[middle].value <= keyval) && 72 (nl[middle + 1].value > keyval)) { 73 if (nxtsym_val) { 74 *nxtsym_val = module->load_base + 75 (nl[middle + 1].value - module->txt_origin); 76 } 77 78 return (&nl[middle]); 79 } 80 81 if (nl[middle].value > keyval) 82 high = middle; 83 else 84 low = middle + 1; 85 } 86 87 /* must never reach here! */ 88 return (NULL); 89 } 90 91 /* 92 * Look up a module's base address in a sorted list of pc-hits. Unlike 93 * nllookup(), this deals with misses by mapping them to the next *higher* 94 * pc-hit. This is so that we get into the module's first pc-hit rightaway, 95 * even if the module's entry-point (load_base) itself is not a hit. 96 */ 97 Address * 98 locate(Address *pclist, size_t nelem, Address keypc) 99 { 100 size_t low = 0, middle, high = nelem - 1; 101 102 if (keypc <= pclist[low]) 103 return (pclist); 104 105 if (keypc > pclist[high]) 106 return (NULL); 107 108 while (low != high) { 109 middle = (high + low) >> 1; 110 111 if ((pclist[middle] < keypc) && (pclist[middle + 1] >= keypc)) 112 return (&pclist[middle + 1]); 113 114 if (pclist[middle] >= keypc) 115 high = middle; 116 else 117 low = middle + 1; 118 } 119 120 /* must never reach here! */ 121 return (NULL); 122 } 123