Include bfd.h before sysdep.h, so ansidecl and PROTO() get defined first.
[deliverable/binutils-gdb.git] / ld / ldsym.c
1 /* Copyright (C) 1991 Free Software Foundation, Inc.
2
3 This file is part of GLD, the Gnu Linker.
4
5 GLD is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 1, or (at your option)
8 any later version.
9
10 GLD is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GLD; see the file COPYING. If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19 /*
20 * $Id$
21 *
22 *
23 */
24
25 /*
26 Written by Steve Chamberlain steve@cygnus.com
27
28 All symbol handling for the linker
29
30
31
32
33 We keep a hash table of global symbols. Each entry in a hash table
34 is called an ldsym_type. Each has three chains; a pointer to a
35 chain of definitions for the symbol (hopefully one long), a pointer
36 to a chain of references to the symbol, and a pointer to a chain of
37 common symbols. Each pointer points into the canonical symbol table
38 provided by bfd, each one of which points to an asymbol. Duringing
39 linkage, the linker uses the udata field to point to the next entry
40 in a canonical table....
41
42
43 ld_sym
44 | |
45 +----------+ +----------+
46 | defs | a canonical symbol table
47 +----------+ +----------+
48 | refs | -----> | one entry| -----> asymbol
49 +----------+ +----------+ | |
50 | coms | | | +---------+
51 +----------+ +----------+ | udata |-----> another canonical symbol
52 +---------+
53
54
55
56 It is very simple to make all the symbol pointers point to the same
57 definition - just run down the chain and make the asymbols pointers
58 within the canonical table point to the asymbol attacthed to the
59 definition of the symbol.
60
61 */
62
63 #include "bfd.h"
64 #include "sysdep.h"
65
66 #include "ld.h"
67 #include "ldsym.h"
68 #include "ldmisc.h"
69 #include "ldlang.h"
70 /* IMPORT */
71
72 extern bfd *output_bfd;
73 extern strip_symbols_type strip_symbols;
74 extern discard_locals_type discard_locals;
75 /* Head and tail of global symbol table chronological list */
76
77 ldsym_type *symbol_head = (ldsym_type *)NULL;
78 ldsym_type **symbol_tail_ptr = &symbol_head;
79
80 /*
81 incremented for each symbol in the ldsym_type table
82 no matter what flavour it is
83 */
84 unsigned int global_symbol_count;
85
86 /* IMPORTS */
87
88 extern boolean option_longmap ;
89
90 /* LOCALS */
91 #define TABSIZE 1009
92 static ldsym_type *global_symbol_hash_table[TABSIZE];
93
94 /* Compute the hash code for symbol name KEY. */
95 static
96 #ifdef __GNUC__
97 inline
98 #endif
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 *) ldmalloc ((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 = buystring(key);
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 printf ( "\nLocal symbols of ");
202 info("%I", entry);
203 printf (":\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 print_file_stuff(f)
219 lang_input_statement_type *f;
220 {
221 fprintf (stdout, " %s\n", f->filename);
222 if (f->just_syms_flag)
223 {
224 fprintf (stdout, " 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 printf (" %08x 2**%2ud %s\n",
235 (unsigned)s->size, s->alignment_power, s->name);
236 }
237 }
238 else {
239 for (s = f->the_bfd->sections;
240 s != (asection *)NULL;
241 s = s->next) {
242 printf("%s ", s->name);
243 print_address(s->output_offset);
244 printf("(%x)", (unsigned)s->size);
245 }
246 printf("hex \n");
247 }
248 }
249 fprintf (stdout, "\n");
250 }
251
252 void
253 ldsym_print_symbol_table ()
254 {
255 fprintf (stdout, "**FILES**\n\n");
256
257 lang_for_each_file(print_file_stuff);
258
259 fprintf(stdout, "**GLOBAL SYMBOLS**\n\n");
260 fprintf(stdout, "offset section offset symbol\n");
261 {
262 register ldsym_type *sp;
263
264 for (sp = symbol_head; sp; sp = sp->next)
265 {
266 if (sp->flags & SYM_INDIRECT) {
267 fprintf(stdout,"indirect %s to %s\n",
268 sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
269 }
270 else {
271 if (sp->sdefs_chain)
272 {
273 asymbol *defsym = *(sp->sdefs_chain);
274 asection *defsec = bfd_get_section(defsym);
275 print_address(defsym->value);
276 if (defsec)
277 {
278 printf(" %-10s",
279 bfd_section_name(output_bfd,
280 defsec));
281 print_space();
282 print_address(defsym->value+defsec->vma);
283
284 }
285 else
286 {
287 printf(" .......");
288 }
289
290 }
291
292
293 if (sp->scoms_chain) {
294 printf("common ");
295 print_address((*(sp->scoms_chain))->value);
296 printf(" %s ",sp->name);
297 }
298 else if (sp->sdefs_chain) {
299 printf(" %s ",sp->name);
300 }
301 else {
302 printf("undefined ");
303 printf("%s ",sp->name);
304
305 }
306 }
307 print_nl();
308
309 }
310 }
311 lang_for_each_file(list_file_locals);
312 }
313
314 extern lang_output_section_statement_type *create_object_symbols;
315 extern char lprefix;
316 static asymbol **
317 write_file_locals(output_buffer)
318 asymbol **output_buffer;
319 {
320 LANG_FOR_EACH_INPUT_STATEMENT(entry)
321 {
322 /* Run trough the symbols and work out what to do with them */
323 unsigned int i;
324
325 /* Add one for the filename symbol if needed */
326 if (create_object_symbols
327 != (lang_output_section_statement_type *)NULL) {
328 asection *s;
329 for (s = entry->the_bfd->sections;
330 s != (asection *)NULL;
331 s = s->next) {
332 if (s->output_section == create_object_symbols->bfd_section) {
333 /* Add symbol to this section */
334 asymbol * newsym =
335 (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
336 newsym->name = entry->local_sym_name;
337 /* The symbol belongs to the output file's text section */
338
339 /* The value is the start of this section in the output file*/
340 newsym->value = 0;
341 newsym->flags = BSF_LOCAL;
342 newsym->section = s;
343 *output_buffer++ = newsym;
344 break;
345 }
346 }
347 }
348 for (i = 0; i < entry->symbol_count; i++)
349 {
350 asymbol *p = entry->asymbols[i];
351
352 if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
353 {
354 /* We are only interested in outputting
355 globals at this stage in special circumstances */
356 if (p->the_bfd == entry->the_bfd
357 && flag_is_not_at_end(p->flags)) {
358 /* And this is one of them */
359 *(output_buffer++) = p;
360 p->flags |= BSF_KEEP;
361 }
362 }
363 else {
364 if (flag_is_ordinary_local(p->flags))
365 {
366 if (discard_locals == DISCARD_ALL)
367 { }
368 else if (discard_locals == DISCARD_L &&
369 (p->name[0] == lprefix))
370 { }
371 else if (p->flags == BSF_WARNING)
372 { }
373 else
374 { *output_buffer++ = p; }
375 }
376 else if (flag_is_debugger(p->flags))
377 {
378 /* Only keep the debugger symbols if no stripping required */
379 if (strip_symbols == STRIP_NONE) {
380 *output_buffer++ = p;
381 }
382 }
383 else if (flag_is_undefined(p->flags))
384 { /* This must be global */
385 }
386 else if (flag_is_common(p->flags)) {
387 /* And so must this */
388 }
389 else if (p->flags & BSF_CTOR) {
390 /* Throw it away */
391 }
392 else
393 {
394 FAIL();
395 }
396 }
397 }
398
399
400 }
401 return output_buffer;
402 }
403
404
405 static asymbol **
406 write_file_globals(symbol_table)
407 asymbol **symbol_table;
408 {
409 FOR_EACH_LDSYM(sp)
410 {
411 if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) {
412 asymbol *bufp = (*(sp->sdefs_chain));
413
414 if ((bufp->flags & BSF_KEEP) ==0) {
415 ASSERT(bufp != (asymbol *)NULL);
416
417 bufp->name = sp->name;
418
419 if (sp->scoms_chain != (asymbol **)NULL)
420
421 {
422 /*
423 defined as common but not allocated, this happens
424 only with -r and not -d, write out a common
425 definition
426 */
427 bufp = *(sp->scoms_chain);
428 }
429 *symbol_table++ = bufp;
430 }
431 }
432 else if (sp->scoms_chain != (asymbol **)NULL) {
433 /* This symbol is a common - just output */
434 asymbol *bufp = (*(sp->scoms_chain));
435 *symbol_table++ = bufp;
436 }
437 else if (sp->srefs_chain != (asymbol **)NULL) {
438 /* This symbol is undefined but has a reference */
439 asymbol *bufp = (*(sp->srefs_chain));
440 *symbol_table++ = bufp;
441 }
442 else {
443 /*
444 This symbol has neither defs nor refs, it must have come
445 from the command line, since noone has used it it has no
446 data attatched, so we'll ignore it
447 */
448 }
449 }
450 return symbol_table;
451 }
452
453
454
455 void
456 ldsym_write()
457 {
458 if (strip_symbols != STRIP_ALL) {
459 /* We know the maximum size of the symbol table -
460 it's the size of all the global symbols ever seen +
461 the size of all the symbols from all the files +
462 the number of files (for the per file symbols)
463 +1 (for the null at the end)
464 */
465 extern unsigned int total_files_seen;
466 extern unsigned int total_symbols_seen;
467
468 asymbol ** symbol_table = (asymbol **)
469 ldmalloc ((bfd_size_type)(global_symbol_count +
470 total_files_seen +
471 total_symbols_seen + 1) * sizeof (asymbol *));
472 asymbol ** tablep = write_file_locals(symbol_table);
473
474 tablep = write_file_globals(tablep);
475
476 *tablep = (asymbol *)NULL;
477 bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
478 }
479 }
480
481 /*
482 return true if the supplied symbol name is not in the
483 linker symbol table
484 */
485 boolean
486 DEFUN(ldsym_undefined,(sym),
487 CONST char *sym)
488 {
489 ldsym_type *from_table = ldsym_get_soft(sym);
490 if (from_table != (ldsym_type *)NULL) {
491 if (from_table->sdefs_chain != (asymbol **)NULL) return false;
492 }
493 return true;
494 }
This page took 0.039274 seconds and 5 git commands to generate.