Add GPL copyright notices to uncopyrighted files.
[external/binutils.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 }