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 /*
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #pragma ident "%Z%%M% %I% %E% SMI"
29
30 #include "gprof.h"
31
32 /*
33 * look up an address in a sorted-by-address namelist
34 * this deals with misses by mapping them to the next lower
35 * entry point.
36 */
37 static int searchmsg = 0; /* Emit the diagnostic only once */
38
39 nltype *
nllookup(mod_info_t * module,pctype address,pctype * nxtsym)40 nllookup(mod_info_t *module, pctype address, pctype *nxtsym)
41 {
42 size_t low = 0, middle, high = module->nname - 1;
43 pctype keyval;
44 nltype *mnl = module->nl;
45
46 /*
47 * If this is the program executable in which we are looking up
48 * a symbol, then the actual load address will be the same as the
49 * address specified in the ELF file. For shared objects, the
50 * load address may differ from what is specified in the file. In
51 * this case, we may need to look for a different value altogether.
52 */
53 keyval = module->txt_origin + (address - module->load_base);
54
55 if (keyval < mnl[low].value) {
56 if (nxtsym) {
57 *nxtsym = module->load_base +
58 (mnl[low].value - module->txt_origin);
59 }
60 return (NULL);
61 }
62
63 if (keyval >= mnl[high].value) {
64 if (nxtsym)
65 *nxtsym = module->load_end;
66 return (&mnl[high]);
67 }
68
69 while (low != high) {
70 middle = (high + low) >> 1;
71
72 if (mnl[middle].value <= keyval &&
73 mnl[middle + 1].value > keyval) {
74 if (nxtsym) {
75 *nxtsym = module->load_base +
76 (mnl[middle + 1].value -
77 module->txt_origin);
78 }
79 return (&mnl[middle]);
80 }
81
82 if (mnl[middle].value > keyval) {
83 high = middle;
84 } else {
85 low = middle + 1;
86 }
87 }
88
89 if (searchmsg++ == 0)
90 (void) fprintf(stderr, "[nllookup] binary search fails???\n");
91
92 /* must never reach here! */
93 return (0);
94 }
95
96 arctype *
arclookup(nltype * parentp,nltype * childp)97 arclookup(nltype *parentp, nltype *childp)
98 {
99 arctype *arcp;
100
101 if (parentp == 0 || childp == 0) {
102 (void) fprintf(stderr,
103 "[arclookup] parentp == 0 || childp == 0\n");
104 return (0);
105 }
106 #ifdef DEBUG
107 if (debug & LOOKUPDEBUG) {
108 (void) printf("[arclookup] parent %s child %s\n",
109 parentp->name, childp->name);
110 }
111 #endif /* DEBUG */
112
113 for (arcp = parentp->children; arcp; arcp = arcp->arc_childlist) {
114 #ifdef DEBUG
115 if (debug & LOOKUPDEBUG) {
116 (void) printf(
117 "[arclookup]\t arc_parent %s arc_child %s\n",
118 arcp->arc_parentp->name,
119 arcp->arc_childp->name);
120 }
121 #endif /* DEBUG */
122 if (arcp->arc_childp == childp) {
123 return (arcp);
124 }
125 }
126 return (0);
127 }
128