]> Git Repo - binutils.git/blob - ld/ldsym.c
* ldver.c: Bumped version to 1.96 - new release, resync with the
[binutils.git] / ld / ldsym.c
1 /* All symbol handling for the linker
2    Copyright (C) 1991 Free Software Foundation, Inc.
3    Written by Steve Chamberlain [email protected]
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.053418 seconds and 4 git commands to generate.