source: branches/libc-0.6/src/binutils/gprof/symtab.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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