1 /* All symbol handling for the linker
2 Copyright (C) 1991 Free Software Foundation, Inc.
5 This file is part of GLD, the Gnu Linker.
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 We keep a hash table of global symbols. Each entry in a hash table
23 is called an ldsym_type. Each has three chains; a pointer to a
24 chain of definitions for the symbol (hopefully one long), a pointer
25 to a chain of references to the symbol, and a pointer to a chain of
26 common symbols. Each pointer points into the canonical symbol table
27 provided by bfd, each one of which points to an asymbol. During
28 linkage, the linker uses the udata field to point to the next entry
29 in a canonical table....
34 +----------+ +----------+
35 | defs | a canonical symbol table
36 +----------+ +----------+
37 | refs | -----> | one entry| -----> asymbol
38 +----------+ +----------+ | |
39 | coms | | | +---------+
40 +----------+ +----------+ | udata |-----> another canonical symbol
45 It is very simple to make all the symbol pointers point to the same
46 definition - just run down the chain and make the asymbols pointers
47 within the canonical table point to the asymbol attacthed to the
48 definition of the symbol.
61 extern bfd *output_bfd;
62 extern strip_symbols_type strip_symbols;
63 extern discard_locals_type discard_locals;
64 /* Head and tail of global symbol table chronological list */
66 ldsym_type *symbol_head = (ldsym_type *)NULL;
67 ldsym_type **symbol_tail_ptr = &symbol_head;
68 CONST char *keepsyms_file;
71 extern ld_config_type config;
73 struct obstack global_sym_obstack;
74 #define obstack_chunk_alloc ldmalloc
75 #define obstack_chunk_free free
78 incremented for each symbol in the ldsym_type table
79 no matter what flavour it is
81 unsigned int global_symbol_count;
85 extern boolean option_longmap ;
89 static ldsym_type *global_symbol_hash_table[TABSIZE];
91 /* Compute the hash code for symbol name KEY. */
98 DEFUN(hash_string,(key),
101 register CONST char *cp;
107 k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
115 #endif ldsym_type *bp;
117 DEFUN(search,(key,hashval) ,
122 for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
123 if (! strcmp (key, bp->name)) {
124 if (bp->flags & SYM_INDIRECT) {
125 /* Use the symbol we're aliased to instead */
126 return (ldsym_type *)(bp->sdefs_chain);
134 /* Get the symbol table entry for the global symbol named KEY.
135 Create one if there is none. */
137 DEFUN(ldsym_get,(key),
140 register int hashval;
141 register ldsym_type *bp;
143 /* Determine the proper bucket. */
145 hashval = hash_string (key) % TABSIZE;
147 /* Search the bucket. */
148 bp = search(key, hashval);
153 /* Nothing was found; create a new symbol table entry. */
155 bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type)(sizeof (ldsym_type)));
156 bp->srefs_chain = (asymbol **)NULL;
157 bp->sdefs_chain = (asymbol **)NULL;
158 bp->scoms_chain = (asymbol **)NULL;
159 bp->name = obstack_copy(&global_sym_obstack, key, strlen(key)+1);
161 /* Add the entry to the bucket. */
163 bp->link = global_symbol_hash_table[hashval];
164 global_symbol_hash_table[hashval] = bp;
166 /* Keep the chronological list up to date too */
167 *symbol_tail_ptr = bp;
168 symbol_tail_ptr = &bp->next;
170 global_symbol_count++;
175 /* Like `ldsym_get' but return 0 if the symbol is not already known. */
178 DEFUN(ldsym_get_soft,(key),
181 register int hashval;
182 /* Determine which bucket. */
184 hashval = hash_string (key) % TABSIZE;
186 /* Search the bucket. */
187 return search(key, hashval);
191 process_keepsyms (table, size)
195 struct obstack obstack;
196 char *start_of_obstack;
198 asymbol **out = table;
199 asymbol **end = table + size;
202 if (!keepsyms_file || size == 0)
204 obstack_init (&obstack);
205 obstack_alloc (&obstack, 1);
206 obstack_finish (&obstack);
207 start_of_obstack = obstack_alloc (&obstack, 1);
208 ks_file = fopen (keepsyms_file, "r");
211 info ("%X%P: can't open keep-symbols file `%s'\n", keepsyms_file);
217 do { asymbol **p=(S), *tmp=*out; *out=*p; *p=tmp; out++; } while (0)
219 while (!feof (ks_file) && !ferror (ks_file))
225 obstack_free (&obstack, start_of_obstack);
231 obstack_1grow (&obstack, c);
239 info ("%X%P: error reading keep-symbols file `%s': %E\n",
244 if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1)
245 /* eof in middle of symbol */
247 info ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n",
252 /* All okay -- no incomplete lines, EOF reached. */
255 ptr = obstack_next_free (&obstack) - 2;
256 /* discard trailing trash */
260 ptr = obstack_base (&obstack);
261 for (sym = out; sym < end; sym++)
262 if (!strcmp ((*sym)->name, ptr))
268 info ("%P: symbol `%s' (requested to be kept) not found\n", ptr);
270 /* It'd be slightly faster to move this pass above the previous one,
271 but that'd mean any symbols preserved in this pass would generate
272 warnings if they were also listed in the keepsyms file. */
273 for (sym = out; sym < end; sym++)
276 if (s->section == &bfd_und_section
277 || s->section == &bfd_com_section
278 || s->flags & BSF_KEEP_G)
282 obstack_free (&obstack, start_of_obstack);
289 list_file_locals (entry)
290 lang_input_statement_type *entry;
293 fprintf (config.map_file, "\nLocal symbols of ");
295 fprintf (config.map_file, ":\n\n");
296 if (entry->asymbols) {
297 for (q = entry->asymbols; *q; q++)
300 /* If this is a definition,
301 update it if necessary by this file's start address. */
302 if (p->flags & BSF_LOCAL)
303 info(" %V %s\n",p->value, p->name);
310 DEFUN(print_file_stuff,(f),
311 lang_input_statement_type *f)
313 fprintf (config.map_file," %s\n", f->filename);
314 if (f->just_syms_flag)
316 fprintf (config.map_file, " symbols only\n");
321 if (true || option_longmap) {
322 for (s = f->the_bfd->sections;
323 s != (asection *)NULL;
325 print_address(s->output_offset);
328 fprintf (config.map_file, " %08x 2**%2ud %s\n",
329 (unsigned)bfd_get_section_size_after_reloc(s),
330 s->alignment_power, s->name);
335 fprintf (config.map_file, " %08x 2**%2ud %s\n",
336 (unsigned)bfd_get_section_size_before_reloc(s),
337 s->alignment_power, s->name);
343 for (s = f->the_bfd->sections;
344 s != (asection *)NULL;
346 fprintf(config.map_file, "%s ", s->name);
347 print_address(s->output_offset);
348 fprintf(config.map_file, "(%x)", (unsigned)bfd_get_section_size_after_reloc(s));
350 fprintf(config.map_file, "hex \n");
353 fprintf (config.map_file, "\n");
357 ldsym_print_symbol_table ()
359 fprintf (config.map_file, "**FILES**\n\n");
361 lang_for_each_file(print_file_stuff);
363 fprintf(config.map_file, "**GLOBAL SYMBOLS**\n\n");
364 fprintf(config.map_file, "offset section offset symbol\n");
366 register ldsym_type *sp;
368 for (sp = symbol_head; sp; sp = sp->next)
370 if (sp->flags & SYM_INDIRECT) {
371 fprintf(config.map_file,"indirect %s to %s\n",
372 sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
377 asymbol *defsym = *(sp->sdefs_chain);
378 asection *defsec = bfd_get_section(defsym);
379 print_address(defsym->value);
382 fprintf(config.map_file, " %-10s",
383 bfd_section_name(output_bfd,
386 print_address(defsym->value+defsec->vma);
391 fprintf(config.map_file, " .......");
397 if (sp->scoms_chain) {
398 fprintf(config.map_file, "common ");
399 print_address((*(sp->scoms_chain))->value);
400 fprintf(config.map_file, " %s ",sp->name);
402 else if (sp->sdefs_chain) {
403 fprintf(config.map_file, " %s ",sp->name);
406 fprintf(config.map_file, "undefined ");
407 fprintf(config.map_file, "%s ",sp->name);
415 if (option_longmap) {
416 lang_for_each_file(list_file_locals);
420 extern lang_output_section_statement_type *create_object_symbols;
423 write_file_locals(output_buffer)
424 asymbol **output_buffer;
426 LANG_FOR_EACH_INPUT_STATEMENT(entry)
428 /* Run trough the symbols and work out what to do with them */
431 /* Add one for the filename symbol if needed */
432 if (create_object_symbols
433 != (lang_output_section_statement_type *)NULL) {
435 for (s = entry->the_bfd->sections;
436 s != (asection *)NULL;
438 if (s->output_section == create_object_symbols->bfd_section) {
439 /* Add symbol to this section */
441 (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
442 newsym->name = entry->local_sym_name;
443 /* The symbol belongs to the output file's text section */
445 /* The value is the start of this section in the output file*/
447 /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as
448 "used by the linker" and I can't find any other code that
449 uses it. Should be a cleaner way of doing this (like an
450 "application flags" field in the symbol structure?). */
451 newsym->flags = BSF_LOCAL | BSF_KEEP_G;
453 *output_buffer++ = newsym;
458 for (i = 0; i < entry->symbol_count; i++)
460 asymbol *p = entry->asymbols[i];
461 /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
464 p->section = &bfd_abs_section;
465 if (flag_is_global(p->flags) )
467 /* We are only interested in outputting
468 globals at this stage in special circumstances */
469 if (p->the_bfd == entry->the_bfd
470 && flag_is_not_at_end(p->flags)) {
471 /* And this is one of them */
472 *(output_buffer++) = p;
473 p->flags |= BSF_KEEP;
477 if (flag_is_debugger(p->flags))
479 /* Only keep the debugger symbols if no stripping required */
480 if (strip_symbols == STRIP_NONE) {
481 *output_buffer++ = p;
484 else if (p->section == &bfd_und_section
485 || p->section == &bfd_com_section)
487 /* These must be global. */
489 else if (flag_is_ordinary_local(p->flags))
491 if (discard_locals == DISCARD_ALL)
493 else if (discard_locals == DISCARD_L &&
494 (p->name[0] == lprefix))
496 else if (p->flags == BSF_WARNING)
499 { *output_buffer++ = p; }
501 else if (p->flags & BSF_CTOR) {
513 return output_buffer;
518 write_file_globals(symbol_table)
519 asymbol **symbol_table;
523 if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) {
524 asymbol *bufp = (*(sp->sdefs_chain));
526 if ((bufp->flags & BSF_KEEP) ==0) {
527 ASSERT(bufp != (asymbol *)NULL);
529 bufp->name = sp->name;
531 if (sp->scoms_chain != (asymbol **)NULL)
535 defined as common but not allocated, this happens
536 only with -r and not -d, write out a common
539 bufp = *(sp->scoms_chain);
541 *symbol_table++ = bufp;
544 else if (sp->scoms_chain != (asymbol **)NULL) {
545 /* This symbol is a common - just output */
546 asymbol *bufp = (*(sp->scoms_chain));
547 *symbol_table++ = bufp;
549 else if (sp->srefs_chain != (asymbol **)NULL) {
550 /* This symbol is undefined but has a reference */
551 asymbol *bufp = (*(sp->srefs_chain));
552 *symbol_table++ = bufp;
556 This symbol has neither defs nor refs, it must have come
557 from the command line, since noone has used it it has no
558 data attatched, so we'll ignore it
568 if (keepsyms_file != 0
569 && strip_symbols != STRIP_SOME)
571 info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n");
572 strip_symbols = STRIP_SOME;
574 if (strip_symbols != STRIP_ALL) {
575 /* We know the maximum size of the symbol table -
576 it's the size of all the global symbols ever seen +
577 the size of all the symbols from all the files +
578 the number of files (for the per file symbols)
579 +1 (for the null at the end)
581 extern unsigned int total_files_seen;
582 extern unsigned int total_symbols_seen;
584 asymbol ** symbol_table = (asymbol **)
585 ldmalloc ((bfd_size_type)(global_symbol_count +
587 total_symbols_seen + 1) * sizeof (asymbol *));
588 asymbol ** tablep = write_file_locals(symbol_table);
590 tablep = write_file_globals(tablep);
591 tablep = process_keepsyms (symbol_table, tablep - symbol_table);
593 *tablep = (asymbol *)NULL;
594 bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
599 return true if the supplied symbol name is not in the
603 DEFUN(ldsym_undefined,(sym),
606 ldsym_type *from_table = ldsym_get_soft(sym);
607 if (from_table != (ldsym_type *)NULL)
609 if (from_table->sdefs_chain != (asymbol **)NULL) return false;
615 DEFUN_VOID(ldsym_init)
617 obstack_begin(&global_sym_obstack, 20000);