*** empty log message ***
[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 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
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
69 extern ld_config_type config;
70
71 struct obstack global_sym_obstack;
72 #define obstack_chunk_alloc ldmalloc
73 #define obstack_chunk_free free
74
75 /*
76 incremented for each symbol in the ldsym_type table
77 no matter what flavour it is
78 */
79 unsigned int global_symbol_count;
80
81 /* IMPORTS */
82
83 extern boolean option_longmap ;
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 DEFUN(hash_string,(key),
97 CONST char *key)
98 {
99 register CONST char *cp;
100 register int k;
101
102 cp = key;
103 k = 0;
104 while (*cp)
105 k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
106
107 return k;
108 }
109
110 static
111 #ifdef __GNUC__
112 __inline
113 #endif ldsym_type *bp;
114 ldsym_type *
115 DEFUN(search,(key,hashval) ,
116 CONST char *key AND
117 int hashval)
118 {
119 ldsym_type *bp;
120 for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
121 if (! strcmp (key, bp->name)) {
122 if (bp->flags & SYM_INDIRECT) {
123 /* Use the symbol we're aliased to instead */
124 return (ldsym_type *)(bp->sdefs_chain);
125 }
126 return bp;
127 }
128 return 0;
129 }
130
131
132 /* Get the symbol table entry for the global symbol named KEY.
133 Create one if there is none. */
134 ldsym_type *
135 DEFUN(ldsym_get,(key),
136 CONST char *key)
137 {
138 register int hashval;
139 register ldsym_type *bp;
140
141 /* Determine the proper bucket. */
142
143 hashval = hash_string (key) % TABSIZE;
144
145 /* Search the bucket. */
146 bp = search(key, hashval);
147 if(bp) {
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 DEFUN(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
189
190
191
192 static void
193 list_file_locals (entry)
194 lang_input_statement_type *entry;
195 {
196 asymbol **q;
197 fprintf (config.map_file, "\nLocal symbols of ");
198 minfo("%I", entry);
199 fprintf (config.map_file, ":\n\n");
200 if (entry->asymbols) {
201 for (q = entry->asymbols; *q; q++)
202 {
203 asymbol *p = *q;
204 /* If this is a definition,
205 update it if necessary by this file's start address. */
206 if (p->flags & BSF_LOCAL)
207 info(" %V %s\n",p->value, p->name);
208 }
209 }
210 }
211
212
213 static void
214 DEFUN(print_file_stuff,(f),
215 lang_input_statement_type *f)
216 {
217 fprintf (config.map_file," %s\n", f->filename);
218 if (f->just_syms_flag)
219 {
220 fprintf (config.map_file, " symbols only\n");
221 }
222 else
223 {
224 asection *s;
225 if (true || option_longmap) {
226 for (s = f->the_bfd->sections;
227 s != (asection *)NULL;
228 s = s->next) {
229 print_address(s->output_offset);
230 if (s->reloc_done)
231 {
232 fprintf (config.map_file, " %08x 2**%2ud %s\n",
233 (unsigned)bfd_get_section_size_after_reloc(s),
234 s->alignment_power, s->name);
235 }
236
237 else
238 {
239 fprintf (config.map_file, " %08x 2**%2ud %s\n",
240 (unsigned)bfd_get_section_size_before_reloc(s),
241 s->alignment_power, s->name);
242 }
243 }
244 }
245 else
246 {
247 for (s = f->the_bfd->sections;
248 s != (asection *)NULL;
249 s = s->next) {
250 fprintf(config.map_file, "%s ", s->name);
251 print_address(s->output_offset);
252 fprintf(config.map_file, "(%x)", (unsigned)bfd_get_section_size_after_reloc(s));
253 }
254 fprintf(config.map_file, "hex \n");
255 }
256 }
257 fprintf (config.map_file, "\n");
258 }
259
260 void
261 ldsym_print_symbol_table ()
262 {
263 fprintf (config.map_file, "**FILES**\n\n");
264
265 lang_for_each_file(print_file_stuff);
266
267 fprintf(config.map_file, "**GLOBAL SYMBOLS**\n\n");
268 fprintf(config.map_file, "offset section offset symbol\n");
269 {
270 register ldsym_type *sp;
271
272 for (sp = symbol_head; sp; sp = sp->next)
273 {
274 if (sp->flags & SYM_INDIRECT) {
275 fprintf(config.map_file,"indirect %s to %s\n",
276 sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
277 }
278 else {
279 if (sp->sdefs_chain)
280 {
281 asymbol *defsym = *(sp->sdefs_chain);
282 asection *defsec = bfd_get_section(defsym);
283 print_address(defsym->value);
284 if (defsec)
285 {
286 fprintf(config.map_file, " %-10s",
287 bfd_section_name(output_bfd,
288 defsec));
289 print_space();
290 print_address(defsym->value+defsec->vma);
291
292 }
293 else
294 {
295 fprintf(config.map_file, " .......");
296 }
297
298 }
299
300
301 if (sp->scoms_chain) {
302 fprintf(config.map_file, "common ");
303 print_address((*(sp->scoms_chain))->value);
304 fprintf(config.map_file, " %s ",sp->name);
305 }
306 else if (sp->sdefs_chain) {
307 fprintf(config.map_file, " %s ",sp->name);
308 }
309 else {
310 fprintf(config.map_file, "undefined ");
311 fprintf(config.map_file, "%s ",sp->name);
312
313 }
314 }
315 print_nl();
316
317 }
318 }
319 if (option_longmap) {
320 lang_for_each_file(list_file_locals);
321 }
322 }
323
324 extern lang_output_section_statement_type *create_object_symbols;
325 extern char lprefix;
326 static asymbol **
327 write_file_locals(output_buffer)
328 asymbol **output_buffer;
329 {
330 LANG_FOR_EACH_INPUT_STATEMENT(entry)
331 {
332 /* Run trough the symbols and work out what to do with them */
333 unsigned int i;
334
335 /* Add one for the filename symbol if needed */
336 if (create_object_symbols
337 != (lang_output_section_statement_type *)NULL) {
338 asection *s;
339 for (s = entry->the_bfd->sections;
340 s != (asection *)NULL;
341 s = s->next) {
342 if (s->output_section == create_object_symbols->bfd_section) {
343 /* Add symbol to this section */
344 asymbol * newsym =
345 (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
346 newsym->name = entry->local_sym_name;
347 /* The symbol belongs to the output file's text section */
348
349 /* The value is the start of this section in the output file*/
350 newsym->value = 0;
351 newsym->flags = BSF_LOCAL;
352 newsym->section = s;
353 *output_buffer++ = newsym;
354 break;
355 }
356 }
357 }
358 for (i = 0; i < entry->symbol_count; i++)
359 {
360 asymbol *p = entry->asymbols[i];
361 /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
362
363 if (p->section == 0)
364 p->section = &bfd_abs_section;
365 if (flag_is_global(p->flags) )
366 {
367 /* We are only interested in outputting
368 globals at this stage in special circumstances */
369 if (p->the_bfd == entry->the_bfd
370 && flag_is_not_at_end(p->flags)) {
371 /* And this is one of them */
372 *(output_buffer++) = p;
373 p->flags |= BSF_KEEP;
374 }
375 }
376 else {
377 if (flag_is_debugger(p->flags))
378 {
379 /* Only keep the debugger symbols if no stripping required */
380 if (strip_symbols == STRIP_NONE) {
381 *output_buffer++ = p;
382 }
383 }
384 else if (p->section == &bfd_und_section
385 || p->section == &bfd_com_section)
386 {
387 /* These must be global. */
388 }
389 else if (flag_is_ordinary_local(p->flags))
390 {
391 if (discard_locals == DISCARD_ALL)
392 { }
393 else if (discard_locals == DISCARD_L &&
394 (p->name[0] == lprefix))
395 { }
396 else if (p->flags == BSF_WARNING)
397 { }
398 else
399 { *output_buffer++ = p; }
400 }
401 else if (p->flags & BSF_CTOR) {
402 /* Throw it away */
403 }
404 else
405 {
406 FAIL();
407 }
408 }
409 }
410
411
412 }
413 return output_buffer;
414 }
415
416
417 static asymbol **
418 write_file_globals(symbol_table)
419 asymbol **symbol_table;
420 {
421 FOR_EACH_LDSYM(sp)
422 {
423 if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) {
424 asymbol *bufp = (*(sp->sdefs_chain));
425
426 if ((bufp->flags & BSF_KEEP) ==0) {
427 ASSERT(bufp != (asymbol *)NULL);
428
429 bufp->name = sp->name;
430
431 if (sp->scoms_chain != (asymbol **)NULL)
432
433 {
434 /*
435 defined as common but not allocated, this happens
436 only with -r and not -d, write out a common
437 definition
438 */
439 bufp = *(sp->scoms_chain);
440 }
441 *symbol_table++ = bufp;
442 }
443 }
444 else if (sp->scoms_chain != (asymbol **)NULL) {
445 /* This symbol is a common - just output */
446 asymbol *bufp = (*(sp->scoms_chain));
447 *symbol_table++ = bufp;
448 }
449 else if (sp->srefs_chain != (asymbol **)NULL) {
450 /* This symbol is undefined but has a reference */
451 asymbol *bufp = (*(sp->srefs_chain));
452 *symbol_table++ = bufp;
453 }
454 else {
455 /*
456 This symbol has neither defs nor refs, it must have come
457 from the command line, since noone has used it it has no
458 data attatched, so we'll ignore it
459 */
460 }
461 }
462 return symbol_table;
463 }
464
465
466
467 void
468 ldsym_write()
469 {
470 if (strip_symbols != STRIP_ALL) {
471 /* We know the maximum size of the symbol table -
472 it's the size of all the global symbols ever seen +
473 the size of all the symbols from all the files +
474 the number of files (for the per file symbols)
475 +1 (for the null at the end)
476 */
477 extern unsigned int total_files_seen;
478 extern unsigned int total_symbols_seen;
479
480 asymbol ** symbol_table = (asymbol **)
481 ldmalloc ((bfd_size_type)(global_symbol_count +
482 total_files_seen +
483 total_symbols_seen + 1) * sizeof (asymbol *));
484 asymbol ** tablep = write_file_locals(symbol_table);
485
486 tablep = write_file_globals(tablep);
487
488 *tablep = (asymbol *)NULL;
489 bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
490 }
491 }
492
493 /*
494 return true if the supplied symbol name is not in the
495 linker symbol table
496 */
497 boolean
498 DEFUN(ldsym_undefined,(sym),
499 CONST char *sym)
500 {
501 ldsym_type *from_table = ldsym_get_soft(sym);
502 if (from_table != (ldsym_type *)NULL)
503 {
504 if (from_table->sdefs_chain != (asymbol **)NULL) return false;
505 }
506 return true;
507 }
508
509 void
510 DEFUN_VOID(ldsym_init)
511 {
512 obstack_begin(&global_sym_obstack, 20000);
513 }
This page took 0.05612 seconds and 4 git commands to generate.