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