* ldver.c: Increase version number to 1.97, for consistency with ../binutils.
[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 * $Id$
23 */
24
25 /*
26 We keep a hash table of global symbols. Each entry in a hash table
27 is called an ldsym_type. Each has three chains; a pointer to a
28 chain of definitions for the symbol (hopefully one long), a pointer
29 to a chain of references to the symbol, and a pointer to a chain of
30 common symbols. Each pointer points into the canonical symbol table
31 provided by bfd, each one of which points to an asymbol. Duringing
32 linkage, the linker uses the udata field to point to the next entry
33 in a canonical table....
34
35
36 ld_sym
37 | |
38 +----------+ +----------+
39 | defs | a canonical symbol table
40 +----------+ +----------+
41 | refs | -----> | one entry| -----> asymbol
42 +----------+ +----------+ | |
43 | coms | | | +---------+
44 +----------+ +----------+ | udata |-----> another canonical symbol
45 +---------+
46
47
48
49 It is very simple to make all the symbol pointers point to the same
50 definition - just run down the chain and make the asymbols pointers
51 within the canonical table point to the asymbol attacthed to the
52 definition of the symbol.
53
54 */
55
56 #include "bfd.h"
57 #include "sysdep.h"
58
59 #include "ld.h"
60 #include "ldsym.h"
61 #include "ldmisc.h"
62 #include "ldlang.h"
63 /* IMPORT */
64
65 extern bfd *output_bfd;
66 extern strip_symbols_type strip_symbols;
67 extern discard_locals_type discard_locals;
68 /* Head and tail of global symbol table chronological list */
69
70 ldsym_type *symbol_head = (ldsym_type *)NULL;
71 ldsym_type **symbol_tail_ptr = &symbol_head;
72
73 extern ld_config_type config;
74
75 struct obstack global_sym_obstack;
76 #define obstack_chunk_alloc ldmalloc
77 #define obstack_chunk_free free
78
79 /*
80 incremented for each symbol in the ldsym_type table
81 no matter what flavour it is
82 */
83 unsigned int global_symbol_count;
84
85 /* IMPORTS */
86
87 extern boolean option_longmap ;
88
89 /* LOCALS */
90 #define TABSIZE 1009
91 static ldsym_type *global_symbol_hash_table[TABSIZE];
92
93 /* Compute the hash code for symbol name KEY. */
94 static
95 #ifdef __GNUC__
96 __inline
97 #endif
98
99 int
100 DEFUN(hash_string,(key),
101 CONST char *key)
102 {
103 register CONST char *cp;
104 register int k;
105
106 cp = key;
107 k = 0;
108 while (*cp)
109 k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
110
111 return k;
112 }
113
114 static
115 #ifdef __GNUC__
116 __inline
117 #endif ldsym_type *bp;
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 (! strcmp (key, bp->name)) {
126 if (bp->flags & SYM_INDIRECT) {
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 DEFUN(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 return bp;
153 }
154
155 /* Nothing was found; create a new symbol table entry. */
156
157 bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type)(sizeof (ldsym_type)));
158 bp->srefs_chain = (asymbol **)NULL;
159 bp->sdefs_chain = (asymbol **)NULL;
160 bp->scoms_chain = (asymbol **)NULL;
161 bp->name = obstack_copy(&global_sym_obstack, key, strlen(key)+1);
162 bp->flags = 0;
163 /* Add the entry to the bucket. */
164
165 bp->link = global_symbol_hash_table[hashval];
166 global_symbol_hash_table[hashval] = bp;
167
168 /* Keep the chronological list up to date too */
169 *symbol_tail_ptr = bp;
170 symbol_tail_ptr = &bp->next;
171 bp->next = 0;
172 global_symbol_count++;
173
174 return bp;
175 }
176
177 /* Like `ldsym_get' but return 0 if the symbol is not already known. */
178
179 ldsym_type *
180 DEFUN(ldsym_get_soft,(key),
181 CONST char *key)
182 {
183 register int hashval;
184 /* Determine which bucket. */
185
186 hashval = hash_string (key) % TABSIZE;
187
188 /* Search the bucket. */
189 return search(key, hashval);
190 }
191
192
193
194
195
196 static void
197 list_file_locals (entry)
198 lang_input_statement_type *entry;
199 {
200 asymbol **q;
201 fprintf (config.map_file, "\nLocal symbols of ");
202 minfo("%I", entry);
203 fprintf (config.map_file, ":\n\n");
204 if (entry->asymbols) {
205 for (q = entry->asymbols; *q; q++)
206 {
207 asymbol *p = *q;
208 /* If this is a definition,
209 update it if necessary by this file's start address. */
210 if (p->flags & BSF_LOCAL)
211 info(" %V %s\n",p->value, p->name);
212 }
213 }
214 }
215
216
217 static void
218 DEFUN(print_file_stuff,(f),
219 lang_input_statement_type *f)
220 {
221 fprintf (config.map_file," %s\n", f->filename);
222 if (f->just_syms_flag)
223 {
224 fprintf (config.map_file, " symbols only\n");
225 }
226 else
227 {
228 asection *s;
229 if (true || option_longmap) {
230 for (s = f->the_bfd->sections;
231 s != (asection *)NULL;
232 s = s->next) {
233 print_address(s->output_offset);
234 if (s->reloc_done)
235 {
236 fprintf (config.map_file, " %08x 2**%2ud %s\n",
237 (unsigned)bfd_get_section_size_after_reloc(s),
238 s->alignment_power, s->name);
239 }
240
241 else
242 {
243 fprintf (config.map_file, " %08x 2**%2ud %s\n",
244 (unsigned)bfd_get_section_size_before_reloc(s),
245 s->alignment_power, s->name);
246 }
247 }
248 }
249 else
250 {
251 for (s = f->the_bfd->sections;
252 s != (asection *)NULL;
253 s = s->next) {
254 fprintf(config.map_file, "%s ", s->name);
255 print_address(s->output_offset);
256 fprintf(config.map_file, "(%x)", (unsigned)bfd_get_section_size_after_reloc(s));
257 }
258 fprintf(config.map_file, "hex \n");
259 }
260 }
261 fprintf (config.map_file, "\n");
262 }
263
264 void
265 ldsym_print_symbol_table ()
266 {
267 fprintf (config.map_file, "**FILES**\n\n");
268
269 lang_for_each_file(print_file_stuff);
270
271 fprintf(config.map_file, "**GLOBAL SYMBOLS**\n\n");
272 fprintf(config.map_file, "offset section offset symbol\n");
273 {
274 register ldsym_type *sp;
275
276 for (sp = symbol_head; sp; sp = sp->next)
277 {
278 if (sp->flags & SYM_INDIRECT) {
279 fprintf(config.map_file,"indirect %s to %s\n",
280 sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
281 }
282 else {
283 if (sp->sdefs_chain)
284 {
285 asymbol *defsym = *(sp->sdefs_chain);
286 asection *defsec = bfd_get_section(defsym);
287 print_address(defsym->value);
288 if (defsec)
289 {
290 fprintf(config.map_file, " %-10s",
291 bfd_section_name(output_bfd,
292 defsec));
293 print_space();
294 print_address(defsym->value+defsec->vma);
295
296 }
297 else
298 {
299 fprintf(config.map_file, " .......");
300 }
301
302 }
303
304
305 if (sp->scoms_chain) {
306 fprintf(config.map_file, "common ");
307 print_address((*(sp->scoms_chain))->value);
308 fprintf(config.map_file, " %s ",sp->name);
309 }
310 else if (sp->sdefs_chain) {
311 fprintf(config.map_file, " %s ",sp->name);
312 }
313 else {
314 fprintf(config.map_file, "undefined ");
315 fprintf(config.map_file, "%s ",sp->name);
316
317 }
318 }
319 print_nl();
320
321 }
322 }
323 if (option_longmap) {
324 lang_for_each_file(list_file_locals);
325 }
326 }
327
328 extern lang_output_section_statement_type *create_object_symbols;
329 extern char lprefix;
330 static asymbol **
331 write_file_locals(output_buffer)
332 asymbol **output_buffer;
333 {
334 LANG_FOR_EACH_INPUT_STATEMENT(entry)
335 {
336 /* Run trough the symbols and work out what to do with them */
337 unsigned int i;
338
339 /* Add one for the filename symbol if needed */
340 if (create_object_symbols
341 != (lang_output_section_statement_type *)NULL) {
342 asection *s;
343 for (s = entry->the_bfd->sections;
344 s != (asection *)NULL;
345 s = s->next) {
346 if (s->output_section == create_object_symbols->bfd_section) {
347 /* Add symbol to this section */
348 asymbol * newsym =
349 (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
350 newsym->name = entry->local_sym_name;
351 /* The symbol belongs to the output file's text section */
352
353 /* The value is the start of this section in the output file*/
354 newsym->value = 0;
355 newsym->flags = BSF_LOCAL;
356 newsym->section = s;
357 *output_buffer++ = newsym;
358 break;
359 }
360 }
361 }
362 for (i = 0; i < entry->symbol_count; i++)
363 {
364 asymbol *p = entry->asymbols[i];
365 /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
366
367 if (p->section == 0)
368 p->section = &bfd_abs_section;
369 if (flag_is_global(p->flags) )
370 {
371 /* We are only interested in outputting
372 globals at this stage in special circumstances */
373 if (p->the_bfd == entry->the_bfd
374 && flag_is_not_at_end(p->flags)) {
375 /* And this is one of them */
376 *(output_buffer++) = p;
377 p->flags |= BSF_KEEP;
378 }
379 }
380 else {
381 if (flag_is_ordinary_local(p->flags))
382 {
383 if (discard_locals == DISCARD_ALL)
384 { }
385 else if (discard_locals == DISCARD_L &&
386 (p->name[0] == lprefix))
387 { }
388 else if (p->flags == BSF_WARNING)
389 { }
390 else
391 { *output_buffer++ = p; }
392 }
393 else if (flag_is_debugger(p->flags))
394 {
395 /* Only keep the debugger symbols if no stripping required */
396 if (strip_symbols == STRIP_NONE) {
397 *output_buffer++ = p;
398 }
399 }
400 else if (p->section == &bfd_und_section)
401 { /* This must be global */
402 }
403 else if (p->section == &bfd_com_section) {
404 /* And so must this */
405 }
406 else if (p->flags & BSF_CTOR) {
407 /* Throw it away */
408 }
409 else
410 {
411 FAIL();
412 }
413 }
414 }
415
416
417 }
418 return output_buffer;
419 }
420
421
422 static asymbol **
423 write_file_globals(symbol_table)
424 asymbol **symbol_table;
425 {
426 FOR_EACH_LDSYM(sp)
427 {
428 if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) {
429 asymbol *bufp = (*(sp->sdefs_chain));
430
431 if ((bufp->flags & BSF_KEEP) ==0) {
432 ASSERT(bufp != (asymbol *)NULL);
433
434 bufp->name = sp->name;
435
436 if (sp->scoms_chain != (asymbol **)NULL)
437
438 {
439 /*
440 defined as common but not allocated, this happens
441 only with -r and not -d, write out a common
442 definition
443 */
444 bufp = *(sp->scoms_chain);
445 }
446 *symbol_table++ = bufp;
447 }
448 }
449 else if (sp->scoms_chain != (asymbol **)NULL) {
450 /* This symbol is a common - just output */
451 asymbol *bufp = (*(sp->scoms_chain));
452 *symbol_table++ = bufp;
453 }
454 else if (sp->srefs_chain != (asymbol **)NULL) {
455 /* This symbol is undefined but has a reference */
456 asymbol *bufp = (*(sp->srefs_chain));
457 *symbol_table++ = bufp;
458 }
459 else {
460 /*
461 This symbol has neither defs nor refs, it must have come
462 from the command line, since noone has used it it has no
463 data attatched, so we'll ignore it
464 */
465 }
466 }
467 return symbol_table;
468 }
469
470
471
472 void
473 ldsym_write()
474 {
475 if (strip_symbols != STRIP_ALL) {
476 /* We know the maximum size of the symbol table -
477 it's the size of all the global symbols ever seen +
478 the size of all the symbols from all the files +
479 the number of files (for the per file symbols)
480 +1 (for the null at the end)
481 */
482 extern unsigned int total_files_seen;
483 extern unsigned int total_symbols_seen;
484
485 asymbol ** symbol_table = (asymbol **)
486 ldmalloc ((bfd_size_type)(global_symbol_count +
487 total_files_seen +
488 total_symbols_seen + 1) * sizeof (asymbol *));
489 asymbol ** tablep = write_file_locals(symbol_table);
490
491 tablep = write_file_globals(tablep);
492
493 *tablep = (asymbol *)NULL;
494 bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
495 }
496 }
497
498 /*
499 return true if the supplied symbol name is not in the
500 linker symbol table
501 */
502 boolean
503 DEFUN(ldsym_undefined,(sym),
504 CONST char *sym)
505 {
506 ldsym_type *from_table = ldsym_get_soft(sym);
507 if (from_table != (ldsym_type *)NULL)
508 {
509 if (from_table->sdefs_chain != (asymbol **)NULL) return false;
510 }
511 return true;
512 }
513
514 void
515 DEFUN_VOID(ldsym_init)
516 {
517 obstack_begin(&global_sym_obstack, 20000);
518 }
This page took 0.039527 seconds and 4 git commands to generate.