OSDN Git Service

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