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