* ldcref.c (cref_fill_array): Call bfd_demangle rather than demangle.
[deliverable/binutils-gdb.git] / gprof / sym_ids.c
CommitLineData
ef368dac
NC
1/* sym_ids.c
2
d6a39701 3 Copyright 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
ef368dac
NC
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
44eb1801
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
ef368dac 21\f
252b5132 22#include "libiberty.h"
3882b010 23#include "safe-ctype.h"
6d9c411a
AM
24#include "gprof.h"
25#include "search_list.h"
26#include "source.h"
27#include "symtab.h"
252b5132
RH
28#include "cg_arcs.h"
29#include "sym_ids.h"
30
9e972ca0 31static struct sym_id
252b5132
RH
32 {
33 struct sym_id *next;
ef368dac 34 char *spec; /* Parsing modifies this. */
252b5132 35 Table_Id which_table;
b34976b6 36 bfd_boolean has_right;
0eee5820 37
252b5132
RH
38 struct match
39 {
ef368dac
NC
40 int prev_index; /* Index of prev match. */
41 Sym *prev_match; /* Previous match. */
42 Sym *first_match; /* Chain of all matches. */
252b5132
RH
43 Sym sym;
44 }
45 left, right;
46 }
47 *id_list;
48
b34976b6 49static void parse_spec
3e8f6abf 50 (char *, Sym *);
b34976b6 51static void parse_id
3e8f6abf 52 (struct sym_id *);
b34976b6 53static bfd_boolean match
3e8f6abf 54 (Sym *, Sym *);
b34976b6 55static void extend_match
3e8f6abf 56 (struct match *, Sym *, Sym_Table *, bfd_boolean);
1355568a
AM
57
58
252b5132
RH
59Sym_Table syms[NUM_TABLES];
60
61#ifdef DEBUG
9e972ca0 62static const char *table_name[] =
252b5132
RH
63{
64 "INCL_GRAPH", "EXCL_GRAPH",
65 "INCL_ARCS", "EXCL_ARCS",
66 "INCL_FLAT", "EXCL_FLAT",
67 "INCL_TIME", "EXCL_TIME",
68 "INCL_ANNO", "EXCL_ANNO",
69 "INCL_EXEC", "EXCL_EXEC"
70};
71#endif /* DEBUG */
72
ef368dac
NC
73/* This is the table in which we keep all the syms that match
74 the right half of an arc id. It is NOT sorted according
75 to the addresses, because it is accessed only through
76 the left half's CHILDREN pointers (so it's crucial not
77 to reorder this table once pointers into it exist). */
252b5132
RH
78static Sym_Table right_ids;
79
80static Source_File non_existent_file =
81{
8622e41b 82 0, "<non-existent-file>", 0, 0, 0, NULL
252b5132
RH
83};
84
85
86void
3e8f6abf 87sym_id_add (const char *spec, Table_Id which_table)
252b5132
RH
88{
89 struct sym_id *id;
90 int len = strlen (spec);
91
92 id = (struct sym_id *) xmalloc (sizeof (*id) + len + 1);
93 memset (id, 0, sizeof (*id));
94
95 id->spec = (char *) id + sizeof (*id);
96 strcpy (id->spec, spec);
97 id->which_table = which_table;
98
99 id->next = id_list;
100 id_list = id;
101}
102
103
ef368dac
NC
104/* A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
105 to the user, a spec without a colon is interpreted as:
0eee5820
AM
106
107 (i) a FILENAME if it contains a dot
108 (ii) a FUNCNAME if it starts with a non-digit character
109 (iii) a LINENUM if it starts with a digit
110
ef368dac
NC
111 A FUNCNAME containing a dot can be specified by :FUNCNAME, a
112 FILENAME not containing a dot can be specified by FILENAME. */
113
252b5132 114static void
3e8f6abf 115parse_spec (char *spec, Sym *sym)
252b5132
RH
116{
117 char *colon;
118
119 sym_init (sym);
120 colon = strrchr (spec, ':');
0eee5820 121
252b5132
RH
122 if (colon)
123 {
124 *colon = '\0';
0eee5820 125
252b5132
RH
126 if (colon > spec)
127 {
128 sym->file = source_file_lookup_name (spec);
0eee5820 129
252b5132 130 if (!sym->file)
ef368dac 131 sym->file = &non_existent_file;
252b5132 132 }
0eee5820 133
252b5132 134 spec = colon + 1;
0eee5820 135
252b5132
RH
136 if (strlen (spec))
137 {
3882b010 138 if (ISDIGIT (spec[0]))
ef368dac 139 sym->line_num = atoi (spec);
252b5132 140 else
ef368dac 141 sym->name = spec;
252b5132
RH
142 }
143 }
144 else if (strlen (spec))
145 {
ef368dac 146 /* No colon: spec is a filename if it contains a dot. */
252b5132
RH
147 if (strchr (spec, '.'))
148 {
149 sym->file = source_file_lookup_name (spec);
0eee5820 150
252b5132 151 if (!sym->file)
ef368dac 152 sym->file = &non_existent_file;
252b5132 153 }
3882b010 154 else if (ISDIGIT (*spec))
252b5132
RH
155 {
156 sym->line_num = atoi (spec);
157 }
158 else if (strlen (spec))
159 {
160 sym->name = spec;
161 }
162 }
163}
164
165
ef368dac
NC
166/* A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
167 by parse_spec(). */
168
252b5132 169static void
3e8f6abf 170parse_id (struct sym_id *id)
252b5132
RH
171{
172 char *slash;
173
174 DBG (IDDEBUG, printf ("[parse_id] %s -> ", id->spec));
175
176 slash = strchr (id->spec, '/');
177 if (slash)
178 {
179 parse_spec (slash + 1, &id->right.sym);
180 *slash = '\0';
b34976b6 181 id->has_right = TRUE;
252b5132
RH
182 }
183 parse_spec (id->spec, &id->left.sym);
184
185#ifdef DEBUG
186 if (debug_level & IDDEBUG)
187 {
188 printf ("%s:", id->left.sym.file ? id->left.sym.file->name : "*");
0eee5820 189
252b5132 190 if (id->left.sym.name)
ef368dac 191 printf ("%s", id->left.sym.name);
252b5132 192 else if (id->left.sym.line_num)
ef368dac 193 printf ("%d", id->left.sym.line_num);
252b5132 194 else
ef368dac 195 printf ("*");
0eee5820 196
252b5132
RH
197 if (id->has_right)
198 {
199 printf ("/%s:",
200 id->right.sym.file ? id->right.sym.file->name : "*");
0eee5820 201
252b5132 202 if (id->right.sym.name)
ef368dac 203 printf ("%s", id->right.sym.name);
252b5132 204 else if (id->right.sym.line_num)
ef368dac 205 printf ("%d", id->right.sym.line_num);
252b5132 206 else
ef368dac 207 printf ("*");
252b5132 208 }
0eee5820 209
252b5132
RH
210 printf ("\n");
211 }
212#endif
213}
214
215
ef368dac
NC
216/* Return TRUE iff PATTERN matches SYM. */
217
b34976b6 218static bfd_boolean
3e8f6abf 219match (Sym *pattern, Sym *sym)
252b5132 220{
b34976b6
AM
221 return (pattern->file ? pattern->file == sym->file : TRUE)
222 && (pattern->line_num ? pattern->line_num == sym->line_num : TRUE)
5af11cab
AM
223 && (pattern->name
224 ? strcmp (pattern->name,
225 sym->name+(discard_underscores && sym->name[0] == '_')) == 0
b34976b6 226 : TRUE);
252b5132
RH
227}
228
229
230static void
3e8f6abf 231extend_match (struct match *m, Sym *sym, Sym_Table *tab, bfd_boolean second_pass)
252b5132
RH
232{
233 if (m->prev_match != sym - 1)
234 {
ef368dac 235 /* Discontinuity: add new match to table. */
252b5132
RH
236 if (second_pass)
237 {
238 tab->base[tab->len] = *sym;
239 m->prev_index = tab->len;
240
ef368dac 241 /* Link match into match's chain. */
252b5132
RH
242 tab->base[tab->len].next = m->first_match;
243 m->first_match = &tab->base[tab->len];
244 }
0eee5820 245
252b5132
RH
246 ++tab->len;
247 }
248
ef368dac 249 /* Extend match to include this symbol. */
252b5132 250 if (second_pass)
ef368dac
NC
251 tab->base[m->prev_index].end_addr = sym->end_addr;
252
252b5132
RH
253 m->prev_match = sym;
254}
255
256
ef368dac
NC
257/* Go through sym_id list produced by option processing and fill
258 in the various symbol tables indicating what symbols should
259 be displayed or suppressed for the various kinds of outputs.
0eee5820 260
ef368dac
NC
261 This can potentially produce huge tables and in particulars
262 tons of arcs, but this happens only if the user makes silly
263 requests---you get what you ask for! */
264
252b5132 265void
1355568a 266sym_id_parse ()
252b5132
RH
267{
268 Sym *sym, *left, *right;
269 struct sym_id *id;
270 Sym_Table *tab;
271
ef368dac 272 /* Convert symbol ids into Syms, so we can deal with them more easily. */
252b5132 273 for (id = id_list; id; id = id->next)
ef368dac 274 parse_id (id);
252b5132 275
ef368dac 276 /* First determine size of each table. */
252b5132
RH
277 for (sym = symtab.base; sym < symtab.limit; ++sym)
278 {
279 for (id = id_list; id; id = id->next)
280 {
281 if (match (&id->left.sym, sym))
b34976b6 282 extend_match (&id->left, sym, &syms[id->which_table], FALSE);
ef368dac 283
252b5132 284 if (id->has_right && match (&id->right.sym, sym))
b34976b6 285 extend_match (&id->right, sym, &right_ids, FALSE);
252b5132
RH
286 }
287 }
288
ef368dac 289 /* Create tables of appropriate size and reset lengths. */
252b5132
RH
290 for (tab = syms; tab < &syms[NUM_TABLES]; ++tab)
291 {
292 if (tab->len)
293 {
294 tab->base = (Sym *) xmalloc (tab->len * sizeof (Sym));
295 tab->limit = tab->base + tab->len;
296 tab->len = 0;
297 }
298 }
0eee5820 299
252b5132
RH
300 if (right_ids.len)
301 {
302 right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym));
303 right_ids.limit = right_ids.base + right_ids.len;
304 right_ids.len = 0;
305 }
306
ef368dac 307 /* Make a second pass through symtab, creating syms as necessary. */
252b5132
RH
308 for (sym = symtab.base; sym < symtab.limit; ++sym)
309 {
310 for (id = id_list; id; id = id->next)
311 {
312 if (match (&id->left.sym, sym))
b34976b6 313 extend_match (&id->left, sym, &syms[id->which_table], TRUE);
ef368dac 314
252b5132 315 if (id->has_right && match (&id->right.sym, sym))
b34976b6 316 extend_match (&id->right, sym, &right_ids, TRUE);
252b5132
RH
317 }
318 }
319
ef368dac 320 /* Go through ids creating arcs as needed. */
252b5132
RH
321 for (id = id_list; id; id = id->next)
322 {
323 if (id->has_right)
324 {
325 for (left = id->left.first_match; left; left = left->next)
326 {
327 for (right = id->right.first_match; right; right = right->next)
328 {
329 DBG (IDDEBUG,
330 printf (
331 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
332 left->file ? left->file->name : "*",
fdcf7d43
ILT
333 left->name ? left->name : "*",
334 (unsigned long) left->addr,
335 (unsigned long) left->end_addr,
252b5132 336 right->file ? right->file->name : "*",
fdcf7d43
ILT
337 right->name ? right->name : "*",
338 (unsigned long) right->addr,
339 (unsigned long) right->end_addr,
252b5132 340 table_name[id->which_table]));
0eee5820 341
252b5132
RH
342 arc_add (left, right, (unsigned long) 0);
343 }
344 }
345 }
346 }
347
ef368dac 348 /* Finally, we can sort the tables and we're done. */
252b5132
RH
349 for (tab = &syms[0]; tab < &syms[NUM_TABLES]; ++tab)
350 {
351 DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n",
352 table_name[tab - &syms[0]]));
353 symtab_finalize (tab);
354 }
355}
356
357
ef368dac
NC
358/* Symbol tables storing the FROM symbols of arcs do not necessarily
359 have distinct address ranges. For example, somebody might request
360 -k /_mcount to suppress any arcs into _mcount, while at the same
361 time requesting -k a/b. Fortunately, those symbol tables don't get
362 very big (the user has to type them!), so a linear search is probably
363 tolerable. */
b34976b6 364bfd_boolean
3e8f6abf 365sym_id_arc_is_present (Sym_Table *sym_tab, Sym *from, Sym *to)
252b5132
RH
366{
367 Sym *sym;
368
1355568a 369 for (sym = sym_tab->base; sym < sym_tab->limit; ++sym)
252b5132
RH
370 {
371 if (from->addr >= sym->addr && from->addr <= sym->end_addr
372 && arc_lookup (sym, to))
b34976b6 373 return TRUE;
252b5132 374 }
0eee5820 375
b34976b6 376 return FALSE;
252b5132 377}
This page took 0.308928 seconds and 4 git commands to generate.