* interp.c (sim_open): Disable chunk of code that wrote code in
[deliverable/binutils-gdb.git] / gprof / sym_ids.c
CommitLineData
ef368dac
NC
1/* sym_ids.c
2
1355568a 3 Copyright 2000, 2001, 2002 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
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
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
31struct sym_id
32 {
33 struct sym_id *next;
ef368dac 34 char *spec; /* Parsing modifies this. */
252b5132 35 Table_Id which_table;
bde52789 36 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
1355568a
AM
49static void parse_spec PARAMS ((char *, Sym *));
50static void parse_id PARAMS ((struct sym_id *));
51static boolean match PARAMS ((Sym *, Sym *));
52static void extend_match PARAMS ((struct match *, Sym *, Sym_Table *, boolean));
53
54
252b5132
RH
55Sym_Table syms[NUM_TABLES];
56
57#ifdef DEBUG
58const char *table_name[] =
59{
60 "INCL_GRAPH", "EXCL_GRAPH",
61 "INCL_ARCS", "EXCL_ARCS",
62 "INCL_FLAT", "EXCL_FLAT",
63 "INCL_TIME", "EXCL_TIME",
64 "INCL_ANNO", "EXCL_ANNO",
65 "INCL_EXEC", "EXCL_EXEC"
66};
67#endif /* DEBUG */
68
ef368dac
NC
69/* This is the table in which we keep all the syms that match
70 the right half of an arc id. It is NOT sorted according
71 to the addresses, because it is accessed only through
72 the left half's CHILDREN pointers (so it's crucial not
73 to reorder this table once pointers into it exist). */
252b5132
RH
74static Sym_Table right_ids;
75
76static Source_File non_existent_file =
77{
8622e41b 78 0, "<non-existent-file>", 0, 0, 0, NULL
252b5132
RH
79};
80
81
82void
1355568a
AM
83sym_id_add (spec, which_table)
84 const char *spec;
85 Table_Id which_table;
252b5132
RH
86{
87 struct sym_id *id;
88 int len = strlen (spec);
89
90 id = (struct sym_id *) xmalloc (sizeof (*id) + len + 1);
91 memset (id, 0, sizeof (*id));
92
93 id->spec = (char *) id + sizeof (*id);
94 strcpy (id->spec, spec);
95 id->which_table = which_table;
96
97 id->next = id_list;
98 id_list = id;
99}
100
101
ef368dac
NC
102/* A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
103 to the user, a spec without a colon is interpreted as:
0eee5820
AM
104
105 (i) a FILENAME if it contains a dot
106 (ii) a FUNCNAME if it starts with a non-digit character
107 (iii) a LINENUM if it starts with a digit
108
ef368dac
NC
109 A FUNCNAME containing a dot can be specified by :FUNCNAME, a
110 FILENAME not containing a dot can be specified by FILENAME. */
111
252b5132 112static void
1355568a
AM
113parse_spec (spec, sym)
114 char *spec;
115 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
1355568a
AM
170parse_id (id)
171 struct sym_id *id;
252b5132
RH
172{
173 char *slash;
174
175 DBG (IDDEBUG, printf ("[parse_id] %s -> ", id->spec));
176
177 slash = strchr (id->spec, '/');
178 if (slash)
179 {
180 parse_spec (slash + 1, &id->right.sym);
181 *slash = '\0';
bde52789 182 id->has_right = true;
252b5132
RH
183 }
184 parse_spec (id->spec, &id->left.sym);
185
186#ifdef DEBUG
187 if (debug_level & IDDEBUG)
188 {
189 printf ("%s:", id->left.sym.file ? id->left.sym.file->name : "*");
0eee5820 190
252b5132 191 if (id->left.sym.name)
ef368dac 192 printf ("%s", id->left.sym.name);
252b5132 193 else if (id->left.sym.line_num)
ef368dac 194 printf ("%d", id->left.sym.line_num);
252b5132 195 else
ef368dac 196 printf ("*");
0eee5820 197
252b5132
RH
198 if (id->has_right)
199 {
200 printf ("/%s:",
201 id->right.sym.file ? id->right.sym.file->name : "*");
0eee5820 202
252b5132 203 if (id->right.sym.name)
ef368dac 204 printf ("%s", id->right.sym.name);
252b5132 205 else if (id->right.sym.line_num)
ef368dac 206 printf ("%d", id->right.sym.line_num);
252b5132 207 else
ef368dac 208 printf ("*");
252b5132 209 }
0eee5820 210
252b5132
RH
211 printf ("\n");
212 }
213#endif
214}
215
216
ef368dac
NC
217/* Return TRUE iff PATTERN matches SYM. */
218
bde52789 219static boolean
1355568a
AM
220match (pattern, sym)
221 Sym *pattern;
222 Sym *sym;
252b5132 223{
bde52789
AM
224 return (pattern->file ? pattern->file == sym->file : true)
225 && (pattern->line_num ? pattern->line_num == sym->line_num : true)
5af11cab
AM
226 && (pattern->name
227 ? strcmp (pattern->name,
228 sym->name+(discard_underscores && sym->name[0] == '_')) == 0
bde52789 229 : true);
252b5132
RH
230}
231
232
233static void
1355568a
AM
234extend_match (m, sym, tab, second_pass)
235 struct match *m;
236 Sym *sym;
237 Sym_Table *tab;
238 boolean second_pass;
252b5132
RH
239{
240 if (m->prev_match != sym - 1)
241 {
ef368dac 242 /* Discontinuity: add new match to table. */
252b5132
RH
243 if (second_pass)
244 {
245 tab->base[tab->len] = *sym;
246 m->prev_index = tab->len;
247
ef368dac 248 /* Link match into match's chain. */
252b5132
RH
249 tab->base[tab->len].next = m->first_match;
250 m->first_match = &tab->base[tab->len];
251 }
0eee5820 252
252b5132
RH
253 ++tab->len;
254 }
255
ef368dac 256 /* Extend match to include this symbol. */
252b5132 257 if (second_pass)
ef368dac
NC
258 tab->base[m->prev_index].end_addr = sym->end_addr;
259
252b5132
RH
260 m->prev_match = sym;
261}
262
263
ef368dac
NC
264/* Go through sym_id list produced by option processing and fill
265 in the various symbol tables indicating what symbols should
266 be displayed or suppressed for the various kinds of outputs.
0eee5820 267
ef368dac
NC
268 This can potentially produce huge tables and in particulars
269 tons of arcs, but this happens only if the user makes silly
270 requests---you get what you ask for! */
271
252b5132 272void
1355568a 273sym_id_parse ()
252b5132
RH
274{
275 Sym *sym, *left, *right;
276 struct sym_id *id;
277 Sym_Table *tab;
278
ef368dac 279 /* Convert symbol ids into Syms, so we can deal with them more easily. */
252b5132 280 for (id = id_list; id; id = id->next)
ef368dac 281 parse_id (id);
252b5132 282
ef368dac 283 /* First determine size of each table. */
252b5132
RH
284 for (sym = symtab.base; sym < symtab.limit; ++sym)
285 {
286 for (id = id_list; id; id = id->next)
287 {
288 if (match (&id->left.sym, sym))
bde52789 289 extend_match (&id->left, sym, &syms[id->which_table], false);
ef368dac 290
252b5132 291 if (id->has_right && match (&id->right.sym, sym))
bde52789 292 extend_match (&id->right, sym, &right_ids, false);
252b5132
RH
293 }
294 }
295
ef368dac 296 /* Create tables of appropriate size and reset lengths. */
252b5132
RH
297 for (tab = syms; tab < &syms[NUM_TABLES]; ++tab)
298 {
299 if (tab->len)
300 {
301 tab->base = (Sym *) xmalloc (tab->len * sizeof (Sym));
302 tab->limit = tab->base + tab->len;
303 tab->len = 0;
304 }
305 }
0eee5820 306
252b5132
RH
307 if (right_ids.len)
308 {
309 right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym));
310 right_ids.limit = right_ids.base + right_ids.len;
311 right_ids.len = 0;
312 }
313
ef368dac 314 /* Make a second pass through symtab, creating syms as necessary. */
252b5132
RH
315 for (sym = symtab.base; sym < symtab.limit; ++sym)
316 {
317 for (id = id_list; id; id = id->next)
318 {
319 if (match (&id->left.sym, sym))
bde52789 320 extend_match (&id->left, sym, &syms[id->which_table], true);
ef368dac 321
252b5132 322 if (id->has_right && match (&id->right.sym, sym))
bde52789 323 extend_match (&id->right, sym, &right_ids, true);
252b5132
RH
324 }
325 }
326
ef368dac 327 /* Go through ids creating arcs as needed. */
252b5132
RH
328 for (id = id_list; id; id = id->next)
329 {
330 if (id->has_right)
331 {
332 for (left = id->left.first_match; left; left = left->next)
333 {
334 for (right = id->right.first_match; right; right = right->next)
335 {
336 DBG (IDDEBUG,
337 printf (
338 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
339 left->file ? left->file->name : "*",
fdcf7d43
ILT
340 left->name ? left->name : "*",
341 (unsigned long) left->addr,
342 (unsigned long) left->end_addr,
252b5132 343 right->file ? right->file->name : "*",
fdcf7d43
ILT
344 right->name ? right->name : "*",
345 (unsigned long) right->addr,
346 (unsigned long) right->end_addr,
252b5132 347 table_name[id->which_table]));
0eee5820 348
252b5132
RH
349 arc_add (left, right, (unsigned long) 0);
350 }
351 }
352 }
353 }
354
ef368dac 355 /* Finally, we can sort the tables and we're done. */
252b5132
RH
356 for (tab = &syms[0]; tab < &syms[NUM_TABLES]; ++tab)
357 {
358 DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n",
359 table_name[tab - &syms[0]]));
360 symtab_finalize (tab);
361 }
362}
363
364
ef368dac
NC
365/* Symbol tables storing the FROM symbols of arcs do not necessarily
366 have distinct address ranges. For example, somebody might request
367 -k /_mcount to suppress any arcs into _mcount, while at the same
368 time requesting -k a/b. Fortunately, those symbol tables don't get
369 very big (the user has to type them!), so a linear search is probably
370 tolerable. */
bde52789 371boolean
1355568a
AM
372sym_id_arc_is_present (sym_tab, from, to)
373 Sym_Table *sym_tab;
374 Sym *from;
375 Sym *to;
252b5132
RH
376{
377 Sym *sym;
378
1355568a 379 for (sym = sym_tab->base; sym < sym_tab->limit; ++sym)
252b5132
RH
380 {
381 if (from->addr >= sym->addr && from->addr <= sym->end_addr
382 && arc_lookup (sym, to))
bde52789 383 return true;
252b5132 384 }
0eee5820 385
bde52789 386 return false;
252b5132 387}
This page took 0.140692 seconds and 4 git commands to generate.