source: trunk/src/binutils/gprof/symtab.c@ 106

Last change on this file since 106 was 10, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 7.0 KB
Line 
1/* symtab.c
2
3 Copyright 2000, 2001 Free Software Foundation, Inc.
4
5 This file is part of GNU Binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22
23#include "gprof.h"
24#include "cg_arcs.h"
25#include "corefile.h"
26#include "symtab.h"
27
28Sym_Table symtab;
29
30
31/* Initialize a symbol (so it's empty). */
32
33void
34DEFUN (sym_init, (sym), Sym * sym)
35{
36 memset (sym, 0, sizeof (*sym));
37
38 /* It is not safe to assume that a binary zero corresponds
39 to a floating-point 0.0, so initialize floats explicitly. */
40 sym->hist.time = 0.0;
41 sym->cg.child_time = 0.0;
42 sym->cg.prop.fract = 0.0;
43 sym->cg.prop.self = 0.0;
44 sym->cg.prop.child = 0.0;
45}
46
47
48/* Compare the function entry-point of two symbols and return <0, =0,
49 or >0 depending on whether the left value is smaller than, equal
50 to, or greater than the right value. If two symbols are equal
51 but one has is_func set and the other doesn't, we make the
52 non-function symbol one "bigger" so that the function symbol will
53 survive duplicate removal. Finally, if both symbols have the
54 same is_func value, we discriminate against is_static such that
55 the global symbol survives. */
56
57static int
58DEFUN (cmp_addr, (lp, rp), const PTR lp AND const PTR rp)
59{
60 Sym *left = (Sym *) lp;
61 Sym *right = (Sym *) rp;
62
63 if (left->addr > right->addr)
64 return 1;
65 else if (left->addr < right->addr)
66 return -1;
67
68 if (left->is_func != right->is_func)
69 return right->is_func - left->is_func;
70
71 return left->is_static - right->is_static;
72}
73
74
75void
76DEFUN (symtab_finalize, (tab), Sym_Table * tab)
77{
78 Sym *src, *dst;
79 bfd_vma prev_addr;
80
81 if (!tab->len)
82 return;
83
84 /* Sort symbol table in order of increasing function addresses. */
85 qsort (tab->base, tab->len, sizeof (Sym), cmp_addr);
86
87 /* Remove duplicate entries to speed-up later processing and
88 set end_addr if its not set yet. */
89 prev_addr = tab->base[0].addr + 1;
90
91 for (src = dst = tab->base; src < tab->limit; ++src)
92 {
93 if (src->addr == prev_addr)
94 {
95 /* If same address, favor global symbol over static one,
96 then function over line number. If both symbols are
97 either static or global and either function or line, check
98 whether one has name beginning with underscore while
99 the other doesn't. In such cases, keep sym without
100 underscore. This takes cares of compiler generated
101 symbols (such as __gnu_compiled, __c89_used, etc.). */
102 if ((!src->is_static && dst[-1].is_static)
103 || ((src->is_static == dst[-1].is_static)
104 && ((src->is_func && !dst[-1].is_func)
105 || ((src->is_func == dst[-1].is_func)
106 && ((src->name[0] != '_' && dst[-1].name[0] == '_')
107 || (src->name[0]
108 && src->name[1] != '_'
109 && dst[-1].name[1] == '_'))))))
110 {
111 DBG (AOUTDEBUG | IDDEBUG,
112 printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
113 src->name, src->is_static ? 't' : 'T',
114 src->is_func ? 'F' : 'f',
115 dst[-1].name, dst[-1].is_static ? 't' : 'T',
116 dst[-1].is_func ? 'F' : 'f');
117 printf (" (addr=%lx)\n", (unsigned long) src->addr));
118
119 dst[-1] = *src;
120 }
121 else
122 {
123 DBG (AOUTDEBUG | IDDEBUG,
124 printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
125 dst[-1].name, dst[-1].is_static ? 't' : 'T',
126 dst[-1].is_func ? 'F' : 'f',
127 src->name, src->is_static ? 't' : 'T',
128 src->is_func ? 'F' : 'f');
129 printf (" (addr=%lx)\n", (unsigned long) src->addr));
130 }
131 }
132 else
133 {
134 if (dst > tab->base && dst[-1].end_addr == 0)
135 dst[-1].end_addr = src->addr - 1;
136
137 /* Retain sym only if it has a non-empty address range. */
138 if (!src->end_addr || src->addr <= src->end_addr)
139 {
140 *dst = *src;
141 dst++;
142 prev_addr = src->addr;
143 }
144 }
145 }
146
147 if (tab->len > 0 && dst[-1].end_addr == 0)
148 dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1;
149
150 DBG (AOUTDEBUG | IDDEBUG,
151 printf ("[symtab_finalize]: removed %d duplicate entries\n",
152 tab->len - (int) (dst - tab->base)));
153
154 tab->limit = dst;
155 tab->len = tab->limit - tab->base;
156
157 DBG (AOUTDEBUG | IDDEBUG,
158 unsigned int j;
159
160 for (j = 0; j < tab->len; ++j)
161 {
162 printf ("[symtab_finalize] 0x%lx-0x%lx\t%s\n",
163 (long) tab->base[j].addr, (long) tab->base[j].end_addr,
164 tab->base[j].name);
165 }
166 );
167}
168
169
170#ifdef DEBUG
171
172Sym *
173DEFUN (dbg_sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
174{
175 long low, mid, high;
176 Sym *sym;
177
178 fprintf (stderr, "[dbg_sym_lookup] address 0x%lx\n",
179 (unsigned long) address);
180
181 sym = symtab->base;
182 for (low = 0, high = symtab->len - 1; low != high;)
183 {
184 mid = (high + low) >> 1;
185
186 fprintf (stderr, "[dbg_sym_lookup] low=0x%lx, mid=0x%lx, high=0x%lx\n",
187 low, mid, high);
188 fprintf (stderr, "[dbg_sym_lookup] sym[m]=0x%lx sym[m + 1]=0x%lx\n",
189 (unsigned long) sym[mid].addr,
190 (unsigned long) sym[mid + 1].addr);
191
192 if (sym[mid].addr <= address && sym[mid + 1].addr > address)
193 return &sym[mid];
194
195 if (sym[mid].addr > address)
196 high = mid;
197 else
198 low = mid + 1;
199 }
200
201 fprintf (stderr, "[dbg_sym_lookup] binary search fails???\n");
202
203 return 0;
204}
205
206#endif /* DEBUG */
207
208
209/* Look up an address in the symbol-table that is sorted by address.
210 If address does not hit any symbol, 0 is returned. */
211Sym *
212DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
213{
214 long low, high;
215 long mid = -1;
216 Sym *sym;
217#ifdef DEBUG
218 int probes = 0;
219#endif /* DEBUG */
220
221 if (!symtab->len)
222 return 0;
223
224 sym = symtab->base;
225 for (low = 0, high = symtab->len - 1; low != high;)
226 {
227 DBG (LOOKUPDEBUG, ++probes);
228 mid = (high + low) / 2;
229
230 if (sym[mid].addr <= address && sym[mid + 1].addr > address)
231 {
232 if (address > sym[mid].end_addr)
233 {
234 /* Address falls into gap between
235 sym[mid] and sym[mid + 1]. */
236 return 0;
237 }
238 else
239 {
240 DBG (LOOKUPDEBUG,
241 printf ("[sym_lookup] %d probes (symtab->len=%u)\n",
242 probes, symtab->len - 1));
243 return &sym[mid];
244 }
245 }
246
247 if (sym[mid].addr > address)
248 high = mid;
249 else
250 low = mid + 1;
251 }
252
253 if (sym[mid + 1].addr <= address)
254 {
255 if (address > sym[mid + 1].end_addr)
256 {
257 /* Address is beyond end of sym[mid + 1]. */
258 return 0;
259 }
260 else
261 {
262 DBG (LOOKUPDEBUG, printf ("[sym_lookup] %d (%u) probes, fall off\n",
263 probes, symtab->len - 1));
264 return &sym[mid + 1];
265 }
266 }
267
268 return 0;
269}
Note: See TracBrowser for help on using the repository browser.