2001-05-28 Philip Blundell <philb@gnu.org>
[binutils.git] / gprof / symtab.c
blobac9e95f7ab290562da9d66fe70ba16bcce47c65c
1 /* symtab.c
3 Copyright (C) 2000 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
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.
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.
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. */
22 #include "gprof.h"
23 #include "cg_arcs.h"
24 #include "corefile.h"
25 #include "symtab.h"
27 Sym_Table symtab;
30 /* Initialize a symbol (so it's empty). */
32 void
33 DEFUN (sym_init, (sym), Sym * sym)
35 memset (sym, 0, sizeof (*sym));
37 /* It is not safe to assume that a binary zero corresponds
38 to a floating-point 0.0, so initialize floats explicitly. */
39 sym->hist.time = 0.0;
40 sym->cg.child_time = 0.0;
41 sym->cg.prop.fract = 0.0;
42 sym->cg.prop.self = 0.0;
43 sym->cg.prop.child = 0.0;
47 /* Compare the function entry-point of two symbols and return <0, =0,
48 or >0 depending on whether the left value is smaller than, equal
49 to, or greater than the right value. If two symbols are equal
50 but one has is_func set and the other doesn't, we make the
51 non-function symbol one "bigger" so that the function symbol will
52 survive duplicate removal. Finally, if both symbols have the
53 same is_func value, we discriminate against is_static such that
54 the global symbol survives. */
56 static int
57 DEFUN (cmp_addr, (lp, rp), const PTR lp AND const PTR rp)
59 Sym *left = (Sym *) lp;
60 Sym *right = (Sym *) rp;
62 if (left->addr > right->addr)
63 return 1;
64 else if (left->addr < right->addr)
65 return -1;
67 if (left->is_func != right->is_func)
68 return right->is_func - left->is_func;
70 return left->is_static - right->is_static;
74 void
75 DEFUN (symtab_finalize, (tab), Sym_Table * tab)
77 Sym *src, *dst;
78 bfd_vma prev_addr;
80 if (!tab->len)
81 return;
83 /* Sort symbol table in order of increasing function addresses. */
84 qsort (tab->base, tab->len, sizeof (Sym), cmp_addr);
86 /* Remove duplicate entries to speed-up later processing and
87 set end_addr if its not set yet. */
88 prev_addr = tab->base[0].addr + 1;
90 for (src = dst = tab->base; src < tab->limit; ++src)
92 if (src->addr == prev_addr)
94 /* If same address, favor global symbol over static one,
95 then function over line number. If both symbols are
96 either static or global and either function or line, check
97 whether one has name beginning with underscore while
98 the other doesn't. In such cases, keep sym without
99 underscore. This takes cares of compiler generated
100 symbols (such as __gnu_compiled, __c89_used, etc.). */
101 if ((!src->is_static && dst[-1].is_static)
102 || ((src->is_static == dst[-1].is_static)
103 && ((src->is_func && !dst[-1].is_func)
104 || ((src->is_func == dst[-1].is_func)
105 && ((src->name[0] != '_' && dst[-1].name[0] == '_')
106 || (src->name[0]
107 && src->name[1] != '_'
108 && dst[-1].name[1] == '_'))))))
110 DBG (AOUTDEBUG | IDDEBUG,
111 printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
112 src->name, src->is_static ? 't' : 'T',
113 src->is_func ? 'F' : 'f',
114 dst[-1].name, dst[-1].is_static ? 't' : 'T',
115 dst[-1].is_func ? 'F' : 'f');
116 printf (" (addr=%lx)\n", (unsigned long) src->addr));
118 dst[-1] = *src;
120 else
122 DBG (AOUTDEBUG | IDDEBUG,
123 printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
124 dst[-1].name, dst[-1].is_static ? 't' : 'T',
125 dst[-1].is_func ? 'F' : 'f',
126 src->name, src->is_static ? 't' : 'T',
127 src->is_func ? 'F' : 'f');
128 printf (" (addr=%lx)\n", (unsigned long) src->addr));
131 else
133 if (dst > tab->base && dst[-1].end_addr == 0)
134 dst[-1].end_addr = src->addr - 1;
136 /* Retain sym only if it has a non-empty address range. */
137 if (!src->end_addr || src->addr <= src->end_addr)
139 *dst = *src;
140 dst++;
141 prev_addr = src->addr;
146 if (tab->len > 0 && dst[-1].end_addr == 0)
147 dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1;
149 DBG (AOUTDEBUG | IDDEBUG,
150 printf ("[symtab_finalize]: removed %d duplicate entries\n",
151 tab->len - (int) (dst - tab->base)));
153 tab->limit = dst;
154 tab->len = tab->limit - tab->base;
156 DBG (AOUTDEBUG | IDDEBUG,
157 unsigned int j;
159 for (j = 0; j < tab->len; ++j)
161 printf ("[symtab_finalize] 0x%lx-0x%lx\t%s\n",
162 (long) tab->base[j].addr, (long) tab->base[j].end_addr,
163 tab->base[j].name);
169 #ifdef DEBUG
171 Sym *
172 DEFUN (dbg_sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
174 long low, mid, high;
175 Sym *sym;
177 fprintf (stderr, "[dbg_sym_lookup] address 0x%lx\n",
178 (unsigned long) address);
180 sym = symtab->base;
181 for (low = 0, high = symtab->len - 1; low != high;)
183 mid = (high + low) >> 1;
185 fprintf (stderr, "[dbg_sym_lookup] low=0x%lx, mid=0x%lx, high=0x%lx\n",
186 low, mid, high);
187 fprintf (stderr, "[dbg_sym_lookup] sym[m]=0x%lx sym[m + 1]=0x%lx\n",
188 (unsigned long) sym[mid].addr,
189 (unsigned long) sym[mid + 1].addr);
191 if (sym[mid].addr <= address && sym[mid + 1].addr > address)
192 return &sym[mid];
194 if (sym[mid].addr > address)
195 high = mid;
196 else
197 low = mid + 1;
200 fprintf (stderr, "[dbg_sym_lookup] binary search fails???\n");
202 return 0;
205 #endif /* DEBUG */
208 /* Look up an address in the symbol-table that is sorted by address.
209 If address does not hit any symbol, 0 is returned. */
210 Sym *
211 DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
213 long low, high;
214 long mid = -1;
215 Sym *sym;
216 #ifdef DEBUG
217 int probes = 0;
218 #endif /* DEBUG */
220 if (!symtab->len)
221 return 0;
223 sym = symtab->base;
224 for (low = 0, high = symtab->len - 1; low != high;)
226 DBG (LOOKUPDEBUG, ++probes);
227 mid = (high + low) / 2;
229 if (sym[mid].addr <= address && sym[mid + 1].addr > address)
231 if (address > sym[mid].end_addr)
233 /* Address falls into gap between
234 sym[mid] and sym[mid + 1]. */
235 return 0;
237 else
239 DBG (LOOKUPDEBUG,
240 printf ("[sym_lookup] %d probes (symtab->len=%u)\n",
241 probes, symtab->len - 1));
242 return &sym[mid];
246 if (sym[mid].addr > address)
247 high = mid;
248 else
249 low = mid + 1;
252 if (sym[mid + 1].addr <= address)
254 if (address > sym[mid + 1].end_addr)
256 /* Address is beyond end of sym[mid + 1]. */
257 return 0;
259 else
261 DBG (LOOKUPDEBUG, printf ("[sym_lookup] %d (%u) probes, fall off\n",
262 probes, symtab->len - 1));
263 return &sym[mid + 1];
267 return 0;