Lots of changes from David Mosberger-Tang; see ChangeLog and NOTES for details:
[platform/upstream/binutils.git] / gprof / core.c
1 #include "libiberty.h"
2 #include "gprof.h"
3 #include "core.h"
4 #include "symtab.h"
5
6 bfd *core_bfd;
7 int core_num_syms;
8 asymbol **core_syms;
9 asection *core_text_sect;
10 PTR core_text_space;
11
12
13 void
14 DEFUN(core_init, (a_out_name), const char *a_out_name)
15 {
16     core_bfd = bfd_openr(a_out_name, 0);
17
18     if (!core_bfd) {
19         perror(a_out_name);
20         done(1);
21     } /* if */
22
23     if (!bfd_check_format(core_bfd, bfd_object)) {
24         fprintf(stderr, "%s: %s: not in a.out format\n", whoami, a_out_name);
25         done(1);
26     } /* if */
27
28     /* get core's text section: */
29     core_text_sect = bfd_get_section_by_name(core_bfd, ".text");
30     if (!core_text_sect) {
31         core_text_sect = bfd_get_section_by_name(core_bfd, "$CODE$");
32         if (!core_text_sect) {
33             fprintf(stderr, "%s: can't find .text section in %s\n",
34                     whoami, a_out_name);
35             done(1);
36         } /* if */
37     } /* if */
38
39     /* read core's symbol table: */
40
41     /* this will probably give us more than we need, but that's ok:  */
42     core_num_syms = bfd_get_symtab_upper_bound(core_bfd);
43     if (core_num_syms < 0) {
44         fprintf(stderr, "%s: %s: %s\n", whoami, a_out_name,
45                 bfd_errmsg(bfd_get_error()));
46         done(1);
47     } /* if */
48
49     core_syms = (asymbol**)xmalloc(core_num_syms);
50     core_num_syms = bfd_canonicalize_symtab(core_bfd, core_syms);
51     if (core_num_syms < 0) {
52         fprintf(stderr, "%s: %s: %s\n", whoami, a_out_name,
53                 bfd_errmsg(bfd_get_error()));
54         done(1);
55     } /* if */
56 } /* core_init */
57
58
59 /*
60  * Read in the text space of an a.out file
61  */
62 void
63 DEFUN(core_get_text_space, (core_bfd), bfd *core_bfd)
64 {
65     core_text_space = (PTR) malloc(core_text_sect->_raw_size);
66
67     if (!core_text_space) {
68         fprintf(stderr, "%s: ran out room for %ld bytes of text space\n",
69                 whoami, core_text_sect->_raw_size);
70         done(1);
71     } /* if */
72     if (!bfd_get_section_contents(core_bfd, core_text_sect, core_text_space,
73                                   0, core_text_sect->_raw_size))
74     {
75         bfd_perror("bfd_get_section_contents");
76         free(core_text_space);
77         core_text_space = 0;
78     } /* if */
79     if (!core_text_space) {
80         fprintf(stderr, "%s: can't do -c\n", whoami);
81     } /* if */
82 } /* core_get_text_space */
83
84
85 /*
86  * Return class of symbol SYM.  The returned class can be any of:
87  *      0   -> symbol is not interesting to us
88  *      'T' -> symbol is a global name
89  *      't' -> symbol is a local (static) name
90  */
91 static int
92 DEFUN(core_sym_class, (sym), asymbol *sym)
93 {
94     symbol_info syminfo;
95     const char *name;
96     char sym_prefix;
97     int i;
98
99     /*
100      * Must be a text symbol, and static text symbols don't qualify if
101      * ignore_static_funcs set.
102      */
103     if (!sym->section) {
104         return 0;
105     } /* if */
106
107     if (ignore_static_funcs && (sym->flags & BSF_LOCAL)) {
108         DBG(AOUTDEBUG, printf("[core_sym_class] %s: not a function\n",
109                               sym->name));
110         return 0;
111     } /* if */
112
113     bfd_get_symbol_info(core_bfd, sym, &syminfo);
114     i = syminfo.type;
115
116     if (i == 'T') {
117         return i;       /* it's a global symbol */
118     } /* if */
119
120     if (i != 't') {
121         /* not a static text symbol */
122         DBG(AOUTDEBUG, printf("[core_sym_class] %s is of class %c\n",
123                               sym->name, i));
124         return 0;
125     } /* if */
126
127     /* do some more filtering on static function-names: */
128
129     if (ignore_static_funcs) {
130         return 0;
131     } /* if */
132     /*
133      * Can't zero-length name or funny characters in name, where
134      * `funny' includes: `.' (.o file names) and `$' (Pascal labels).
135      */
136     if (!sym->name || sym->name[0] == '\0') {
137         return 0;
138     } /* if */
139
140     for (name = sym->name; *name; ++name) {
141         if (*name == '.' || *name == '$') {
142             return 0;
143         } /* if */
144     } /* if */
145     /*
146      * On systems where the C compiler adds an underscore to all
147      * names, static names without underscores seem usually to be
148      * labels in hand written assembler in the library.  We don't want
149      * these names.  This is certainly necessary on a Sparc running
150      * SunOS 4.1 (try profiling a program that does a lot of
151      * division). I don't know whether it has harmful side effects on
152      * other systems.  Perhaps it should be made configurable.
153      */
154     sym_prefix = bfd_get_symbol_leading_char(core_bfd);
155     if (sym_prefix && sym_prefix != sym->name[0]
156         /*
157          * GCC may add special symbols to help gdb figure out the file
158          * language.  We want to ignore these, since sometimes they mask
159          * the real function.  (dj@ctron)
160          */
161         || !strncmp (sym->name, "__gnu_compiled", 14)
162         || !strncmp (sym->name, "___gnu_compiled", 15))
163     {
164         return 0;
165     } /* if */
166     return 't';         /* it's a static text symbol */
167 } /* core_sym_class */
168
169
170 /*
171  * Get whatever source info we can get regarding address ADDR:
172  */
173 static bool
174 DEFUN(get_src_info, (addr, filename, name, line_num),
175       bfd_vma addr AND const char **filename AND const char **name
176       AND int *line_num)
177 {
178     const char *fname = 0, *func_name = 0;
179     int l = 0;
180
181     if (bfd_find_nearest_line(core_bfd, core_text_sect, core_syms,
182                               addr - core_text_sect->vma,
183                               &fname, &func_name, &l)
184         && fname && func_name && l)
185     {
186         DBG(AOUTDEBUG, printf("[get_src_info] 0x%lx -> %s:%d (%s)\n",
187                               addr, fname, l, func_name));
188         *filename = fname;
189         *name = func_name;
190         *line_num = l;
191         return TRUE;
192     } else {
193         DBG(AOUTDEBUG, printf("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
194                               (long) addr, fname ? fname : "<unknown>", l,
195                               func_name ? func_name : "<unknown>"));
196         return FALSE;
197     } /* if */
198 } /* get_src_info */
199
200
201 /*
202  * Read in symbol table from core.  One symbol per function is
203  * entered.
204  */
205 void
206 DEFUN(core_create_function_syms, (core_bfd), bfd *core_bfd)
207 {
208     bfd_vma min_vma = ~0, max_vma = 0;
209     const char *filename, *func_name;
210     int class;
211     long i;
212
213     /* pass 1 - determine upper bound on number of function names: */
214     symtab.len = 0;
215     for (i = 0; i < core_num_syms; ++i) {
216         if (!core_sym_class(core_syms[i])) {
217             continue;
218         } /* if */
219         ++symtab.len;
220     } /* for */
221
222     if (symtab.len == 0) {
223         fprintf(stderr, "%s: file `%s' has no symbols\n", whoami, a_out_name);
224         done(1);
225     } /* if */
226
227     /* the "+ 2" is for the sentinels: */
228     symtab.base = (Sym*)xmalloc((symtab.len + 2) * sizeof(Sym));
229
230     /* pass 2 - create symbols: */
231
232     symtab.limit = symtab.base;
233     for (i = 0; i < core_num_syms; ++i) {
234         class = core_sym_class(core_syms[i]);
235         if (!class) {
236             DBG(AOUTDEBUG,
237                 printf("[core_create_function_syms] rejecting: 0x%lx %s\n",
238                        core_syms[i]->value, core_syms[i]->name));
239             continue;
240         } /* if */
241
242         sym_init(symtab.limit);
243
244         /* symbol offsets are always section-relative: */
245
246         symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma;
247         symtab.limit->name = core_syms[i]->name;
248
249 #ifdef __osf__
250         /*
251          * Suppress symbols that are not function names.  This is
252          * useful to suppress code-labels and aliases.
253          *
254          * This is known to be useful under DEC's OSF/1.  Under SunOS 4.x,
255          * labels do not appear in the symbol table info, so this isn't
256          * necessary.
257          */
258         if (get_src_info(symtab.limit->addr, &filename, &func_name,
259                          &symtab.limit->line_num))
260         {
261             symtab.limit->file = source_file_lookup_path(filename);
262
263             if (strcmp(symtab.limit->name, func_name) != 0) {
264                 /*
265                  * The symbol's address maps to a different name, so
266                  * it can't be a function-entry point.  This happens
267                  * for labels, for example.
268                  */
269                 DBG(AOUTDEBUG,
270                     printf("[core_create_function_syms: rej %s (maps to %s)\n",
271                            symtab.limit->name, func_name));
272                 continue;
273             } /* if */
274         } /* if */
275 #endif
276
277         symtab.limit->is_func = TRUE;
278         symtab.limit->is_bb_head = TRUE;
279         if (class == 't') {
280             symtab.limit->is_static = TRUE;
281         } /* if */
282
283         min_vma = MIN(symtab.limit->addr, min_vma);
284         max_vma = MAX(symtab.limit->addr, max_vma);
285
286         /*
287          * If we see "main" without an initial '_', we assume names
288          * are *not* prefixed by '_'.
289          */
290         if (symtab.limit->name[0] == 'm' && discard_underscores
291             && strcmp(symtab.limit->name, "main") == 0)
292         {
293             discard_underscores = 0;
294         } /* if */
295
296         DBG(AOUTDEBUG, printf("[core_create_function_syms] %ld %s 0x%lx\n",
297                               (long)(symtab.limit - symtab.base),
298                               symtab.limit->name, symtab.limit->addr));
299         ++symtab.limit;
300     } /* for */
301
302     /* create sentinels: */
303
304     sym_init(symtab.limit);
305     symtab.limit->name = "<locore>";
306     symtab.limit->addr = 0;
307     symtab.limit->end_addr = min_vma - 1;
308     ++symtab.limit;
309
310     sym_init(symtab.limit);
311     symtab.limit->name = "<hicore>";
312     symtab.limit->addr = max_vma + 1;
313     symtab.limit->end_addr = ~0;
314     ++symtab.limit;
315
316     symtab.len = symtab.limit - symtab.base;
317     symtab_finalize(&symtab);
318 } /* core_create_function_syms */
319
320
321 /*
322  * Read in symbol table from core.  One symbol per line of source code
323  * is entered.
324  */
325 void
326 DEFUN(core_create_line_syms, (core_bfd), bfd *core_bfd)
327 {
328     char prev_name[PATH_MAX], prev_filename[PATH_MAX];
329     bfd_vma vma, min_vma = ~0, max_vma = 0;
330     bfd_vma offset, prev_offset, min_dist;
331     Sym *prev, dummy, *sentinel, *sym;
332     const char *filename;
333     int prev_line_num, i;
334     Sym_Table ltab;
335     /*
336      * Create symbols for functions as usual.  This is necessary in
337      * cases where parts of a program were not compiled with -g.  For
338      * those parts we still want to get info at the function level:
339      */
340     core_create_function_syms(core_bfd);
341
342     /* pass 1 - counter number of symbols: */
343
344     /*
345      * To find all line information, walk through all possible
346      * text-space addresses (one by one!) and get the debugging
347      * info for each address.  When the debugging info changes,
348      * it is time to create a new symbol.
349      *
350      * Of course, this is rather slow and it would be better if
351      * bfd would provide an iterator for enumerating all line
352      * infos, but for now, we try to speed up the second pass
353      * by determining what the minimum code distance between two
354      * lines is.
355      */
356     prev_name[0] = '\0';
357     ltab.len = 0;
358     min_dist = core_text_sect->_raw_size;
359     prev_offset = -min_dist;
360     prev_filename[0] = '\0';
361     prev_line_num = 0;
362     for (offset = 0; offset < core_text_sect->_raw_size; ++offset) {
363         vma = core_text_sect->vma + offset;
364         if (!get_src_info(vma, &filename, &dummy.name, &dummy.line_num)
365             || (prev_line_num == dummy.line_num &&
366                 strcmp(prev_name, dummy.name) == 0
367                 && strcmp(prev_filename, filename) == 0))
368         {
369             continue;
370         } /* if */
371
372         ++ltab.len;
373         prev_line_num = dummy.line_num;
374         strcpy(prev_name, dummy.name);
375         strcpy(prev_filename, filename);
376
377         if (offset - prev_offset < min_dist) {
378             min_dist = offset - prev_offset;
379         } /* if */
380         prev_offset = offset;
381
382         min_vma = MIN(vma, min_vma);
383         max_vma = MAX(vma, max_vma);
384     } /* for */
385
386     DBG(AOUTDEBUG, printf("[core_create_line_syms] min_dist=%lx\n", min_dist));
387
388     /* make room for function symbols, too: */
389     ltab.len += symtab.len;
390     ltab.base = (Sym*) xmalloc(ltab.len * sizeof(Sym));
391     ltab.limit = ltab.base;
392
393     /* pass 2 - create symbols: */
394
395     prev = 0;
396     for (offset = 0; offset < core_text_sect->_raw_size; offset += min_dist) {
397         sym_init(ltab.limit);
398         if (!get_src_info(core_text_sect->vma + offset, &filename,
399                           &ltab.limit->name, &ltab.limit->line_num)
400             || (prev && prev->line_num == ltab.limit->line_num
401                 && strcmp(prev->name, ltab.limit->name) == 0
402                 && strcmp(prev->file->name, filename) == 0))
403         {
404             continue;
405         } /* if */
406
407         /* make name pointer a malloc'ed string: */
408         ltab.limit->name = strdup(ltab.limit->name);
409         ltab.limit->file = source_file_lookup_path(filename);
410
411         ltab.limit->addr = core_text_sect->vma + offset;
412         prev = ltab.limit;
413
414         /*
415          * If we see "main" without an initial '_', we assume names
416          * are *not* prefixed by '_'.
417          */
418         if (ltab.limit->name[0] == 'm' && discard_underscores
419             && strcmp(ltab.limit->name, "main") == 0)
420         {
421             discard_underscores = 0;
422         } /* if */
423
424         DBG(AOUTDEBUG, printf("[core_create_line_syms] %d %s 0x%lx\n",
425                               ltab.len, ltab.limit->name,
426                               ltab.limit->addr));
427         ++ltab.limit;
428     } /* for */
429
430     /* update sentinels: */
431
432     sentinel = sym_lookup(&symtab, 0);
433     if (strcmp(sentinel->name, "<locore>") == 0
434         && min_vma <= sentinel->end_addr)
435     {
436         sentinel->end_addr = min_vma - 1;
437     } /* if */
438
439     sentinel = sym_lookup(&symtab, ~0);
440     if (strcmp(sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr) {
441         sentinel->addr = max_vma + 1;
442     } /* if */
443
444     /* copy in function symbols: */
445     memcpy(ltab.limit, symtab.base, symtab.len * sizeof(Sym));
446     ltab.limit += symtab.len;
447
448     if (ltab.limit - ltab.base != ltab.len) {
449         fprintf(stderr,
450                 "%s: somebody miscounted: ltab.len=%ld instead of %d\n",
451                 whoami, (long) (ltab.limit - ltab.base), ltab.len);
452         done(1);
453     } /* if */
454
455     /* finalize ltab and make it symbol table: */
456
457     symtab_finalize(&ltab);
458     free(symtab.base);
459     symtab = ltab;
460
461     /* now go through all core symbols and set is_static accordingly: */
462
463     for (i = 0; i < core_num_syms; ++i) {
464         if (core_sym_class(core_syms[i]) == 't') {
465             sym = sym_lookup(&symtab, core_syms[i]->value
466                              + core_syms[i]->section->vma);
467             do {
468                 sym++->is_static = TRUE;
469             } while (sym->file == sym[-1].file &&
470                      strcmp(sym->name, sym[-1].name) == 0);
471         } /* if */
472     } /* for */
473
474 } /* core_create_line_syms */
475
476                         /*** end of core.c ***/