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