]> Git Repo - binutils.git/blob - ld/ldsym.c
.Sanitize: added relax.c
[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 /*
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 *) ldmalloc ((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 = buystring(key);
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->flags & SEC_HAS_CONTENTS) 
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               
246           }
247       }
248     else {            
249         for (s = f->the_bfd->sections;
250              s != (asection *)NULL;
251              s = s->next) {
252             fprintf(config.map_file, "%s ", s->name);
253             print_address(s->output_offset);
254             fprintf(config.map_file, "(%x)", (unsigned)bfd_get_section_size_after_reloc(s));
255           }
256         fprintf(config.map_file, "hex \n");
257       }
258   }
259   fprintf (config.map_file, "\n");
260 }
261
262 void
263 ldsym_print_symbol_table ()
264 {
265   fprintf (config.map_file, "**FILES**\n\n");
266
267   lang_for_each_file(print_file_stuff);
268
269   fprintf(config.map_file, "**GLOBAL SYMBOLS**\n\n");
270   fprintf(config.map_file, "offset    section    offset   symbol\n");
271   {
272     register ldsym_type *sp;
273
274     for (sp = symbol_head; sp; sp = sp->next)
275       {
276         if (sp->flags & SYM_INDIRECT) {
277           fprintf(config.map_file,"indirect %s to %s\n",
278                   sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
279         }
280         else {
281           if (sp->sdefs_chain) 
282             {
283               asymbol *defsym = *(sp->sdefs_chain);
284               asection *defsec = bfd_get_section(defsym);
285               print_address(defsym->value);
286               if (defsec)
287                 {
288                   fprintf(config.map_file, "  %-10s",
289                          bfd_section_name(output_bfd,
290                                           defsec));
291                   print_space();
292                   print_address(defsym->value+defsec->vma);
293
294                 }
295               else 
296                 {
297                   fprintf(config.map_file, "         .......");
298                 }
299
300             }   
301
302
303           if (sp->scoms_chain) {
304             fprintf(config.map_file, "common               ");
305             print_address((*(sp->scoms_chain))->value);
306             fprintf(config.map_file, " %s ",sp->name);
307           }
308           else if (sp->sdefs_chain) {
309             fprintf(config.map_file, " %s ",sp->name);
310           }
311           else {
312             fprintf(config.map_file, "undefined                     ");
313             fprintf(config.map_file, "%s ",sp->name);
314
315           }
316         }
317         print_nl();
318
319       }
320   }
321   if (option_longmap) {
322     lang_for_each_file(list_file_locals);
323   }
324 }
325
326 extern lang_output_section_statement_type *create_object_symbols;
327 extern char lprefix;
328 static asymbol **
329 write_file_locals(output_buffer)
330 asymbol **output_buffer;
331 {
332 LANG_FOR_EACH_INPUT_STATEMENT(entry)
333     {
334       /* Run trough the symbols and work out what to do with them */
335       unsigned int i;
336
337       /* Add one for the filename symbol if needed */
338       if (create_object_symbols 
339           != (lang_output_section_statement_type *)NULL) {
340         asection *s;
341         for (s = entry->the_bfd->sections;
342              s != (asection *)NULL;
343              s = s->next) {
344           if (s->output_section == create_object_symbols->bfd_section) {
345             /* Add symbol to this section */
346             asymbol * newsym  =
347               (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
348             newsym->name = entry->local_sym_name;
349             /* The symbol belongs to the output file's text section */
350
351             /* The value is the start of this section in the output file*/
352             newsym->value  = 0;
353             newsym->flags = BSF_LOCAL;
354             newsym->section = s;
355             *output_buffer++ = newsym;
356             break;
357           }
358         }
359       }
360       for (i = 0; i < entry->symbol_count; i++) 
361         {
362           asymbol *p = entry->asymbols[i];
363
364           if (flag_is_global(p->flags) )
365             {
366               /* We are only interested in outputting 
367                  globals at this stage in special circumstances */
368               if (p->the_bfd == entry->the_bfd 
369                   && flag_is_not_at_end(p->flags)) {
370                 /* And this is one of them */
371                 *(output_buffer++) = p;
372                 p->flags |= BSF_KEEP;
373               }
374             }
375           else {
376             if (flag_is_ordinary_local(p->flags)) 
377               {
378                 if (discard_locals == DISCARD_ALL)
379                   {  }
380                 else if (discard_locals == DISCARD_L &&
381                          (p->name[0] == lprefix)) 
382                   {  }
383                 else if (p->flags ==  BSF_WARNING) 
384                   {  }
385                 else 
386                   { *output_buffer++ = p; }
387               }
388             else if (flag_is_debugger(p->flags)) 
389               {
390                 /* Only keep the debugger symbols if no stripping required */
391                 if (strip_symbols == STRIP_NONE) {
392                   *output_buffer++ = p;
393                 }
394               }
395             else if (p->section == &bfd_und_section)
396               { /* This must be global */
397               }
398             else if (p->section == &bfd_com_section) {
399            /* And so must this */
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     if (from_table->sdefs_chain != (asymbol **)NULL) return false;
504   }
505   return true;
506 }
This page took 0.051205 seconds and 4 git commands to generate.