Tue Mar 30 09:40:25 1993 Steve Chamberlain (sac@thepub.cygnus.com)
[binutils-gdb.git] / ld / ldsym.c
1 /* All symbol handling for the linker
2 Copyright (C) 1991 Free Software Foundation, Inc.
3 Written by Steve Chamberlain steve@cygnus.com
4
5 This file is part of GLD, the Gnu Linker.
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /*
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....
30
31
32 ld_sym
33 | |
34 +----------+ +----------+
35 | defs | a canonical symbol table
36 +----------+ +----------+
37 | refs | -----> | one entry| -----> asymbol
38 +----------+ +----------+ | |
39 | coms | | | +---------+
40 +----------+ +----------+ | udata |-----> another canonical symbol
41 +---------+
42
43
44
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.
49
50 */
51
52 #include "bfd.h"
53 #include "sysdep.h"
54
55 #include "ld.h"
56 #include "ldsym.h"
57 #include "ldmisc.h"
58 #include "ldlang.h"
59 /* IMPORT */
60 extern int symbol_truncate;
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 */
65
66 ldsym_type *symbol_head = (ldsym_type *) NULL;
67 ldsym_type **symbol_tail_ptr = &symbol_head;
68 CONST char *keepsyms_file;
69 int kept_syms;
70
71 extern ld_config_type config;
72
73 struct obstack global_sym_obstack;
74 #define obstack_chunk_alloc ldmalloc
75 #define obstack_chunk_free free
76
77 /*
78 incremented for each symbol in the ldsym_type table
79 no matter what flavour it is
80 */
81 unsigned int global_symbol_count;
82
83 /* IMPORTS */
84
85 extern boolean option_longmap;
86
87 /* LOCALS */
88 #define TABSIZE 1009
89 static ldsym_type *global_symbol_hash_table[TABSIZE];
90
91 /* Compute the hash code for symbol name KEY. */
92 static
93 #ifdef __GNUC__
94 __inline
95 #endif
96
97 int
98 DEFUN (hash_string, (key),
99 CONST char *key)
100 {
101 register CONST char *cp;
102 register int k;
103 register int l = 0;
104 cp = key;
105 k = 0;
106 while (*cp && l < symbol_truncate)
107 {
108 k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
109 l++;
110 }
111 return k;
112 }
113
114 static
115 #ifdef __GNUC__
116 __inline
117 #endif
118 ldsym_type *
119 DEFUN (search, (key, hashval),
120 CONST char *key AND
121 int hashval)
122 {
123 ldsym_type *bp;
124 for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
125 if (!strncmp (key, bp->name, symbol_truncate))
126 {
127 if (bp->flags & SYM_INDIRECT)
128 {
129 /* Use the symbol we're aliased to instead */
130 return (ldsym_type *) (bp->sdefs_chain);
131 }
132 return bp;
133 }
134 return 0;
135 }
136
137
138 /* Get the symbol table entry for the global symbol named KEY.
139 Create one if there is none. */
140 ldsym_type *
141 DEFUN (ldsym_get, (key),
142 CONST char *key)
143 {
144 register int hashval;
145 register ldsym_type *bp;
146
147 /* Determine the proper bucket. */
148
149 hashval = hash_string (key) % TABSIZE;
150
151 /* Search the bucket. */
152 bp = search (key, hashval);
153 if (bp)
154 {
155 return bp;
156 }
157
158 /* Nothing was found; create a new symbol table entry. */
159
160 bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type) (sizeof (ldsym_type)));
161 bp->srefs_chain = (asymbol **) NULL;
162 bp->sdefs_chain = (asymbol **) NULL;
163 bp->scoms_chain = (asymbol **) NULL;
164 bp->name = obstack_copy (&global_sym_obstack, key, strlen (key) + 1);
165 bp->flags = 0;
166 /* Add the entry to the bucket. */
167
168 bp->link = global_symbol_hash_table[hashval];
169 global_symbol_hash_table[hashval] = bp;
170
171 /* Keep the chronological list up to date too */
172 *symbol_tail_ptr = bp;
173 symbol_tail_ptr = &bp->next;
174 bp->next = 0;
175 global_symbol_count++;
176
177 return bp;
178 }
179
180 /* Like `ldsym_get' but return 0 if the symbol is not already known. */
181
182 ldsym_type *
183 DEFUN (ldsym_get_soft, (key),
184 CONST char *key)
185 {
186 register int hashval;
187 /* Determine which bucket. */
188
189 hashval = hash_string (key) % TABSIZE;
190
191 /* Search the bucket. */
192 return search (key, hashval);
193 }
194
195 static asymbol **
196 process_keepsyms (table, size)
197 asymbol **table;
198 int size;
199 {
200 struct obstack obstack;
201 char *start_of_obstack;
202 FILE *ks_file = 0;
203 asymbol **out = table;
204 asymbol **end = table + size;
205 asymbol **sym;
206
207 if (!keepsyms_file || size == 0)
208 return end;
209 obstack_init (&obstack);
210 obstack_alloc (&obstack, 1);
211 obstack_finish (&obstack);
212 start_of_obstack = obstack_alloc (&obstack, 1);
213 ks_file = fopen (keepsyms_file, "r");
214 if (!ks_file)
215 {
216 info ("%X%P: can't open keep-symbols file `%s'\n", keepsyms_file);
217 goto egress;
218 }
219 errno = 0;
220
221 #define KEEP(S) \
222 do { asymbol **p = (S), *tmp = *out; *out = *p; *p = tmp; out++; } while (0)
223
224 while (!feof (ks_file) && !ferror (ks_file))
225 {
226 int c;
227 char *ptr;
228 int found = 0;
229
230 obstack_free (&obstack, start_of_obstack);
231 do
232 {
233 c = getc (ks_file);
234 if (c == '\n')
235 c = 0;
236 obstack_1grow (&obstack, c);
237 }
238 while (c > 0);
239 if (c == EOF)
240 {
241 if (!feof (ks_file))
242 /* error occurred */
243 {
244 info ("%X%P: error reading keep-symbols file `%s': %E\n",
245 keepsyms_file);
246 out = end;
247 goto egress;
248 }
249 if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1)
250 /* eof in middle of symbol */
251 {
252 info ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n",
253 keepsyms_file);
254 out = end;
255 goto egress;
256 }
257 /* All okay -- no incomplete lines, EOF reached. */
258 break;
259 }
260 ptr = obstack_next_free (&obstack) - 2;
261 /* discard trailing trash */
262 while (*ptr == ' '
263 || *ptr == '\t')
264 *ptr-- = 0;
265 ptr = obstack_base (&obstack);
266 for (sym = out; sym < end; sym++)
267 if (!strncmp ((*sym)->name, ptr, symbol_truncate))
268 {
269 KEEP (sym);
270 found = 1;
271 }
272 if (!found)
273 info ("%P: symbol `%s' (requested to be kept) not found\n", ptr);
274 }
275 /* It'd be slightly faster to move this pass above the previous one,
276 but that'd mean any symbols preserved in this pass would generate
277 warnings if they were also listed in the keepsyms file. */
278 for (sym = out; sym < end; sym++)
279 {
280 asymbol *s = *sym;
281 if (s->section == &bfd_und_section
282 || bfd_is_com_section (s->section)
283 || s->flags & BSF_KEEP_G)
284 KEEP (sym);
285 }
286 egress:
287 obstack_free (&obstack, start_of_obstack);
288 if (ks_file)
289 fclose (ks_file);
290 return out;
291 }
292
293 static void
294 list_file_locals (entry)
295 lang_input_statement_type *entry;
296 {
297 asymbol **q;
298 fprintf (config.map_file, "\nLocal symbols of ");
299 minfo ("%I", entry);
300 fprintf (config.map_file, ":\n\n");
301 if (entry->asymbols)
302 {
303 for (q = entry->asymbols; *q; q++)
304 {
305 asymbol *p = *q;
306 /* If this is a definition,
307 update it if necessary by this file's start address. */
308 if (p->flags & BSF_LOCAL)
309 info (" %V %s\n", p->value, p->name);
310 }
311 }
312 }
313
314
315 static void
316 DEFUN (print_file_stuff, (f),
317 lang_input_statement_type * f)
318 {
319 fprintf (config.map_file, " %s\n", f->filename);
320 if (f->just_syms_flag)
321 {
322 fprintf (config.map_file, " symbols only\n");
323 }
324 else
325 {
326 asection *s;
327 if (true || option_longmap)
328 {
329 for (s = f->the_bfd->sections;
330 s != (asection *) NULL;
331 s = s->next)
332 {
333 print_address (s->output_offset);
334 if (s->reloc_done)
335 {
336 fprintf (config.map_file, " %08x 2**%2ud %s\n",
337 (unsigned) bfd_get_section_size_after_reloc (s),
338 s->alignment_power, s->name);
339 }
340
341 else
342 {
343 fprintf (config.map_file, " %08x 2**%2ud %s\n",
344 (unsigned) bfd_get_section_size_before_reloc (s),
345 s->alignment_power, s->name);
346 }
347 }
348 }
349 else
350 {
351 for (s = f->the_bfd->sections;
352 s != (asection *) NULL;
353 s = s->next)
354 {
355 fprintf (config.map_file, "%s ", s->name);
356 print_address (s->output_offset);
357 fprintf (config.map_file, "(%x)", (unsigned) bfd_get_section_size_after_reloc (s));
358 }
359 fprintf (config.map_file, "hex \n");
360 }
361 }
362 fprintf (config.map_file, "\n");
363 }
364
365 void
366 ldsym_print_symbol_table ()
367 {
368 fprintf (config.map_file, "**FILES**\n\n");
369
370 lang_for_each_file (print_file_stuff);
371
372 fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
373 fprintf (config.map_file, "offset section offset symbol\n");
374 {
375 register ldsym_type *sp;
376
377 for (sp = symbol_head; sp; sp = sp->next)
378 {
379 if (sp->flags & SYM_INDIRECT)
380 {
381 fprintf (config.map_file, "indirect %s to %s\n",
382 sp->name, (((ldsym_type *) (sp->sdefs_chain))->name));
383 }
384 else
385 {
386 if (sp->sdefs_chain)
387 {
388 asymbol *defsym = *(sp->sdefs_chain);
389 asection *defsec = bfd_get_section (defsym);
390 print_address (defsym->value);
391 if (defsec)
392 {
393 fprintf (config.map_file, " %-10s",
394 bfd_section_name (output_bfd,
395 defsec));
396 print_space ();
397 print_address (defsym->value + defsec->vma);
398
399 }
400 else
401 {
402 fprintf (config.map_file, " .......");
403 }
404
405 }
406
407
408 if (sp->scoms_chain)
409 {
410 fprintf (config.map_file, "common ");
411 print_address ((*(sp->scoms_chain))->value);
412 fprintf (config.map_file, " %s ", sp->name);
413 }
414 else if (sp->sdefs_chain)
415 {
416 fprintf (config.map_file, " %s ", sp->name);
417 }
418 else
419 {
420 fprintf (config.map_file, "undefined ");
421 fprintf (config.map_file, "%s ", sp->name);
422
423 }
424 }
425 print_nl ();
426
427 }
428 }
429 if (option_longmap)
430 {
431 lang_for_each_file (list_file_locals);
432 }
433 }
434
435 extern lang_output_section_statement_type *create_object_symbols;
436 extern char lprefix;
437 static asymbol **
438 write_file_locals (output_buffer)
439 asymbol **output_buffer;
440 {
441 LANG_FOR_EACH_INPUT_STATEMENT (entry)
442 {
443 /* Run trough the symbols and work out what to do with them */
444 unsigned int i;
445
446 /* Add one for the filename symbol if needed */
447 if (create_object_symbols
448 != (lang_output_section_statement_type *) NULL)
449 {
450 asection *s;
451 for (s = entry->the_bfd->sections;
452 s != (asection *) NULL;
453 s = s->next)
454 {
455 if (s->output_section == create_object_symbols->bfd_section)
456 {
457 /* Add symbol to this section */
458 asymbol *newsym =
459 (asymbol *) bfd_make_empty_symbol (entry->the_bfd);
460 newsym->name = entry->local_sym_name;
461 /* The symbol belongs to the output file's text section */
462
463 /* The value is the start of this section in the output file*/
464 newsym->value = 0;
465 /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as
466 "used by the linker" and I can't find any other code that
467 uses it. Should be a cleaner way of doing this (like an
468 "application flags" field in the symbol structure?). */
469 newsym->flags = BSF_LOCAL | BSF_KEEP_G;
470 newsym->section = s;
471 *output_buffer++ = newsym;
472 break;
473 }
474 }
475 }
476 for (i = 0; i < entry->symbol_count; i++)
477 {
478 asymbol *p = entry->asymbols[i];
479 /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
480
481 if (p->section == 0)
482 p->section = &bfd_abs_section;
483 if (flag_is_global (p->flags))
484 {
485 /* We are only interested in outputting
486 globals at this stage in special circumstances */
487 if (bfd_asymbol_bfd (p) == entry->the_bfd
488 && flag_is_not_at_end (p->flags))
489 {
490 /* And this is one of them */
491 *(output_buffer++) = p;
492 p->flags |= BSF_KEEP;
493 }
494 }
495 else
496 {
497 if (p->section == &bfd_ind_section)
498 {
499 /* Dont think about indirect symbols */
500 }
501 else if (flag_is_debugger (p->flags))
502 {
503 /* Only keep the debugger symbols if no stripping required */
504 if (strip_symbols == STRIP_NONE)
505 {
506 *output_buffer++ = p;
507 }
508 }
509 else if (p->section == &bfd_und_section
510 || bfd_is_com_section (p->section))
511 {
512 /* These must be global. */
513 }
514 else if (flag_is_ordinary_local (p->flags))
515 {
516 if (discard_locals == DISCARD_ALL)
517 {
518 }
519 else if (discard_locals == DISCARD_L &&
520 (p->name[0] == lprefix))
521 {
522 }
523 else if (p->flags == BSF_WARNING)
524 {
525 }
526 else
527 {
528 *output_buffer++ = p;
529 }
530 }
531 else if (p->flags & BSF_CTOR)
532 {
533 /* Throw it away */
534 }
535 else
536 {
537 FAIL ();
538 }
539 }
540 }
541
542
543 }
544 return output_buffer;
545 }
546
547
548 static asymbol **
549 write_file_globals (symbol_table)
550 asymbol **symbol_table;
551 {
552 FOR_EACH_LDSYM (sp)
553 {
554 if (sp->flags & SYM_INDIRECT)
555 {
556 asymbol *bufp = (*(sp->srefs_chain));
557 ldsym_type *aliased_to = (ldsym_type *) (sp->sdefs_chain);
558 if (aliased_to->sdefs_chain)
559 {
560 asymbol *p = aliased_to->sdefs_chain[0];
561 bufp->value = p->value;
562 bufp->section = p->section;
563 bufp->flags = p->flags;
564 }
565 else
566 {
567 bufp->value = 0;
568 bufp->flags = 0;
569 bufp->section = &bfd_und_section;
570 }
571 *symbol_table++ = bufp;
572 }
573 else if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **) NULL)
574 {
575 asymbol *bufp = (*(sp->sdefs_chain));
576
577 if ((bufp->flags & BSF_KEEP) == 0)
578 {
579 ASSERT (bufp != (asymbol *) NULL);
580
581 bufp->name = sp->name;
582
583 if (sp->scoms_chain != (asymbol **) NULL)
584
585 {
586 /*
587 defined as common but not allocated, this happens
588 only with -r and not -d, write out a common
589 definition
590 */
591 bufp = *(sp->scoms_chain);
592 }
593 *symbol_table++ = bufp;
594 }
595 }
596 else if (sp->scoms_chain != (asymbol **) NULL)
597 {
598 /* This symbol is a common - just output */
599 asymbol *bufp = (*(sp->scoms_chain));
600 *symbol_table++ = bufp;
601 }
602 else if (sp->srefs_chain != (asymbol **) NULL)
603 {
604 /* This symbol is undefined but has a reference */
605 asymbol *bufp = (*(sp->srefs_chain));
606 *symbol_table++ = bufp;
607 }
608 else
609 {
610 /*
611 This symbol has neither defs nor refs, it must have come
612 from the command line, since noone has used it it has no
613 data attatched, so we'll ignore it
614 */
615 }
616 }
617 return symbol_table;
618 }
619
620 void
621 ldsym_write ()
622 {
623 if (keepsyms_file != 0
624 && strip_symbols != STRIP_SOME)
625 {
626 info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n");
627 strip_symbols = STRIP_SOME;
628 }
629 if (strip_symbols != STRIP_ALL)
630 {
631 /* We know the maximum size of the symbol table -
632 it's the size of all the global symbols ever seen +
633 the size of all the symbols from all the files +
634 the number of files (for the per file symbols)
635 +1 (for the null at the end)
636 */
637 extern unsigned int total_files_seen;
638 extern unsigned int total_symbols_seen;
639
640 asymbol **symbol_table = (asymbol **)
641 ldmalloc ((bfd_size_type) (global_symbol_count +
642 total_files_seen +
643 total_symbols_seen + 1) * sizeof (asymbol *));
644 asymbol **tablep = write_file_locals (symbol_table);
645
646 tablep = write_file_globals (tablep);
647 tablep = process_keepsyms (symbol_table, tablep - symbol_table);
648
649 *tablep = (asymbol *) NULL;
650 bfd_set_symtab (output_bfd, symbol_table, (unsigned) (tablep - symbol_table));
651 }
652 }
653
654 /*
655 return true if the supplied symbol name is not in the
656 linker symbol table
657 */
658 boolean
659 DEFUN (ldsym_undefined, (sym),
660 CONST char *sym)
661 {
662 ldsym_type *from_table = ldsym_get_soft (sym);
663 if (from_table != (ldsym_type *) NULL)
664 {
665 if (from_table->sdefs_chain != (asymbol **) NULL)
666 return false;
667 }
668 return true;
669 }
670
671 void
672 DEFUN_VOID (ldsym_init)
673 {
674 obstack_begin (&global_sym_obstack, 20000);
675 }