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