Mon Oct 5 14:07:37 1992 Ian Lance Taylor (ian@cygnus.com)
[deliverable/binutils-gdb.git] / ld / ldsym.c
CommitLineData
2d1a2445
PB
1/* All symbol handling for the linker
2 Copyright (C) 1991 Free Software Foundation, Inc.
3 Written by Steve Chamberlain steve@cygnus.com
4
2fa0b342
DHW
5This file is part of GLD, the Gnu Linker.
6
2d1a2445 7This program is free software; you can redistribute it and/or modify
2fa0b342 8it under the terms of the GNU General Public License as published by
2d1a2445
PB
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
2fa0b342 11
2d1a2445 12This program is distributed in the hope that it will be useful,
2fa0b342
DHW
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
2d1a2445
PB
18along with this program; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
2fa0b342 20
2fa0b342 21/*
1af27af8
SC
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
32846f9c 27 provided by bfd, each one of which points to an asymbol. During
1af27af8
SC
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
2fa0b342 52#include "bfd.h"
f177a611 53#include "sysdep.h"
2fa0b342
DHW
54
55#include "ld.h"
56#include "ldsym.h"
57#include "ldmisc.h"
58#include "ldlang.h"
59/* IMPORT */
60
61extern bfd *output_bfd;
d646b568
SC
62extern strip_symbols_type strip_symbols;
63extern discard_locals_type discard_locals;
2fa0b342
DHW
64/* Head and tail of global symbol table chronological list */
65
66ldsym_type *symbol_head = (ldsym_type *)NULL;
67ldsym_type **symbol_tail_ptr = &symbol_head;
f3b36ecb
KR
68CONST char *keepsyms_file;
69int kept_syms;
2fa0b342 70
6fd50a20
SC
71extern ld_config_type config;
72
bfbdc80f
SC
73struct obstack global_sym_obstack;
74#define obstack_chunk_alloc ldmalloc
75#define obstack_chunk_free free
76
2fa0b342
DHW
77/*
78 incremented for each symbol in the ldsym_type table
79 no matter what flavour it is
80*/
81unsigned int global_symbol_count;
82
83/* IMPORTS */
84
85extern boolean option_longmap ;
86
87/* LOCALS */
88#define TABSIZE 1009
89static ldsym_type *global_symbol_hash_table[TABSIZE];
90
91/* Compute the hash code for symbol name KEY. */
1af27af8
SC
92static
93#ifdef __GNUC__
b773e0e5 94__inline
1af27af8 95#endif
b773e0e5 96
2fa0b342 97int
1af27af8
SC
98DEFUN(hash_string,(key),
99 CONST char *key)
2fa0b342 100{
1af27af8 101 register CONST char *cp;
2fa0b342
DHW
102 register int k;
103
104 cp = key;
105 k = 0;
106 while (*cp)
107 k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
108
109 return k;
110}
111
1af27af8
SC
112static
113#ifdef __GNUC__
b773e0e5 114__inline
1af27af8
SC
115#endif ldsym_type *bp;
116ldsym_type *
117DEFUN(search,(key,hashval) ,
118 CONST char *key AND
119 int hashval)
120{
121 ldsym_type *bp;
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);
127 }
128 return bp;
129 }
130 return 0;
131}
132
133
2fa0b342
DHW
134/* Get the symbol table entry for the global symbol named KEY.
135 Create one if there is none. */
136ldsym_type *
99fe4553
SC
137DEFUN(ldsym_get,(key),
138 CONST char *key)
2fa0b342
DHW
139{
140 register int hashval;
141 register ldsym_type *bp;
142
143 /* Determine the proper bucket. */
144
145 hashval = hash_string (key) % TABSIZE;
146
147 /* Search the bucket. */
1af27af8
SC
148 bp = search(key, hashval);
149 if(bp) {
150 return bp;
151 }
2fa0b342
DHW
152
153 /* Nothing was found; create a new symbol table entry. */
154
bfbdc80f 155 bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type)(sizeof (ldsym_type)));
2fa0b342
DHW
156 bp->srefs_chain = (asymbol **)NULL;
157 bp->sdefs_chain = (asymbol **)NULL;
158 bp->scoms_chain = (asymbol **)NULL;
bfbdc80f 159 bp->name = obstack_copy(&global_sym_obstack, key, strlen(key)+1);
81016051 160 bp->flags = 0;
2fa0b342
DHW
161 /* Add the entry to the bucket. */
162
163 bp->link = global_symbol_hash_table[hashval];
164 global_symbol_hash_table[hashval] = bp;
165
166 /* Keep the chronological list up to date too */
167 *symbol_tail_ptr = bp;
168 symbol_tail_ptr = &bp->next;
169 bp->next = 0;
170 global_symbol_count++;
171
172 return bp;
173}
174
175/* Like `ldsym_get' but return 0 if the symbol is not already known. */
176
177ldsym_type *
99fe4553
SC
178DEFUN(ldsym_get_soft,(key),
179 CONST char *key)
2fa0b342
DHW
180{
181 register int hashval;
2fa0b342
DHW
182 /* Determine which bucket. */
183
184 hashval = hash_string (key) % TABSIZE;
185
186 /* Search the bucket. */
7fe11a82 187 return search(key, hashval);
2fa0b342
DHW
188}
189
f3b36ecb
KR
190static asymbol **
191process_keepsyms (table, size)
192 asymbol ** table;
193 int size;
194{
195 struct obstack obstack;
196 char *start_of_obstack;
197 FILE *ks_file = 0;
198 asymbol **out = table;
199 asymbol **end = table + size;
200 asymbol **sym;
201
202 if (!keepsyms_file || size == 0)
203 return end;
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");
209 if (!ks_file)
210 {
211 info ("%X%P: can't open keep-symbols file `%s'\n", keepsyms_file);
212 goto egress;
213 }
214 errno = 0;
2fa0b342 215
f3b36ecb
KR
216#define KEEP(S) \
217 do { asymbol **p=(S), *tmp=*out; *out=*p; *p=tmp; out++; } while (0)
2fa0b342 218
f3b36ecb
KR
219 while (!feof (ks_file) && !ferror (ks_file))
220 {
221 int c;
222 char *ptr;
223 int found = 0;
2fa0b342 224
f3b36ecb
KR
225 obstack_free (&obstack, start_of_obstack);
226 do
227 {
228 c = getc (ks_file);
229 if (c == '\n')
230 c = 0;
231 obstack_1grow (&obstack, c);
232 }
233 while (c > 0);
234 if (c == EOF)
235 {
236 if (!feof (ks_file))
237 /* error occurred */
238 {
239 info ("%X%P: error reading keep-symbols file `%s': %E\n",
240 keepsyms_file);
241 out = end;
242 goto egress;
243 }
244 if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1)
245 /* eof in middle of symbol */
246 {
247 info ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n",
248 keepsyms_file);
249 out = end;
250 goto egress;
251 }
252 /* All okay -- no incomplete lines, EOF reached. */
253 break;
254 }
255 ptr = obstack_next_free (&obstack) - 2;
256 /* discard trailing trash */
257 while (*ptr == ' '
258 || *ptr == '\t')
259 *ptr-- = 0;
260 ptr = obstack_base (&obstack);
261 for (sym = out; sym < end; sym++)
262 if (!strcmp ((*sym)->name, ptr))
263 {
264 KEEP (sym);
265 found = 1;
266 }
267 if (!found)
268 info ("%P: symbol `%s' (requested to be kept) not found\n", ptr);
269 }
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++)
274 {
275 asymbol *s = *sym;
276 if (s->section == &bfd_und_section
277 || s->section == &bfd_com_section
278 || s->flags & BSF_KEEP_G)
279 KEEP (sym);
280 }
281 egress:
282 obstack_free (&obstack, start_of_obstack);
283 if (ks_file)
284 fclose (ks_file);
285 return out;
286}
2fa0b342
DHW
287
288static void
289list_file_locals (entry)
290lang_input_statement_type *entry;
291{
292 asymbol **q;
6fd50a20
SC
293 fprintf (config.map_file, "\nLocal symbols of ");
294 minfo("%I", entry);
295 fprintf (config.map_file, ":\n\n");
2fa0b342
DHW
296 if (entry->asymbols) {
297 for (q = entry->asymbols; *q; q++)
298 {
299 asymbol *p = *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);
304 }
305 }
306}
307
308
309static void
6fd50a20
SC
310DEFUN(print_file_stuff,(f),
311 lang_input_statement_type *f)
2fa0b342 312{
6fd50a20 313 fprintf (config.map_file," %s\n", f->filename);
2fa0b342 314 if (f->just_syms_flag)
c611e285 315 {
6fd50a20 316 fprintf (config.map_file, " symbols only\n");
c611e285 317 }
2fa0b342 318 else
c611e285
SC
319 {
320 asection *s;
321 if (true || option_longmap) {
bfbdc80f
SC
322 for (s = f->the_bfd->sections;
323 s != (asection *)NULL;
324 s = s->next) {
325 print_address(s->output_offset);
326 if (s->reloc_done)
327 {
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);
331 }
c611e285 332
bfbdc80f
SC
333 else
334 {
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);
338 }
c611e285 339 }
bfbdc80f
SC
340 }
341 else
342 {
343 for (s = f->the_bfd->sections;
344 s != (asection *)NULL;
345 s = s->next) {
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));
2fa0b342 349 }
bfbdc80f
SC
350 fprintf(config.map_file, "hex \n");
351 }
c611e285 352 }
6fd50a20 353 fprintf (config.map_file, "\n");
2fa0b342
DHW
354}
355
356void
357ldsym_print_symbol_table ()
358{
6fd50a20 359 fprintf (config.map_file, "**FILES**\n\n");
2fa0b342
DHW
360
361 lang_for_each_file(print_file_stuff);
362
6fd50a20
SC
363 fprintf(config.map_file, "**GLOBAL SYMBOLS**\n\n");
364 fprintf(config.map_file, "offset section offset symbol\n");
2fa0b342
DHW
365 {
366 register ldsym_type *sp;
367
368 for (sp = symbol_head; sp; sp = sp->next)
369 {
1af27af8 370 if (sp->flags & SYM_INDIRECT) {
6fd50a20 371 fprintf(config.map_file,"indirect %s to %s\n",
1af27af8 372 sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
2fa0b342
DHW
373 }
374 else {
d9c53949
SC
375 if (sp->sdefs_chain)
376 {
377 asymbol *defsym = *(sp->sdefs_chain);
378 asection *defsec = bfd_get_section(defsym);
379 print_address(defsym->value);
380 if (defsec)
381 {
6fd50a20 382 fprintf(config.map_file, " %-10s",
d9c53949
SC
383 bfd_section_name(output_bfd,
384 defsec));
385 print_space();
386 print_address(defsym->value+defsec->vma);
387
388 }
389 else
390 {
6fd50a20 391 fprintf(config.map_file, " .......");
d9c53949
SC
392 }
393
394 }
395
396
397 if (sp->scoms_chain) {
6fd50a20 398 fprintf(config.map_file, "common ");
d9c53949 399 print_address((*(sp->scoms_chain))->value);
6fd50a20 400 fprintf(config.map_file, " %s ",sp->name);
d9c53949
SC
401 }
402 else if (sp->sdefs_chain) {
6fd50a20 403 fprintf(config.map_file, " %s ",sp->name);
d9c53949
SC
404 }
405 else {
6fd50a20
SC
406 fprintf(config.map_file, "undefined ");
407 fprintf(config.map_file, "%s ",sp->name);
1af27af8 408
d9c53949 409 }
2fa0b342 410 }
19b03b7a 411 print_nl();
2fa0b342
DHW
412
413 }
414 }
d9c53949
SC
415 if (option_longmap) {
416 lang_for_each_file(list_file_locals);
417 }
2fa0b342
DHW
418}
419
420extern lang_output_section_statement_type *create_object_symbols;
421extern char lprefix;
422static asymbol **
423write_file_locals(output_buffer)
424asymbol **output_buffer;
425{
bfbdc80f
SC
426 LANG_FOR_EACH_INPUT_STATEMENT(entry)
427 {
428 /* Run trough the symbols and work out what to do with them */
429 unsigned int i;
430
431 /* Add one for the filename symbol if needed */
432 if (create_object_symbols
433 != (lang_output_section_statement_type *)NULL) {
434 asection *s;
435 for (s = entry->the_bfd->sections;
436 s != (asection *)NULL;
437 s = s->next) {
438 if (s->output_section == create_object_symbols->bfd_section) {
439 /* Add symbol to this section */
440 asymbol * newsym =
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 */
444
445 /* The value is the start of this section in the output file*/
446 newsym->value = 0;
f3b36ecb
KR
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;
bfbdc80f
SC
452 newsym->section = s;
453 *output_buffer++ = newsym;
454 break;
455 }
456 }
457 }
458 for (i = 0; i < entry->symbol_count; i++)
2fa0b342 459 {
bfbdc80f
SC
460 asymbol *p = entry->asymbols[i];
461 /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
462
463 if (p->section == 0)
464 p->section = &bfd_abs_section;
465 if (flag_is_global(p->flags) )
466 {
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;
2fa0b342
DHW
474 }
475 }
bfbdc80f 476 else {
571c4c26
KR
477 if (flag_is_debugger(p->flags))
478 {
479 /* Only keep the debugger symbols if no stripping required */
480 if (strip_symbols == STRIP_NONE) {
481 *output_buffer++ = p;
482 }
483 }
484 else if (p->section == &bfd_und_section
485 || p->section == &bfd_com_section)
486 {
487 /* These must be global. */
488 }
489 else if (flag_is_ordinary_local(p->flags))
2fa0b342 490 {
bfbdc80f
SC
491 if (discard_locals == DISCARD_ALL)
492 { }
493 else if (discard_locals == DISCARD_L &&
494 (p->name[0] == lprefix))
495 { }
496 else if (p->flags == BSF_WARNING)
497 { }
498 else
499 { *output_buffer++ = p; }
500 }
bfbdc80f
SC
501 else if (p->flags & BSF_CTOR) {
502 /* Throw it away */
503 }
504 else
505 {
506 FAIL();
507 }
508 }
509 }
2fa0b342
DHW
510
511
bfbdc80f 512 }
2fa0b342
DHW
513 return output_buffer;
514}
515
516
517static asymbol **
518write_file_globals(symbol_table)
519asymbol **symbol_table;
520{
521 FOR_EACH_LDSYM(sp)
522 {
1af27af8 523 if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) {
2fa0b342
DHW
524 asymbol *bufp = (*(sp->sdefs_chain));
525
526 if ((bufp->flags & BSF_KEEP) ==0) {
527 ASSERT(bufp != (asymbol *)NULL);
528
529 bufp->name = sp->name;
530
531 if (sp->scoms_chain != (asymbol **)NULL)
532
533 {
534 /*
535 defined as common but not allocated, this happens
536 only with -r and not -d, write out a common
537 definition
538 */
539 bufp = *(sp->scoms_chain);
540 }
541 *symbol_table++ = bufp;
542 }
543 }
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;
548 }
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;
553 }
554 else {
555 /*
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
559 */
560 }
561 }
562 return symbol_table;
563}
564
2fa0b342
DHW
565void
566ldsym_write()
567{
f3b36ecb
KR
568 if (keepsyms_file != 0
569 && strip_symbols != STRIP_SOME)
570 {
571 info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n");
572 strip_symbols = STRIP_SOME;
573 }
2fa0b342
DHW
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)
580 */
581 extern unsigned int total_files_seen;
582 extern unsigned int total_symbols_seen;
583
584 asymbol ** symbol_table = (asymbol **)
19b03b7a 585 ldmalloc ((bfd_size_type)(global_symbol_count +
2fa0b342
DHW
586 total_files_seen +
587 total_symbols_seen + 1) * sizeof (asymbol *));
588 asymbol ** tablep = write_file_locals(symbol_table);
589
590 tablep = write_file_globals(tablep);
f3b36ecb 591 tablep = process_keepsyms (symbol_table, tablep - symbol_table);
2fa0b342
DHW
592
593 *tablep = (asymbol *)NULL;
594 bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
595 }
596}
c660714f
SC
597
598/*
599return true if the supplied symbol name is not in the
600linker symbol table
601*/
602boolean
99fe4553
SC
603DEFUN(ldsym_undefined,(sym),
604 CONST char *sym)
c660714f
SC
605{
606 ldsym_type *from_table = ldsym_get_soft(sym);
bfbdc80f
SC
607 if (from_table != (ldsym_type *)NULL)
608 {
c660714f
SC
609 if (from_table->sdefs_chain != (asymbol **)NULL) return false;
610 }
611 return true;
612}
bfbdc80f
SC
613
614void
615DEFUN_VOID(ldsym_init)
616{
617 obstack_begin(&global_sym_obstack, 20000);
618}
This page took 0.082658 seconds and 4 git commands to generate.