9 asection
*core_text_sect
;
14 DEFUN(core_init
, (a_out_name
), const char *a_out_name
)
16 core_bfd
= bfd_openr(a_out_name
, 0);
23 if (!bfd_check_format(core_bfd
, bfd_object
)) {
24 fprintf(stderr
, "%s: %s: not in a.out format\n", whoami
, a_out_name
);
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",
39 /* read core's symbol table: */
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()));
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()));
60 * Read in the text space of an a.out file
63 DEFUN(core_get_text_space
, (core_bfd
), bfd
*core_bfd
)
65 core_text_space
= (PTR
) malloc(core_text_sect
->_raw_size
);
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
);
72 if (!bfd_get_section_contents(core_bfd
, core_text_sect
, core_text_space
,
73 0, core_text_sect
->_raw_size
))
75 bfd_perror("bfd_get_section_contents");
76 free(core_text_space
);
79 if (!core_text_space
) {
80 fprintf(stderr
, "%s: can't do -c\n", whoami
);
82 } /* core_get_text_space */
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
92 DEFUN(core_sym_class
, (sym
), asymbol
*sym
)
100 * Must be a text symbol, and static text symbols don't qualify if
101 * ignore_static_funcs set.
107 if (ignore_static_funcs
&& (sym
->flags
& BSF_LOCAL
)) {
108 DBG(AOUTDEBUG
, printf("[core_sym_class] %s: not a function\n",
113 bfd_get_symbol_info(core_bfd
, sym
, &syminfo
);
117 return i
; /* it's a global symbol */
121 /* not a static text symbol */
122 DBG(AOUTDEBUG
, printf("[core_sym_class] %s is of class %c\n",
127 /* do some more filtering on static function-names: */
129 if (ignore_static_funcs
) {
133 * Can't zero-length name or funny characters in name, where
134 * `funny' includes: `.' (.o file names) and `$' (Pascal labels).
136 if (!sym
->name
|| sym
->name
[0] == '\0') {
140 for (name
= sym
->name
; *name
; ++name
) {
141 if (*name
== '.' || *name
== '$') {
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.
154 sym_prefix
= bfd_get_symbol_leading_char(core_bfd
);
155 if (sym_prefix
&& sym_prefix
!= sym
->name
[0]
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)
161 || !strncmp (sym
->name
, "__gnu_compiled", 14)
162 || !strncmp (sym
->name
, "___gnu_compiled", 15))
166 return 't'; /* it's a static text symbol */
167 } /* core_sym_class */
171 * Get whatever source info we can get regarding address ADDR:
174 DEFUN(get_src_info
, (addr
, filename
, name
, line_num
),
175 bfd_vma addr AND
const char **filename AND
const char **name
178 const char *fname
= 0, *func_name
= 0;
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
)
186 DBG(AOUTDEBUG
, printf("[get_src_info] 0x%lx -> %s:%d (%s)\n",
187 addr
, fname
, l
, func_name
));
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>"));
202 * Read in symbol table from core. One symbol per function is
206 DEFUN(core_create_function_syms
, (core_bfd
), bfd
*core_bfd
)
208 bfd_vma min_vma
= ~0, max_vma
= 0;
209 const char *filename
, *func_name
;
213 /* pass 1 - determine upper bound on number of function names: */
215 for (i
= 0; i
< core_num_syms
; ++i
) {
216 if (!core_sym_class(core_syms
[i
])) {
222 if (symtab
.len
== 0) {
223 fprintf(stderr
, "%s: file `%s' has no symbols\n", whoami
, a_out_name
);
227 /* the "+ 2" is for the sentinels: */
228 symtab
.base
= (Sym
*)xmalloc((symtab
.len
+ 2) * sizeof(Sym
));
230 /* pass 2 - create symbols: */
232 symtab
.limit
= symtab
.base
;
233 for (i
= 0; i
< core_num_syms
; ++i
) {
234 class = core_sym_class(core_syms
[i
]);
237 printf("[core_create_function_syms] rejecting: 0x%lx %s\n",
238 core_syms
[i
]->value
, core_syms
[i
]->name
));
242 sym_init(symtab
.limit
);
244 /* symbol offsets are always section-relative: */
246 symtab
.limit
->addr
= core_syms
[i
]->value
+ core_syms
[i
]->section
->vma
;
247 symtab
.limit
->name
= core_syms
[i
]->name
;
251 * Suppress symbols that are not function names. This is
252 * useful to suppress code-labels and aliases.
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
258 if (get_src_info(symtab
.limit
->addr
, &filename
, &func_name
,
259 &symtab
.limit
->line_num
))
261 symtab
.limit
->file
= source_file_lookup_path(filename
);
263 if (strcmp(symtab
.limit
->name
, func_name
) != 0) {
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.
270 printf("[core_create_function_syms: rej %s (maps to %s)\n",
271 symtab
.limit
->name
, func_name
));
277 symtab
.limit
->is_func
= TRUE
;
278 symtab
.limit
->is_bb_head
= TRUE
;
280 symtab
.limit
->is_static
= TRUE
;
283 min_vma
= MIN(symtab
.limit
->addr
, min_vma
);
284 max_vma
= MAX(symtab
.limit
->addr
, max_vma
);
287 * If we see "main" without an initial '_', we assume names
288 * are *not* prefixed by '_'.
290 if (symtab
.limit
->name
[0] == 'm' && discard_underscores
291 && strcmp(symtab
.limit
->name
, "main") == 0)
293 discard_underscores
= 0;
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
));
302 /* create sentinels: */
304 sym_init(symtab
.limit
);
305 symtab
.limit
->name
= "<locore>";
306 symtab
.limit
->addr
= 0;
307 symtab
.limit
->end_addr
= min_vma
- 1;
310 sym_init(symtab
.limit
);
311 symtab
.limit
->name
= "<hicore>";
312 symtab
.limit
->addr
= max_vma
+ 1;
313 symtab
.limit
->end_addr
= ~0;
316 symtab
.len
= symtab
.limit
- symtab
.base
;
317 symtab_finalize(&symtab
);
318 } /* core_create_function_syms */
322 * Read in symbol table from core. One symbol per line of source code
326 DEFUN(core_create_line_syms
, (core_bfd
), bfd
*core_bfd
)
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
;
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:
340 core_create_function_syms(core_bfd
);
342 /* pass 1 - counter number of symbols: */
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.
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
358 min_dist
= core_text_sect
->_raw_size
;
359 prev_offset
= -min_dist
;
360 prev_filename
[0] = '\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))
373 prev_line_num
= dummy
.line_num
;
374 strcpy(prev_name
, dummy
.name
);
375 strcpy(prev_filename
, filename
);
377 if (offset
- prev_offset
< min_dist
) {
378 min_dist
= offset
- prev_offset
;
380 prev_offset
= offset
;
382 min_vma
= MIN(vma
, min_vma
);
383 max_vma
= MAX(vma
, max_vma
);
386 DBG(AOUTDEBUG
, printf("[core_create_line_syms] min_dist=%lx\n", min_dist
));
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
;
393 /* pass 2 - create symbols: */
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 <ab
.limit
->name
, <ab
.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))
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
);
411 ltab
.limit
->addr
= core_text_sect
->vma
+ offset
;
415 * If we see "main" without an initial '_', we assume names
416 * are *not* prefixed by '_'.
418 if (ltab
.limit
->name
[0] == 'm' && discard_underscores
419 && strcmp(ltab
.limit
->name
, "main") == 0)
421 discard_underscores
= 0;
424 DBG(AOUTDEBUG
, printf("[core_create_line_syms] %d %s 0x%lx\n",
425 ltab
.len
, ltab
.limit
->name
,
430 /* update sentinels: */
432 sentinel
= sym_lookup(&symtab
, 0);
433 if (strcmp(sentinel
->name
, "<locore>") == 0
434 && min_vma
<= sentinel
->end_addr
)
436 sentinel
->end_addr
= min_vma
- 1;
439 sentinel
= sym_lookup(&symtab
, ~0);
440 if (strcmp(sentinel
->name
, "<hicore>") == 0 && max_vma
>= sentinel
->addr
) {
441 sentinel
->addr
= max_vma
+ 1;
444 /* copy in function symbols: */
445 memcpy(ltab
.limit
, symtab
.base
, symtab
.len
* sizeof(Sym
));
446 ltab
.limit
+= symtab
.len
;
448 if (ltab
.limit
- ltab
.base
!= ltab
.len
) {
450 "%s: somebody miscounted: ltab.len=%ld instead of %d\n",
451 whoami
, (long) (ltab
.limit
- ltab
.base
), ltab
.len
);
455 /* finalize ltab and make it symbol table: */
457 symtab_finalize(<ab
);
461 /* now go through all core symbols and set is_static accordingly: */
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
);
468 sym
++->is_static
= TRUE
;
469 } while (sym
->file
== sym
[-1].file
&&
470 strcmp(sym
->name
, sym
[-1].name
) == 0);
474 } /* core_create_line_syms */
476 /*** end of core.c ***/