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