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