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.18.50/] [gprof/] [sym_ids.c] - Blame information for rev 609

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

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

powered by: WebSVN 2.1.0

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