]> Git Repo - binutils.git/blob - ld/ldsym.c
Initial revision
[binutils.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  *  $Log$
23  *  Revision 1.3  1991/03/27 02:29:21  steve
24  *  *** empty log message ***
25  *
26  * Revision 1.2  1991/03/22  23:02:38  steve
27  * Brought up to sync with Intel again.
28  *
29  * Revision 1.1  1991/03/13  00:48:32  chrisb
30  * Initial revision
31  *
32  * Revision 1.4  1991/03/10  09:31:36  rich
33  *  Modified Files:
34  *      Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
35  *      ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
36  *      ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
37  *      ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
38  *      ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
39  *
40  * As of this round of changes, ld now builds on all hosts of (Intel960)
41  * interest and copy passes my copy test on big endian hosts again.
42  *
43  * Revision 1.3  1991/03/06  02:28:56  sac
44  * Cleaned up
45  *
46  * Revision 1.2  1991/02/22  17:15:06  sac
47  * Added RCS keywords and copyrights
48  *
49 */
50
51 /* 
52    Written by Steve Chamberlain [email protected]
53  
54    All symbol handling for the linker
55  */
56
57
58 #include "sysdep.h"
59 #include "bfd.h"
60
61 #include "ld.h"
62 #include "ldsym.h"
63 #include "ldmisc.h"
64 #include "ldlang.h"
65 /* IMPORT */
66
67 extern bfd *output_bfd;
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
89 int
90 hash_string (key)
91      char *key;
92 {
93   register char *cp;
94   register int k;
95
96   cp = key;
97   k = 0;
98   while (*cp)
99     k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
100
101   return k;
102 }
103
104 /* Get the symbol table entry for the global symbol named KEY.
105    Create one if there is none.  */
106 ldsym_type *
107 ldsym_get (key)
108      char *key;
109 {
110   register int hashval;
111   register ldsym_type *bp;
112
113   /* Determine the proper bucket.  */
114
115   hashval = hash_string (key) % TABSIZE;
116
117   /* Search the bucket.  */
118
119   for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
120     if (! strcmp (key, bp->name))
121       return bp;
122
123   /* Nothing was found; create a new symbol table entry.  */
124
125   bp = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
126   bp->srefs_chain = (asymbol **)NULL;
127   bp->sdefs_chain = (asymbol **)NULL;
128   bp->scoms_chain = (asymbol **)NULL;
129   bp->name = (char *) ldmalloc (strlen (key) + 1);
130   strcpy (bp->name, key);
131
132
133
134
135   /* Add the entry to the bucket.  */
136
137   bp->link = global_symbol_hash_table[hashval];
138   global_symbol_hash_table[hashval] = bp;
139
140   /* Keep the chronological list up to date too */
141   *symbol_tail_ptr = bp;
142   symbol_tail_ptr = &bp->next;
143   bp->next = 0;
144   global_symbol_count++;
145
146   return bp;
147 }
148
149 /* Like `ldsym_get' but return 0 if the symbol is not already known.  */
150
151 ldsym_type *
152 ldsym_get_soft (key)
153      char *key;
154 {
155   register int hashval;
156   register ldsym_type *bp;
157
158   /* Determine which bucket.  */
159
160   hashval = hash_string (key) % TABSIZE;
161
162   /* Search the bucket.  */
163
164   for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
165     if (! strcmp (key, bp->name))
166       return bp;
167
168   return 0;
169 }
170
171
172
173
174
175 static void
176 list_file_locals (entry)
177 lang_input_statement_type *entry;
178 {
179   asymbol **q;
180   fprintf (stderr, "\nLocal symbols of ");
181   info("%I", entry);
182   fprintf (stderr, ":\n\n");
183   if (entry->asymbols) {
184     for (q = entry->asymbols; *q; q++) 
185       {
186         asymbol *p = *q;
187         /* If this is a definition,
188            update it if necessary by this file's start address.  */
189         if (p->flags & BSF_LOCAL)
190          info("  %V %s\n",p->value, p->name);
191       }
192   }
193 }
194
195
196 static void
197 print_file_stuff(f)
198 lang_input_statement_type *f;
199 {
200   fprintf (stderr, "  %s", f->filename);
201   fprintf (stderr, " ");
202   if (f->just_syms_flag) 
203     {
204       fprintf (stderr, " symbols only\n");
205     }
206   else 
207     {
208       asection *s;
209       if (option_longmap) {
210         for (s = f->the_bfd->sections;
211              s != (asection *)NULL;
212              s = s->next) {
213           fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
214                    s->output_offset,
215                    (unsigned)s->size, s->alignment_power, s->name);
216         }
217       }
218       else {          
219         for (s = f->the_bfd->sections;
220              s != (asection *)NULL;
221              s = s->next) {
222           fprintf (stderr, "%s %lx(%x) ",
223                    s->name,
224                    s->output_offset,
225                    (unsigned)   s->size);
226         }
227         fprintf (stderr, "hex \n");
228       }
229     }
230 }
231
232 void
233 ldsym_print_symbol_table ()
234 {
235   fprintf (stderr, "\nFiles:\n\n");
236
237   lang_for_each_file(print_file_stuff);
238
239   fprintf (stderr, "\nGlobal symbols:\n\n");
240   {
241     register ldsym_type *sp;
242
243     for (sp = symbol_head; sp; sp = sp->next)
244       {
245         if (sp->sdefs_chain) 
246           {
247             asymbol *defsym = *(sp->sdefs_chain);
248             asection *defsec = bfd_get_section(defsym);
249             fprintf(stderr,"%08lx ",defsym->value);
250             if (defsec)
251               {
252                 fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
253                 fprintf(stderr,
254                         "%7s",
255                         bfd_section_name(output_bfd,
256                                          defsec));
257
258               }
259             else 
260               {
261                 fprintf(stderr,"         .......");
262               }
263
264           }     
265         else {
266           fprintf(stderr,"undefined");
267         }
268
269
270         if (sp->scoms_chain) {
271           fprintf(stderr, " common size %5lu    %s",
272                   (*(sp->scoms_chain))->value, sp->name);
273         }
274         if (sp->sdefs_chain) {
275           fprintf(stderr, " symbol def %08lx    %s",
276                   (*(sp->sdefs_chain))->value,
277                   sp->name);
278         }
279         else {
280           fprintf(stderr, " undefined    %s",
281                   sp->name);
282         }
283         fprintf(stderr, "\n");
284
285       }
286   }
287   lang_for_each_file(list_file_locals);
288 }
289
290 extern lang_output_section_statement_type *create_object_symbols;
291 extern char lprefix;
292 static asymbol **
293 write_file_locals(output_buffer)
294 asymbol **output_buffer;
295 {
296 LANG_FOR_EACH_INPUT_STATEMENT(entry)
297     {
298       /* Run trough the symbols and work out what to do with them */
299       unsigned int i;
300
301       /* Add one for the filename symbol if needed */
302       if (create_object_symbols 
303           != (lang_output_section_statement_type *)NULL) {
304         asection *s;
305         for (s = entry->the_bfd->sections;
306              s != (asection *)NULL;
307              s = s->next) {
308           if (s->output_section == create_object_symbols->bfd_section) {
309             /* Add symbol to this section */
310             asymbol * newsym  =
311               (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
312             newsym->name = entry->local_sym_name;
313             /* The symbol belongs to the output file's text section */
314
315             /* The value is the start of this section in the output file*/
316             newsym->value  = 0;
317             newsym->flags = BSF_LOCAL;
318             newsym->section = s;
319             *output_buffer++ = newsym;
320             break;
321           }
322         }
323       }
324       for (i = 0; i < entry->symbol_count; i++) 
325         {
326           asymbol *p = entry->asymbols[i];
327
328           if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
329             {
330               /* We are only interested in outputting 
331                  globals at this stage in special circumstances */
332               if (p->the_bfd == entry->the_bfd 
333                   && flag_is_not_at_end(p->flags)) {
334                 /* And this is one of them */
335                 *(output_buffer++) = p;
336                 p->flags |= BSF_KEEP;
337               }
338             }
339           else {
340             if (flag_is_ordinary_local(p->flags)) 
341               {
342                 if (discard_locals == DISCARD_ALL)
343                   {  }
344                 else if (discard_locals == DISCARD_L &&
345                          (p->name[0] == lprefix)) 
346                   {  }
347                 else if (p->flags ==  BSF_WARNING) 
348                   {  }
349                 else 
350                   { *output_buffer++ = p; }
351               }
352             else if (flag_is_debugger(p->flags)) 
353               {
354                 /* Only keep the debugger symbols if no stripping required */
355                 if (strip_symbols == STRIP_NONE) {
356                   *output_buffer++ = p;
357                 }
358               }
359             else if (flag_is_undefined(p->flags)) 
360               { /* This must be global */
361               }
362             else if (flag_is_common(p->flags)) {
363            /* And so must this */
364             } 
365             else if (p->flags & BSF_CTOR) {
366               /* Throw it away */
367             }
368 else
369               {
370                 FAIL();
371               }
372           }
373         }
374
375
376     }
377   return output_buffer;
378 }
379
380
381 static asymbol **
382 write_file_globals(symbol_table)
383 asymbol **symbol_table;
384 {
385   FOR_EACH_LDSYM(sp)
386     {
387       if (sp->sdefs_chain != (asymbol **)NULL) {
388         asymbol *bufp = (*(sp->sdefs_chain));
389
390         if ((bufp->flags & BSF_KEEP) ==0) {
391           ASSERT(bufp != (asymbol *)NULL);
392
393           bufp->name = sp->name;
394
395           if (sp->scoms_chain != (asymbol **)NULL)      
396
397             {
398               /* 
399                  defined as common but not allocated, this happens
400                  only with -r and not -d, write out a common
401                  definition
402                  */
403               bufp = *(sp->scoms_chain);
404             }
405           *symbol_table++ = bufp;
406         }
407       }
408       else if (sp->scoms_chain != (asymbol **)NULL) {
409         /* This symbol is a common - just output */
410         asymbol *bufp = (*(sp->scoms_chain));
411         *symbol_table++ = bufp;
412       }
413       else if (sp->srefs_chain != (asymbol **)NULL) {
414         /* This symbol is undefined but has a reference */
415         asymbol *bufp = (*(sp->srefs_chain));
416         *symbol_table++ = bufp;
417       }
418       else {
419         /*
420            This symbol has neither defs nor refs, it must have come
421            from the command line, since noone has used it it has no
422            data attatched, so we'll ignore it 
423            */
424       }
425     }
426   return symbol_table;
427 }
428
429
430
431 void
432 ldsym_write()
433 {
434   if (strip_symbols != STRIP_ALL) {
435     /* We know the maximum size of the symbol table -
436        it's the size of all the global symbols ever seen +
437        the size of all the symbols from all the files +
438        the number of files (for the per file symbols)
439        +1 (for the null at the end)
440        */
441     extern unsigned int total_files_seen;
442     extern unsigned int total_symbols_seen;
443
444     asymbol **  symbol_table =  (asymbol **) 
445       ldmalloc ((size_t)(global_symbol_count +
446                          total_files_seen +
447                          total_symbols_seen + 1) *     sizeof (asymbol *));
448     asymbol ** tablep = write_file_locals(symbol_table);
449
450     tablep = write_file_globals(tablep);
451
452     *tablep =  (asymbol *)NULL;
453     bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
454   }
455 }
456
457 /*
458 return true if the supplied symbol name is not in the 
459 linker symbol table
460 */
461 boolean 
462 ldsym_undefined(sym)
463 char *sym;
464 {
465   ldsym_type *from_table = ldsym_get_soft(sym);
466   if (from_table != (ldsym_type *)NULL) {
467     if (from_table->sdefs_chain != (asymbol **)NULL) return false;
468   }
469   return true;
470 }
This page took 0.049513 seconds and 4 git commands to generate.