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