3 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
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.
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.
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
22 #include "libiberty.h"
23 #include "safe-ctype.h"
25 #include "search_list.h"
34 char *spec
; /* Parsing modifies this. */
36 bfd_boolean has_right
;
40 int prev_index
; /* Index of prev match. */
41 Sym
*prev_match
; /* Previous match. */
42 Sym
*first_match
; /* Chain of all matches. */
49 static void parse_spec
53 static bfd_boolean match
55 static void extend_match
56 (struct match
*, Sym
*, Sym_Table
*, bfd_boolean
);
59 Sym_Table syms
[NUM_TABLES
];
62 const char *table_name
[] =
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"
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). */
78 static Sym_Table right_ids
;
80 static Source_File non_existent_file
=
82 0, "<non-existent-file>", 0, 0, 0, NULL
87 sym_id_add (const char *spec
, Table_Id which_table
)
90 int len
= strlen (spec
);
92 id
= (struct sym_id
*) xmalloc (sizeof (*id
) + len
+ 1);
93 memset (id
, 0, sizeof (*id
));
95 id
->spec
= (char *) id
+ sizeof (*id
);
96 strcpy (id
->spec
, spec
);
97 id
->which_table
= which_table
;
104 /* A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
105 to the user, a spec without a colon is interpreted as:
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
111 A FUNCNAME containing a dot can be specified by :FUNCNAME, a
112 FILENAME not containing a dot can be specified by FILENAME. */
115 parse_spec (char *spec
, Sym
*sym
)
120 colon
= strrchr (spec
, ':');
128 sym
->file
= source_file_lookup_name (spec
);
131 sym
->file
= &non_existent_file
;
138 if (ISDIGIT (spec
[0]))
139 sym
->line_num
= atoi (spec
);
144 else if (strlen (spec
))
146 /* No colon: spec is a filename if it contains a dot. */
147 if (strchr (spec
, '.'))
149 sym
->file
= source_file_lookup_name (spec
);
152 sym
->file
= &non_existent_file
;
154 else if (ISDIGIT (*spec
))
156 sym
->line_num
= atoi (spec
);
158 else if (strlen (spec
))
166 /* A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
170 parse_id (struct sym_id
*id
)
174 DBG (IDDEBUG
, printf ("[parse_id] %s -> ", id
->spec
));
176 slash
= strchr (id
->spec
, '/');
179 parse_spec (slash
+ 1, &id
->right
.sym
);
181 id
->has_right
= TRUE
;
183 parse_spec (id
->spec
, &id
->left
.sym
);
186 if (debug_level
& IDDEBUG
)
188 printf ("%s:", id
->left
.sym
.file
? id
->left
.sym
.file
->name
: "*");
190 if (id
->left
.sym
.name
)
191 printf ("%s", id
->left
.sym
.name
);
192 else if (id
->left
.sym
.line_num
)
193 printf ("%d", id
->left
.sym
.line_num
);
200 id
->right
.sym
.file
? id
->right
.sym
.file
->name
: "*");
202 if (id
->right
.sym
.name
)
203 printf ("%s", id
->right
.sym
.name
);
204 else if (id
->right
.sym
.line_num
)
205 printf ("%d", id
->right
.sym
.line_num
);
216 /* Return TRUE iff PATTERN matches SYM. */
219 match (Sym
*pattern
, Sym
*sym
)
221 return (pattern
->file
? pattern
->file
== sym
->file
: TRUE
)
222 && (pattern
->line_num
? pattern
->line_num
== sym
->line_num
: TRUE
)
224 ? strcmp (pattern
->name
,
225 sym
->name
+(discard_underscores
&& sym
->name
[0] == '_')) == 0
231 extend_match (struct match
*m
, Sym
*sym
, Sym_Table
*tab
, bfd_boolean second_pass
)
233 if (m
->prev_match
!= sym
- 1)
235 /* Discontinuity: add new match to table. */
238 tab
->base
[tab
->len
] = *sym
;
239 m
->prev_index
= tab
->len
;
241 /* Link match into match's chain. */
242 tab
->base
[tab
->len
].next
= m
->first_match
;
243 m
->first_match
= &tab
->base
[tab
->len
];
249 /* Extend match to include this symbol. */
251 tab
->base
[m
->prev_index
].end_addr
= sym
->end_addr
;
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.
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! */
268 Sym
*sym
, *left
, *right
;
272 /* Convert symbol ids into Syms, so we can deal with them more easily. */
273 for (id
= id_list
; id
; id
= id
->next
)
276 /* First determine size of each table. */
277 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
279 for (id
= id_list
; id
; id
= id
->next
)
281 if (match (&id
->left
.sym
, sym
))
282 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], FALSE
);
284 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
285 extend_match (&id
->right
, sym
, &right_ids
, FALSE
);
289 /* Create tables of appropriate size and reset lengths. */
290 for (tab
= syms
; tab
< &syms
[NUM_TABLES
]; ++tab
)
294 tab
->base
= (Sym
*) xmalloc (tab
->len
* sizeof (Sym
));
295 tab
->limit
= tab
->base
+ tab
->len
;
302 right_ids
.base
= (Sym
*) xmalloc (right_ids
.len
* sizeof (Sym
));
303 right_ids
.limit
= right_ids
.base
+ right_ids
.len
;
307 /* Make a second pass through symtab, creating syms as necessary. */
308 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
310 for (id
= id_list
; id
; id
= id
->next
)
312 if (match (&id
->left
.sym
, sym
))
313 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], TRUE
);
315 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
316 extend_match (&id
->right
, sym
, &right_ids
, TRUE
);
320 /* Go through ids creating arcs as needed. */
321 for (id
= id_list
; id
; id
= id
->next
)
325 for (left
= id
->left
.first_match
; left
; left
= left
->next
)
327 for (right
= id
->right
.first_match
; right
; right
= right
->next
)
331 "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
332 left
->file
? left
->file
->name
: "*",
333 left
->name
? left
->name
: "*",
334 (unsigned long) left
->addr
,
335 (unsigned long) left
->end_addr
,
336 right
->file
? right
->file
->name
: "*",
337 right
->name
? right
->name
: "*",
338 (unsigned long) right
->addr
,
339 (unsigned long) right
->end_addr
,
340 table_name
[id
->which_table
]));
342 arc_add (left
, right
, (unsigned long) 0);
348 /* Finally, we can sort the tables and we're done. */
349 for (tab
= &syms
[0]; tab
< &syms
[NUM_TABLES
]; ++tab
)
351 DBG (IDDEBUG
, printf ("[sym_id_parse] syms[%s]:\n",
352 table_name
[tab
- &syms
[0]]));
353 symtab_finalize (tab
);
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
365 sym_id_arc_is_present (Sym_Table
*sym_tab
, Sym
*from
, Sym
*to
)
369 for (sym
= sym_tab
->base
; sym
< sym_tab
->limit
; ++sym
)
371 if (from
->addr
>= sym
->addr
&& from
->addr
<= sym
->end_addr
372 && arc_lookup (sym
, to
))