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