source: trunk/binutils/gprof/corefile.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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