OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gprof/] [sym_ids.c] - Blame information for rev 277

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.