]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gprof/sym_ids.c
* lib/insight-support.exp (_gdbtk_export_target_info): Add
[thirdparty/binutils-gdb.git] / gprof / sym_ids.c
CommitLineData
ef368dac
NC
1/* sym_ids.c
2
0eee5820 3 Copyright 2000, 2001 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
RH
22#include <ctype.h>
23
24#include "libiberty.h"
25#include "cg_arcs.h"
26#include "sym_ids.h"
27
28struct sym_id
29 {
30 struct sym_id *next;
ef368dac 31 char *spec; /* Parsing modifies this. */
252b5132
RH
32 Table_Id which_table;
33 bool has_right;
0eee5820 34
252b5132
RH
35 struct match
36 {
ef368dac
NC
37 int prev_index; /* Index of prev match. */
38 Sym *prev_match; /* Previous match. */
39 Sym *first_match; /* Chain of all matches. */
252b5132
RH
40 Sym sym;
41 }
42 left, right;
43 }
44 *id_list;
45
46Sym_Table syms[NUM_TABLES];
47
48#ifdef DEBUG
49const 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
ef368dac
NC
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). */
252b5132
RH
65static Sym_Table right_ids;
66
67static Source_File non_existent_file =
68{
8622e41b 69 0, "<non-existent-file>", 0, 0, 0, NULL
252b5132
RH
70};
71
72
73void
74DEFUN (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
ef368dac
NC
92/* A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
93 to the user, a spec without a colon is interpreted as:
0eee5820
AM
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
ef368dac
NC
99 A FUNCNAME containing a dot can be specified by :FUNCNAME, a
100 FILENAME not containing a dot can be specified by FILENAME. */
101
252b5132
RH
102static void
103DEFUN (parse_spec, (spec, sym), char *spec AND Sym * sym)
104{
105 char *colon;
106
107 sym_init (sym);
108 colon = strrchr (spec, ':');
0eee5820 109
252b5132
RH
110 if (colon)
111 {
112 *colon = '\0';
0eee5820 113
252b5132
RH
114 if (colon > spec)
115 {
116 sym->file = source_file_lookup_name (spec);
0eee5820 117
252b5132 118 if (!sym->file)
ef368dac 119 sym->file = &non_existent_file;
252b5132 120 }
0eee5820 121
252b5132 122 spec = colon + 1;
0eee5820 123
252b5132
RH
124 if (strlen (spec))
125 {
126 if (isdigit ((unsigned char) spec[0]))
ef368dac 127 sym->line_num = atoi (spec);
252b5132 128 else
ef368dac 129 sym->name = spec;
252b5132
RH
130 }
131 }
132 else if (strlen (spec))
133 {
ef368dac 134 /* No colon: spec is a filename if it contains a dot. */
252b5132
RH
135 if (strchr (spec, '.'))
136 {
137 sym->file = source_file_lookup_name (spec);
0eee5820 138
252b5132 139 if (!sym->file)
ef368dac 140 sym->file = &non_existent_file;
252b5132
RH
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
ef368dac
NC
154/* A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
155 by parse_spec(). */
156
252b5132
RH
157static void
158DEFUN (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 : "*");
0eee5820 177
252b5132 178 if (id->left.sym.name)
ef368dac 179 printf ("%s", id->left.sym.name);
252b5132 180 else if (id->left.sym.line_num)
ef368dac 181 printf ("%d", id->left.sym.line_num);
252b5132 182 else
ef368dac 183 printf ("*");
0eee5820 184
252b5132
RH
185 if (id->has_right)
186 {
187 printf ("/%s:",
188 id->right.sym.file ? id->right.sym.file->name : "*");
0eee5820 189
252b5132 190 if (id->right.sym.name)
ef368dac 191 printf ("%s", id->right.sym.name);
252b5132 192 else if (id->right.sym.line_num)
ef368dac 193 printf ("%d", id->right.sym.line_num);
252b5132 194 else
ef368dac 195 printf ("*");
252b5132 196 }
0eee5820 197
252b5132
RH
198 printf ("\n");
199 }
200#endif
201}
202
203
ef368dac
NC
204/* Return TRUE iff PATTERN matches SYM. */
205
252b5132
RH
206static bool
207DEFUN (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)
5af11cab
AM
211 && (pattern->name
212 ? strcmp (pattern->name,
213 sym->name+(discard_underscores && sym->name[0] == '_')) == 0
214 : TRUE);
252b5132
RH
215}
216
217
218static void
219DEFUN (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 {
ef368dac 224 /* Discontinuity: add new match to table. */
252b5132
RH
225 if (second_pass)
226 {
227 tab->base[tab->len] = *sym;
228 m->prev_index = tab->len;
229
ef368dac 230 /* Link match into match's chain. */
252b5132
RH
231 tab->base[tab->len].next = m->first_match;
232 m->first_match = &tab->base[tab->len];
233 }
0eee5820 234
252b5132
RH
235 ++tab->len;
236 }
237
ef368dac 238 /* Extend match to include this symbol. */
252b5132 239 if (second_pass)
ef368dac
NC
240 tab->base[m->prev_index].end_addr = sym->end_addr;
241
252b5132
RH
242 m->prev_match = sym;
243}
244
245
ef368dac
NC
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.
0eee5820 249
ef368dac
NC
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
252b5132
RH
254void
255DEFUN_VOID (sym_id_parse)
256{
257 Sym *sym, *left, *right;
258 struct sym_id *id;
259 Sym_Table *tab;
260
ef368dac 261 /* Convert symbol ids into Syms, so we can deal with them more easily. */
252b5132 262 for (id = id_list; id; id = id->next)
ef368dac 263 parse_id (id);
252b5132 264
ef368dac 265 /* First determine size of each table. */
252b5132
RH
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))
ef368dac
NC
271 extend_match (&id->left, sym, &syms[id->which_table], FALSE);
272
252b5132 273 if (id->has_right && match (&id->right.sym, sym))
ef368dac 274 extend_match (&id->right, sym, &right_ids, FALSE);
252b5132
RH
275 }
276 }
277
ef368dac 278 /* Create tables of appropriate size and reset lengths. */
252b5132
RH
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 }
0eee5820 288
252b5132
RH
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
ef368dac 296 /* Make a second pass through symtab, creating syms as necessary. */
252b5132
RH
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))
ef368dac
NC
302 extend_match (&id->left, sym, &syms[id->which_table], TRUE);
303
252b5132 304 if (id->has_right && match (&id->right.sym, sym))
ef368dac 305 extend_match (&id->right, sym, &right_ids, TRUE);
252b5132
RH
306 }
307 }
308
ef368dac 309 /* Go through ids creating arcs as needed. */
252b5132
RH
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 : "*",
fdcf7d43
ILT
322 left->name ? left->name : "*",
323 (unsigned long) left->addr,
324 (unsigned long) left->end_addr,
252b5132 325 right->file ? right->file->name : "*",
fdcf7d43
ILT
326 right->name ? right->name : "*",
327 (unsigned long) right->addr,
328 (unsigned long) right->end_addr,
252b5132 329 table_name[id->which_table]));
0eee5820 330
252b5132
RH
331 arc_add (left, right, (unsigned long) 0);
332 }
333 }
334 }
335 }
336
ef368dac 337 /* Finally, we can sort the tables and we're done. */
252b5132
RH
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
ef368dac
NC
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. */
252b5132
RH
353bool
354DEFUN (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))
ef368dac 363 return TRUE;
252b5132 364 }
0eee5820 365
252b5132
RH
366 return FALSE;
367}