* hist.h (struct histogram)
[external/binutils.git] / gprof / corefile.c
1 /* corefile.c
2
3    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005
4    Free Software Foundation, Inc.
5
6    This file is part of GNU Binutils.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21    02110-1301, USA.  */
22 \f
23 #include "libiberty.h"
24 #include "gprof.h"
25 #include "search_list.h"
26 #include "source.h"
27 #include "symtab.h"
28 #include "hist.h"
29 #include "corefile.h"
30
31 bfd *core_bfd;
32 static int core_num_syms;
33 static asymbol **core_syms;
34 asection *core_text_sect;
35 PTR core_text_space;
36
37 static int min_insn_size;
38 int offset_to_code;
39
40 /* For mapping symbols to specific .o files during file ordering.  */
41 struct function_map *symbol_map;
42 unsigned int symbol_map_count;
43
44 static void read_function_mappings (const char *);
45 static int core_sym_class (asymbol *);
46 static bfd_boolean get_src_info
47   (bfd_vma, const char **, const char **, int *);
48
49 extern void i386_find_call  (Sym *, bfd_vma, bfd_vma);
50 extern void alpha_find_call (Sym *, bfd_vma, bfd_vma);
51 extern void vax_find_call   (Sym *, bfd_vma, bfd_vma);
52 extern void tahoe_find_call (Sym *, bfd_vma, bfd_vma);
53 extern void sparc_find_call (Sym *, bfd_vma, bfd_vma);
54 extern void mips_find_call  (Sym *, bfd_vma, bfd_vma);
55
56 static void
57 parse_error (const char *filename)
58 {
59   fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), whoami, filename);
60   done (1);
61 }
62
63 static void
64 read_function_mappings (const char *filename)
65 {
66   FILE *file = fopen (filename, "r");
67   char dummy[1024];
68   int count = 0;
69
70   if (!file)
71     {
72       fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename);
73       done (1);
74     }
75
76   /* First parse the mapping file so we know how big we need to
77      make our tables.  We also do some sanity checks at this
78      time.  */
79   while (!feof (file))
80     {
81       int matches;
82
83       matches = fscanf (file, "%[^\n:]", dummy);
84       if (!matches)
85         parse_error (filename);
86
87       /* Just skip messages about files with no symbols.  */
88       if (!strncmp (dummy, "No symbols in ", 14))
89         {
90           matches = fscanf (file, "\n");
91           if (matches == EOF)
92             parse_error (filename);
93           continue;
94         }
95
96       /* Don't care what else is on this line at this point.  */
97       matches = fscanf (file, "%[^\n]\n", dummy);
98       if (!matches)
99         parse_error (filename);
100       count++;
101     }
102
103   /* Now we know how big we need to make our table.  */
104   symbol_map = ((struct function_map *)
105                 xmalloc (count * sizeof (struct function_map)));
106
107   /* Rewind the input file so we can read it again.  */
108   rewind (file);
109
110   /* Read each entry and put it into the table.  */
111   count = 0;
112   while (!feof (file))
113     {
114       int matches;
115       char *tmp;
116
117       matches = fscanf (file, "%[^\n:]", dummy);
118       if (!matches)
119         parse_error (filename);
120
121       /* Just skip messages about files with no symbols.  */
122       if (!strncmp (dummy, "No symbols in ", 14))
123         {
124           matches = fscanf (file, "\n");
125           if (matches == EOF)
126             parse_error (filename);
127           continue;
128         }
129
130       /* dummy has the filename, go ahead and copy it.  */
131       symbol_map[count].file_name = xmalloc (strlen (dummy) + 1);
132       strcpy (symbol_map[count].file_name, dummy);
133
134       /* Now we need the function name.  */
135       matches = fscanf (file, "%[^\n]\n", dummy);
136       if (!matches)
137         parse_error (filename);
138       tmp = strrchr (dummy, ' ') + 1;
139       symbol_map[count].function_name = xmalloc (strlen (tmp) + 1);
140       strcpy (symbol_map[count].function_name, tmp);
141       count++;
142     }
143
144   /* Record the size of the map table for future reference.  */
145   symbol_map_count = count;
146 }
147
148
149 void
150 core_init (const char *aout_name)
151 {
152   int core_sym_bytes;
153   asymbol *synthsyms;
154   long synth_count;
155
156   core_bfd = bfd_openr (aout_name, 0);
157
158   if (!core_bfd)
159     {
160       perror (aout_name);
161       done (1);
162     }
163
164   if (!bfd_check_format (core_bfd, bfd_object))
165     {
166       fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name);
167       done (1);
168     }
169
170   /* Get core's text section.  */
171   core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
172   if (!core_text_sect)
173     {
174       core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
175       if (!core_text_sect)
176         {
177           fprintf (stderr, _("%s: can't find .text section in %s\n"),
178                    whoami, aout_name);
179           done (1);
180         }
181     }
182
183   /* Read core's symbol table.  */
184
185   /* This will probably give us more than we need, but that's ok.  */
186   core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd);
187   if (core_sym_bytes < 0)
188     {
189       fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
190                bfd_errmsg (bfd_get_error ()));
191       done (1);
192     }
193
194   core_syms = (asymbol **) xmalloc (core_sym_bytes);
195   core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
196
197   if (core_num_syms < 0)
198     {
199       fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
200                bfd_errmsg (bfd_get_error ()));
201       done (1);
202     }
203
204   synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms,
205                                           0, NULL, &synthsyms);
206   if (synth_count > 0)
207     {
208       asymbol **symp;
209       long new_size;
210       long i;
211
212       new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms);
213       core_syms = xrealloc (core_syms, new_size);
214       symp = core_syms + core_num_syms;
215       core_num_syms += synth_count;
216       for (i = 0; i < synth_count; i++)
217         *symp++ = synthsyms + i;
218       *symp = 0;
219     }
220
221   min_insn_size = 1;
222   offset_to_code = 0;
223
224   switch (bfd_get_arch (core_bfd))
225     {
226     case bfd_arch_vax:
227     case bfd_arch_tahoe:
228       offset_to_code = 2;
229       break;
230
231     case bfd_arch_alpha:
232       min_insn_size = 4;
233       break;
234
235     default:
236       break;
237     }
238
239   if (function_mapping_file)
240     read_function_mappings (function_mapping_file);
241 }
242
243 /* Read in the text space of an a.out file.  */
244
245 void
246 core_get_text_space (bfd *cbfd)
247 {
248   core_text_space = malloc (bfd_get_section_size (core_text_sect));
249
250   if (!core_text_space)
251     {
252       fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"),
253                whoami, (unsigned long) bfd_get_section_size (core_text_sect));
254       done (1);
255     }
256
257   if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space,
258                                  0, bfd_get_section_size (core_text_sect)))
259     {
260       bfd_perror ("bfd_get_section_contents");
261       free (core_text_space);
262       core_text_space = 0;
263     }
264
265   if (!core_text_space)
266     fprintf (stderr, _("%s: can't do -c\n"), whoami);
267 }
268
269
270 void
271 find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
272 {
273   if (core_text_space == 0)
274     return;
275
276   hist_clip_symbol_address (&p_lowpc, &p_highpc);
277
278   switch (bfd_get_arch (core_bfd))
279     {
280     case bfd_arch_i386:
281       i386_find_call (parent, p_lowpc, p_highpc);
282       break;
283
284     case bfd_arch_alpha:
285       alpha_find_call (parent, p_lowpc, p_highpc);
286       break;
287
288     case bfd_arch_vax:
289       vax_find_call (parent, p_lowpc, p_highpc);
290       break;
291
292     case bfd_arch_sparc:
293       sparc_find_call (parent, p_lowpc, p_highpc);
294       break;
295
296     case bfd_arch_tahoe:
297       tahoe_find_call (parent, p_lowpc, p_highpc);
298       break;
299
300     case bfd_arch_mips:
301       mips_find_call (parent, p_lowpc, p_highpc);
302       break;
303
304     default:
305       fprintf (stderr, _("%s: -c not supported on architecture %s\n"),
306                whoami, bfd_printable_name(core_bfd));
307
308       /* Don't give the error more than once.  */
309       ignore_direct_calls = FALSE;
310     }
311 }
312
313 /* Return class of symbol SYM.  The returned class can be any of:
314         0   -> symbol is not interesting to us
315         'T' -> symbol is a global name
316         't' -> symbol is a local (static) name.  */
317
318 static int
319 core_sym_class (asymbol *sym)
320 {
321   symbol_info syminfo;
322   const char *name;
323   char sym_prefix;
324   int i;
325
326   if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
327     return 0;
328
329   /* Must be a text symbol, and static text symbols
330      don't qualify if ignore_static_funcs set.   */
331   if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
332     {
333       DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
334                               sym->name));
335       return 0;
336     }
337
338   bfd_get_symbol_info (core_bfd, sym, &syminfo);
339   i = syminfo.type;
340
341   if (i == 'T')
342     return i;                   /* It's a global symbol.  */
343
344   if (i == 'W')
345     /* Treat weak symbols as text symbols.  FIXME: a weak symbol may
346        also be a data symbol.  */
347     return 'T';
348
349   if (i != 't')
350     {
351       /* Not a static text symbol.  */
352       DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
353                               sym->name, i));
354       return 0;
355     }
356
357   /* Do some more filtering on static function-names.  */
358   if (ignore_static_funcs)
359     return 0;
360
361   /* Can't zero-length name or funny characters in name, where
362      `funny' includes: `.' (.o file names) and `$' (Pascal labels).  */
363   if (!sym->name || sym->name[0] == '\0')
364     return 0;
365
366   for (name = sym->name; *name; ++name)
367     {
368       if (*name == '.' || *name == '$')
369         return 0;
370     }
371
372   /* On systems where the C compiler adds an underscore to all
373      names, static names without underscores seem usually to be
374      labels in hand written assembler in the library.  We don't want
375      these names.  This is certainly necessary on a Sparc running
376      SunOS 4.1 (try profiling a program that does a lot of
377      division). I don't know whether it has harmful side effects on
378      other systems.  Perhaps it should be made configurable.  */
379   sym_prefix = bfd_get_symbol_leading_char (core_bfd);
380
381   if ((sym_prefix && sym_prefix != sym->name[0])
382       /* GCC may add special symbols to help gdb figure out the file
383         language.  We want to ignore these, since sometimes they mask
384         the real function.  (dj@ctron)  */
385       || !strncmp (sym->name, "__gnu_compiled", 14)
386       || !strncmp (sym->name, "___gnu_compiled", 15))
387     {
388       return 0;
389     }
390
391   /* If the object file supports marking of function symbols, then
392      we can zap anything that doesn't have BSF_FUNCTION set.  */
393   if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
394     return 0;
395
396   return 't';                   /* It's a static text symbol.  */
397 }
398
399 /* Get whatever source info we can get regarding address ADDR.  */
400
401 static bfd_boolean
402 get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_num)
403 {
404   const char *fname = 0, *func_name = 0;
405   int l = 0;
406
407   if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
408                              addr - core_text_sect->vma,
409                              &fname, &func_name, (unsigned int *) &l)
410       && fname && func_name && l)
411     {
412       DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
413                               (unsigned long) addr, fname, l, func_name));
414       *filename = fname;
415       *name = func_name;
416       *line_num = l;
417       return TRUE;
418     }
419   else
420     {
421       DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
422                               (long) addr, fname ? fname : "<unknown>", l,
423                               func_name ? func_name : "<unknown>"));
424       return FALSE;
425     }
426 }
427
428 /* Read in symbol table from core.
429    One symbol per function is entered.  */
430
431 void
432 core_create_function_syms ()
433 {
434   bfd_vma min_vma = ~(bfd_vma) 0;
435   bfd_vma max_vma = 0;
436   int class;
437   long i, found, skip;
438   unsigned int j;
439
440   /* Pass 1 - determine upper bound on number of function names.  */
441   symtab.len = 0;
442
443   for (i = 0; i < core_num_syms; ++i)
444     {
445       if (!core_sym_class (core_syms[i]))
446         continue;
447
448       /* This should be replaced with a binary search or hashed
449          search.  Gross.
450
451          Don't create a symtab entry for a function that has
452          a mapping to a file, unless it's the first function
453          in the file.  */
454       skip = 0;
455       for (j = 0; j < symbol_map_count; j++)
456         if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
457           {
458             if (j > 0 && ! strcmp (symbol_map [j].file_name,
459                                    symbol_map [j - 1].file_name))
460               skip = 1;
461             break;
462           }
463
464       if (!skip)
465         ++symtab.len;
466     }
467
468   if (symtab.len == 0)
469     {
470       fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name);
471       done (1);
472     }
473
474   /* The "+ 2" is for the sentinels.  */
475   symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym));
476
477   /* Pass 2 - create symbols.  */
478   symtab.limit = symtab.base;
479
480   for (i = 0; i < core_num_syms; ++i)
481     {
482       asection *sym_sec;
483
484       class = core_sym_class (core_syms[i]);
485
486       if (!class)
487         {
488           DBG (AOUTDEBUG,
489                printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
490                        (unsigned long) core_syms[i]->value,
491                        core_syms[i]->name));
492           continue;
493         }
494
495       /* This should be replaced with a binary search or hashed
496          search.  Gross.   */
497       skip = 0;
498       found = 0;
499
500       for (j = 0; j < symbol_map_count; j++)
501         if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
502           {
503             if (j > 0 && ! strcmp (symbol_map [j].file_name,
504                                    symbol_map [j - 1].file_name))
505               skip = 1;
506             else
507               found = j;
508             break;
509           }
510
511       if (skip)
512         continue;
513
514       sym_init (symtab.limit);
515
516       /* Symbol offsets are always section-relative.  */
517       sym_sec = core_syms[i]->section;
518       symtab.limit->addr = core_syms[i]->value;
519       if (sym_sec)
520         symtab.limit->addr += bfd_get_section_vma (sym_sec->owner, sym_sec);
521
522       if (symbol_map_count
523           && !strcmp (core_syms[i]->name, symbol_map[found].function_name))
524         {
525           symtab.limit->name = symbol_map[found].file_name;
526           symtab.limit->mapped = 1;
527         }
528       else
529         {
530           symtab.limit->name = core_syms[i]->name;
531           symtab.limit->mapped = 0;
532         }
533
534       /* Lookup filename and line number, if we can.  */
535       {
536         const char *filename, *func_name;
537
538         if (get_src_info (symtab.limit->addr, &filename, &func_name,
539                           &symtab.limit->line_num))
540           {
541             symtab.limit->file = source_file_lookup_path (filename);
542
543             /* FIXME: Checking __osf__ here does not work with a cross
544                gprof.  */
545 #ifdef __osf__
546             /* Suppress symbols that are not function names.  This is
547                useful to suppress code-labels and aliases.
548
549                This is known to be useful under DEC's OSF/1.  Under SunOS 4.x,
550                labels do not appear in the symbol table info, so this isn't
551                necessary.  */
552
553             if (strcmp (symtab.limit->name, func_name) != 0)
554               {
555                 /* The symbol's address maps to a different name, so
556                    it can't be a function-entry point.  This happens
557                    for labels, for example.  */
558                 DBG (AOUTDEBUG,
559                      printf ("[core_create_function_syms: rej %s (maps to %s)\n",
560                              symtab.limit->name, func_name));
561                 continue;
562               }
563 #endif
564           }
565       }
566
567       symtab.limit->is_func = TRUE;
568       symtab.limit->is_bb_head = TRUE;
569
570       if (class == 't')
571         symtab.limit->is_static = TRUE;
572
573       /* Keep track of the minimum and maximum vma addresses used by all
574          symbols.  When computing the max_vma, use the ending address of the
575          section containing the symbol, if available.  */
576       min_vma = MIN (symtab.limit->addr, min_vma);
577       if (sym_sec)
578         max_vma = MAX (bfd_get_section_vma (sym_sec->owner, sym_sec)
579                        + bfd_section_size (sym_sec->owner, sym_sec) - 1,
580                        max_vma);
581       else
582         max_vma = MAX (symtab.limit->addr, max_vma);
583
584       /* If we see "main" without an initial '_', we assume names
585          are *not* prefixed by '_'.  */
586       if (symtab.limit->name[0] == 'm' && discard_underscores
587           && strcmp (symtab.limit->name, "main") == 0)
588         discard_underscores = 0;
589
590       DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
591                               (long) (symtab.limit - symtab.base),
592                               symtab.limit->name,
593                               (unsigned long) symtab.limit->addr));
594       ++symtab.limit;
595     }
596
597   /* Create sentinels.  */
598   sym_init (symtab.limit);
599   symtab.limit->name = "<locore>";
600   symtab.limit->addr = 0;
601   symtab.limit->end_addr = min_vma - 1;
602   ++symtab.limit;
603
604   sym_init (symtab.limit);
605   symtab.limit->name = "<hicore>";
606   symtab.limit->addr = max_vma + 1;
607   symtab.limit->end_addr = ~(bfd_vma) 0;
608   ++symtab.limit;
609
610   symtab.len = symtab.limit - symtab.base;
611   symtab_finalize (&symtab);
612 }
613
614 /* Read in symbol table from core.
615    One symbol per line of source code is entered.  */
616
617 void
618 core_create_line_syms ()
619 {
620   char *prev_name, *prev_filename;
621   unsigned int prev_name_len, prev_filename_len;
622   bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0;
623   Sym *prev, dummy, *sentinel, *sym;
624   const char *filename;
625   int prev_line_num;
626   Sym_Table ltab;
627   bfd_vma vma_high;
628
629   /* Create symbols for functions as usual.  This is necessary in
630      cases where parts of a program were not compiled with -g.  For
631      those parts we still want to get info at the function level.  */
632   core_create_function_syms ();
633
634   /* Pass 1: count the number of symbols.  */
635
636   /* To find all line information, walk through all possible
637      text-space addresses (one by one!) and get the debugging
638      info for each address.  When the debugging info changes,
639      it is time to create a new symbol.
640
641      Of course, this is rather slow and it would be better if
642      BFD would provide an iterator for enumerating all line infos.  */
643   prev_name_len = PATH_MAX;
644   prev_filename_len = PATH_MAX;
645   prev_name = xmalloc (prev_name_len);
646   prev_filename = xmalloc (prev_filename_len);
647   ltab.len = 0;
648   prev_line_num = 0;
649
650   vma_high = core_text_sect->vma + bfd_get_section_size (core_text_sect);
651   for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
652     {
653       unsigned int len;
654
655       if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
656           || (prev_line_num == dummy.line_num
657               && prev_name != NULL
658               && strcmp (prev_name, dummy.name) == 0
659               && strcmp (prev_filename, filename) == 0))
660         continue;
661
662       ++ltab.len;
663       prev_line_num = dummy.line_num;
664
665       len = strlen (dummy.name);
666       if (len >= prev_name_len)
667         {
668           prev_name_len = len + 1024;
669           free (prev_name);
670           prev_name = xmalloc (prev_name_len);
671         }
672
673       strcpy (prev_name, dummy.name);
674       len = strlen (filename);
675
676       if (len >= prev_filename_len)
677         {
678           prev_filename_len = len + 1024;
679           free (prev_filename);
680           prev_filename = xmalloc (prev_filename_len);
681         }
682
683       strcpy (prev_filename, filename);
684
685       min_vma = MIN (vma, min_vma);
686       max_vma = MAX (vma, max_vma);
687     }
688
689   free (prev_name);
690   free (prev_filename);
691
692   /* Make room for function symbols, too.  */
693   ltab.len += symtab.len;
694   ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
695   ltab.limit = ltab.base;
696
697   /* Pass 2 - create symbols.  */
698
699   /* We now set is_static as we go along, rather than by running
700      through the symbol table at the end.
701
702      The old way called symtab_finalize before the is_static pass,
703      causing a problem since symtab_finalize uses is_static as part of
704      its address conflict resolution algorithm.  Since global symbols
705      were prefered over static symbols, and all line symbols were
706      global at that point, static function names that conflicted with
707      their own line numbers (static, but labeled as global) were
708      rejected in favor of the line num.
709
710      This was not the desired functionality.  We always want to keep
711      our function symbols and discard any conflicting line symbols.
712      Perhaps symtab_finalize should be modified to make this
713      distinction as well, but the current fix works and the code is a
714      lot cleaner now.  */
715   prev = 0;
716
717   for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
718     {
719       sym_init (ltab.limit);
720
721       if (!get_src_info (vma, &filename, &ltab.limit->name, &ltab.limit->line_num)
722           || (prev && prev->line_num == ltab.limit->line_num
723               && strcmp (prev->name, ltab.limit->name) == 0
724               && strcmp (prev->file->name, filename) == 0))
725         continue;
726
727       /* Make name pointer a malloc'ed string.  */
728       ltab.limit->name = xstrdup (ltab.limit->name);
729       ltab.limit->file = source_file_lookup_path (filename);
730
731       ltab.limit->addr = vma;
732
733       /* Set is_static based on the enclosing function, using either:
734          1) the previous symbol, if it's from the same function, or
735          2) a symtab lookup.  */
736       if (prev && ltab.limit->file == prev->file &&
737           strcmp (ltab.limit->name, prev->name) == 0)
738         {
739           ltab.limit->is_static = prev->is_static;
740         }
741       else
742         {
743           sym = sym_lookup(&symtab, ltab.limit->addr);
744           ltab.limit->is_static = sym->is_static;
745         }
746
747       prev = ltab.limit;
748
749       /* If we see "main" without an initial '_', we assume names
750          are *not* prefixed by '_'.  */
751       if (ltab.limit->name[0] == 'm' && discard_underscores
752           && strcmp (ltab.limit->name, "main") == 0)
753         discard_underscores = 0;
754
755       DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
756                               (unsigned long) (ltab.limit - ltab.base),
757                               ltab.limit->name,
758                               (unsigned long) ltab.limit->addr));
759       ++ltab.limit;
760     }
761
762   /* Update sentinels.  */
763   sentinel = sym_lookup (&symtab, (bfd_vma) 0);
764
765   if (sentinel
766       && strcmp (sentinel->name, "<locore>") == 0
767       && min_vma <= sentinel->end_addr)
768     sentinel->end_addr = min_vma - 1;
769
770   sentinel = sym_lookup (&symtab, ~(bfd_vma) 0);
771
772   if (sentinel
773       && strcmp (sentinel->name, "<hicore>") == 0
774       && max_vma >= sentinel->addr)
775     sentinel->addr = max_vma + 1;
776
777   /* Copy in function symbols.  */
778   memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
779   ltab.limit += symtab.len;
780
781   if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
782     {
783       fprintf (stderr,
784                _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
785                whoami, ltab.len, (long) (ltab.limit - ltab.base));
786       done (1);
787     }
788
789   /* Finalize ltab and make it symbol table.  */
790   symtab_finalize (&ltab);
791   free (symtab.base);
792   symtab = ltab;
793 }