3 Copyright (C) 2000 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
24 #include "libiberty.h"
31 char *spec
; /* Parsing modifies this. */
37 int prev_index
; /* Index of prev match. */
38 Sym
*prev_match
; /* Previous match. */
39 Sym
*first_match
; /* Chain of all matches. */
46 Sym_Table syms
[NUM_TABLES
];
49 const char *table_name
[] =
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"
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
;
67 static Source_File non_existent_file
=
69 0, "<non-existent-file>", 0, 0, 0, NULL
74 DEFUN (sym_id_add
, (spec
, which_table
),
75 const char *spec AND Table_Id which_table
)
78 int len
= strlen (spec
);
80 id
= (struct sym_id
*) xmalloc (sizeof (*id
) + len
+ 1);
81 memset (id
, 0, sizeof (*id
));
83 id
->spec
= (char *) id
+ sizeof (*id
);
84 strcpy (id
->spec
, spec
);
85 id
->which_table
= which_table
;
92 /* A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
93 to the user, a spec without a colon is interpreted as:
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
99 A FUNCNAME containing a dot can be specified by :FUNCNAME, a
100 FILENAME not containing a dot can be specified by FILENAME. */
103 DEFUN (parse_spec
, (spec
, sym
), char *spec AND Sym
* sym
)
108 colon
= strrchr (spec
, ':');
116 sym
->file
= source_file_lookup_name (spec
);
119 sym
->file
= &non_existent_file
;
126 if (isdigit ((unsigned char) spec
[0]))
127 sym
->line_num
= atoi (spec
);
132 else if (strlen (spec
))
134 /* No colon: spec is a filename if it contains a dot. */
135 if (strchr (spec
, '.'))
137 sym
->file
= source_file_lookup_name (spec
);
140 sym
->file
= &non_existent_file
;
142 else if (isdigit ((unsigned char) *spec
))
144 sym
->line_num
= atoi (spec
);
146 else if (strlen (spec
))
154 /* A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
158 DEFUN (parse_id
, (id
), struct sym_id
*id
)
162 DBG (IDDEBUG
, printf ("[parse_id] %s -> ", id
->spec
));
164 slash
= strchr (id
->spec
, '/');
167 parse_spec (slash
+ 1, &id
->right
.sym
);
169 id
->has_right
= TRUE
;
171 parse_spec (id
->spec
, &id
->left
.sym
);
174 if (debug_level
& IDDEBUG
)
176 printf ("%s:", id
->left
.sym
.file
? id
->left
.sym
.file
->name
: "*");
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
);
188 id
->right
.sym
.file
? id
->right
.sym
.file
->name
: "*");
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
);
204 /* Return TRUE iff PATTERN matches SYM. */
207 DEFUN (match
, (pattern
, sym
), Sym
* pattern AND Sym
* sym
)
209 return (pattern
->file
? pattern
->file
== sym
->file
: TRUE
)
210 && (pattern
->line_num
? pattern
->line_num
== sym
->line_num
: TRUE
)
212 ? strcmp (pattern
->name
,
213 sym
->name
+(discard_underscores
&& sym
->name
[0] == '_')) == 0
219 DEFUN (extend_match
, (m
, sym
, tab
, second_pass
),
220 struct match
*m AND Sym
* sym AND Sym_Table
* tab AND
bool second_pass
)
222 if (m
->prev_match
!= sym
- 1)
224 /* Discontinuity: add new match to table. */
227 tab
->base
[tab
->len
] = *sym
;
228 m
->prev_index
= tab
->len
;
230 /* Link match into match's chain. */
231 tab
->base
[tab
->len
].next
= m
->first_match
;
232 m
->first_match
= &tab
->base
[tab
->len
];
238 /* Extend match to include this symbol. */
240 tab
->base
[m
->prev_index
].end_addr
= sym
->end_addr
;
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.
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! */
255 DEFUN_VOID (sym_id_parse
)
257 Sym
*sym
, *left
, *right
;
261 /* Convert symbol ids into Syms, so we can deal with them more easily. */
262 for (id
= id_list
; id
; id
= id
->next
)
265 /* First determine size of each table. */
266 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
268 for (id
= id_list
; id
; id
= id
->next
)
270 if (match (&id
->left
.sym
, sym
))
271 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], FALSE
);
273 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
274 extend_match (&id
->right
, sym
, &right_ids
, FALSE
);
278 /* Create tables of appropriate size and reset lengths. */
279 for (tab
= syms
; tab
< &syms
[NUM_TABLES
]; ++tab
)
283 tab
->base
= (Sym
*) xmalloc (tab
->len
* sizeof (Sym
));
284 tab
->limit
= tab
->base
+ tab
->len
;
291 right_ids
.base
= (Sym
*) xmalloc (right_ids
.len
* sizeof (Sym
));
292 right_ids
.limit
= right_ids
.base
+ right_ids
.len
;
296 /* Make a second pass through symtab, creating syms as necessary. */
297 for (sym
= symtab
.base
; sym
< symtab
.limit
; ++sym
)
299 for (id
= id_list
; id
; id
= id
->next
)
301 if (match (&id
->left
.sym
, sym
))
302 extend_match (&id
->left
, sym
, &syms
[id
->which_table
], TRUE
);
304 if (id
->has_right
&& match (&id
->right
.sym
, sym
))
305 extend_match (&id
->right
, sym
, &right_ids
, TRUE
);
309 /* Go through ids creating arcs as needed. */
310 for (id
= id_list
; id
; id
= id
->next
)
314 for (left
= id
->left
.first_match
; left
; left
= left
->next
)
316 for (right
= id
->right
.first_match
; right
; right
= right
->next
)
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
]));
331 arc_add (left
, right
, (unsigned long) 0);
337 /* Finally, we can sort the tables and we're done. */
338 for (tab
= &syms
[0]; tab
< &syms
[NUM_TABLES
]; ++tab
)
340 DBG (IDDEBUG
, printf ("[sym_id_parse] syms[%s]:\n",
341 table_name
[tab
- &syms
[0]]));
342 symtab_finalize (tab
);
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
354 DEFUN (sym_id_arc_is_present
, (symtab
, from
, to
),
355 Sym_Table
* symtab AND Sym
* from AND Sym
* to
)
359 for (sym
= symtab
->base
; sym
< symtab
->limit
; ++sym
)
361 if (from
->addr
>= sym
->addr
&& from
->addr
<= sym
->end_addr
362 && arc_lookup (sym
, to
))