]> Git Repo - binutils.git/blob - ld/ldsym.c
comment formatting fixup
[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    We keep a hash table of global symbols. Each entry in a hash table
23    is called an ldsym_type. Each has three chains; a pointer to a
24    chain of definitions for the symbol (hopefully one long), a pointer
25    to a chain of references to the symbol, and a pointer to a chain of
26    common symbols. Each pointer points into the canonical symbol table
27    provided by bfd, each one of which points to an asymbol. During
28    linkage, the linker uses the udata field to point to the next entry
29    in a canonical table....
30
31
32    ld_sym
33                         |          |
34    +----------+         +----------+
35    | defs     |      a canonical symbol table
36    +----------+         +----------+
37    | refs     | ----->  | one entry|  -----> asymbol
38    +----------+         +----------+       |         |
39    | coms     |         |          |       +---------+
40    +----------+         +----------+       | udata   |-----> another canonical
41                                            +---------+          symbol
42
43
44
45    It is very simple to make all the symbol pointers point to the same
46    definition - just run down the chain and make the asymbols pointers
47    within the canonical table point to the asymbol attacthed to the
48    definition of the symbol.
49
50 */
51
52 #include "bfd.h"
53 #include "sysdep.h"
54
55 #include "ld.h"
56 #include "ldsym.h"
57 #include "ldmisc.h"
58 #include "ldlang.h"
59 /* IMPORT */
60 extern int symbol_truncate;
61 extern bfd *output_bfd;
62 extern strip_symbols_type strip_symbols;
63 extern discard_locals_type discard_locals;
64 /* Head and tail of global symbol table chronological list */
65
66 ldsym_type *symbol_head = (ldsym_type *) NULL;
67 ldsym_type **symbol_tail_ptr = &symbol_head;
68 CONST char *keepsyms_file;
69 int kept_syms;
70
71 extern ld_config_type config;
72
73 struct obstack global_sym_obstack;
74 #define obstack_chunk_alloc ldmalloc
75 #define obstack_chunk_free  free
76
77 /*
78   incremented for each symbol in the ldsym_type table
79   no matter what flavour it is
80 */
81 unsigned int global_symbol_count;
82
83 /* IMPORTS */
84
85 extern boolean option_longmap;
86
87 /* LOCALS */
88 #define TABSIZE 1009
89 static ldsym_type *global_symbol_hash_table[TABSIZE];
90
91 /* Compute the hash code for symbol name KEY.  */
92 static
93 #ifdef __GNUC__
94   __inline
95 #endif
96
97 int
98 DEFUN (hash_string, (key),
99        CONST char *key)
100 {
101   register CONST char *cp;
102   register int k;
103   register int l = 0;
104   cp = key;
105   k = 0;
106   while (*cp && l < symbol_truncate)
107     {
108       k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
109       l++;
110     }
111   return k;
112 }
113
114 static
115 #ifdef __GNUC__
116   __inline
117 #endif
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 (!strncmp (key, bp->name, symbol_truncate))
126       {
127         if (bp->flags & SYM_INDIRECT)
128           {
129             /* Use the symbol we're aliased to instead */
130             return (ldsym_type *) (bp->sdefs_chain);
131           }
132         return bp;
133       }
134   return 0;
135 }
136
137
138 /* Get the symbol table entry for the global symbol named KEY.
139    Create one if there is none.  */
140 ldsym_type *
141 DEFUN (ldsym_get, (key),
142        CONST char *key)
143 {
144   register int hashval;
145   register ldsym_type *bp;
146
147   /* Determine the proper bucket.  */
148
149   hashval = hash_string (key) % TABSIZE;
150
151   /* Search the bucket.  */
152   bp = search (key, hashval);
153   if (bp)
154     {
155       return bp;
156     }
157
158   /* Nothing was found; create a new symbol table entry.  */
159
160   bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type) (sizeof (ldsym_type)));
161   bp->srefs_chain = (asymbol **) NULL;
162   bp->sdefs_chain = (asymbol **) NULL;
163   bp->scoms_chain = (asymbol **) NULL;
164   bp->name = obstack_copy (&global_sym_obstack, key, strlen (key) + 1);
165   bp->flags = 0;
166   /* Add the entry to the bucket.  */
167
168   bp->link = global_symbol_hash_table[hashval];
169   global_symbol_hash_table[hashval] = bp;
170
171   /* Keep the chronological list up to date too */
172   *symbol_tail_ptr = bp;
173   symbol_tail_ptr = &bp->next;
174   bp->next = 0;
175   global_symbol_count++;
176
177   return bp;
178 }
179
180 /* Like `ldsym_get' but return 0 if the symbol is not already known.  */
181
182 ldsym_type *
183 DEFUN (ldsym_get_soft, (key),
184        CONST char *key)
185 {
186   register int hashval;
187   /* Determine which bucket.  */
188
189   hashval = hash_string (key) % TABSIZE;
190
191   /* Search the bucket.  */
192   return search (key, hashval);
193 }
194
195 static asymbol **
196 process_keepsyms (table, size)
197      asymbol **table;
198      int size;
199 {
200   struct obstack obstack;
201   char *start_of_obstack;
202   FILE *ks_file = 0;
203   asymbol **out = table;
204   asymbol **end = table + size;
205   asymbol **sym;
206
207   if (!keepsyms_file || size == 0)
208     return end;
209   obstack_init (&obstack);
210   obstack_alloc (&obstack, 1);
211   obstack_finish (&obstack);
212   start_of_obstack = obstack_alloc (&obstack, 1);
213   ks_file = fopen (keepsyms_file, "r");
214   if (!ks_file)
215     {
216       info ("%X%P: can't open keep-symbols file `%s'\n", keepsyms_file);
217       goto egress;
218     }
219   errno = 0;
220
221 #define KEEP(S) \
222   do { asymbol **p = (S), *tmp = *out; *out = *p; *p = tmp; out++; } while (0)
223
224   while (!feof (ks_file) && !ferror (ks_file))
225     {
226       int c;
227       char *ptr;
228       int found = 0;
229
230       obstack_free (&obstack, start_of_obstack);
231       do
232         {
233           c = getc (ks_file);
234           if (c == '\n')
235             c = 0;
236           obstack_1grow (&obstack, c);
237         }
238       while (c > 0);
239       if (c == EOF)
240         {
241           if (!feof (ks_file))
242             /* error occurred */
243             {
244               info ("%X%P: error reading keep-symbols file `%s': %E\n",
245                     keepsyms_file);
246               out = end;
247               goto egress;
248             }
249           if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1)
250             /* eof in middle of symbol */
251             {
252               info ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n",
253                     keepsyms_file);
254               out = end;
255               goto egress;
256             }
257           /* All okay -- no incomplete lines, EOF reached.  */
258           break;
259         }
260       ptr = obstack_next_free (&obstack) - 2;
261       /* discard trailing trash */
262       while (*ptr == ' '
263              || *ptr == '\t')
264         *ptr-- = 0;
265       ptr = obstack_base (&obstack);
266       for (sym = out; sym < end; sym++)
267         if (!strncmp ((*sym)->name, ptr, symbol_truncate))
268           {
269             KEEP (sym);
270             found = 1;
271           }
272       if (!found)
273         info ("%P: symbol `%s' (requested to be kept) not found\n", ptr);
274     }
275   /* It'd be slightly faster to move this pass above the previous one,
276      but that'd mean any symbols preserved in this pass would generate
277      warnings if they were also listed in the keepsyms file.  */
278   for (sym = out; sym < end; sym++)
279     {
280       asymbol *s = *sym;
281       if (s->section == &bfd_und_section
282           || bfd_is_com_section (s->section)
283           || s->flags & BSF_KEEP_G)
284         KEEP (sym);
285     }
286 egress:
287   obstack_free (&obstack, start_of_obstack);
288   if (ks_file)
289     fclose (ks_file);
290   return out;
291 }
292
293 static void
294 list_file_locals (entry)
295      lang_input_statement_type *entry;
296 {
297   asymbol **q;
298   fprintf (config.map_file, "\nLocal symbols of ");
299   minfo ("%I", entry);
300   fprintf (config.map_file, ":\n\n");
301   if (entry->asymbols)
302     {
303       for (q = entry->asymbols; *q; q++)
304         {
305           asymbol *p = *q;
306           /* If this is a definition,
307            update it if necessary by this file's start address.  */
308           if (p->flags & BSF_LOCAL)
309             info ("  %V %s\n", p->value, p->name);
310         }
311     }
312 }
313
314
315 static void
316 DEFUN (print_file_stuff, (f),
317        lang_input_statement_type * f)
318 {
319   fprintf (config.map_file, "  %s\n", f->filename);
320   if (f->just_syms_flag)
321     {
322       fprintf (config.map_file, " symbols only\n");
323     }
324   else
325     {
326       asection *s;
327       if (true || option_longmap)
328         {
329           for (s = f->the_bfd->sections;
330                s != (asection *) NULL;
331                s = s->next)
332             {
333               print_address (s->output_offset);
334               if (s->reloc_done)
335                 {
336                   fprintf (config.map_file, " %08x 2**%2ud %s\n",
337                            (unsigned) bfd_get_section_size_after_reloc (s),
338                            s->alignment_power, s->name);
339                 }
340
341               else
342                 {
343                   fprintf (config.map_file, " %08x 2**%2ud %s\n",
344                            (unsigned) bfd_get_section_size_before_reloc (s),
345                            s->alignment_power, s->name);
346                 }
347             }
348         }
349       else
350         {
351           for (s = f->the_bfd->sections;
352                s != (asection *) NULL;
353                s = s->next)
354             {
355               fprintf (config.map_file, "%s ", s->name);
356               print_address (s->output_offset);
357               fprintf (config.map_file, "(%x)", (unsigned) bfd_get_section_size_after_reloc (s));
358             }
359           fprintf (config.map_file, "hex \n");
360         }
361     }
362   fprintf (config.map_file, "\n");
363 }
364
365 void
366 ldsym_print_symbol_table ()
367 {
368   fprintf (config.map_file, "**FILES**\n\n");
369
370   lang_for_each_file (print_file_stuff);
371
372   fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
373   fprintf (config.map_file, "offset    section    offset   symbol\n");
374   {
375     register ldsym_type *sp;
376
377     for (sp = symbol_head; sp; sp = sp->next)
378       {
379         if (sp->flags & SYM_INDIRECT)
380           {
381             fprintf (config.map_file, "indirect %s to %s\n",
382                      sp->name, (((ldsym_type *) (sp->sdefs_chain))->name));
383           }
384         else
385           {
386             if (sp->sdefs_chain)
387               {
388                 asymbol *defsym = *(sp->sdefs_chain);
389                 asection *defsec = bfd_get_section (defsym);
390                 print_address (defsym->value);
391                 if (defsec)
392                   {
393                     fprintf (config.map_file, "  %-10s",
394                              bfd_section_name (output_bfd,
395                                                defsec));
396                     print_space ();
397                     print_address (defsym->value + defsec->vma);
398
399                   }
400                 else
401                   {
402                     fprintf (config.map_file, "         .......");
403                   }
404
405               }
406
407
408             if (sp->scoms_chain)
409               {
410                 fprintf (config.map_file, "common               ");
411                 print_address ((*(sp->scoms_chain))->value);
412                 fprintf (config.map_file, " %s ", sp->name);
413               }
414             else if (sp->sdefs_chain)
415               {
416                 fprintf (config.map_file, " %s ", sp->name);
417               }
418             else
419               {
420                 fprintf (config.map_file, "undefined                     ");
421                 fprintf (config.map_file, "%s ", sp->name);
422
423               }
424           }
425         print_nl ();
426
427       }
428   }
429   if (option_longmap)
430     {
431       lang_for_each_file (list_file_locals);
432     }
433 }
434
435 extern lang_output_section_statement_type *create_object_symbols;
436 extern char lprefix;
437 static asymbol **
438 write_file_locals (output_buffer)
439      asymbol **output_buffer;
440 {
441   LANG_FOR_EACH_INPUT_STATEMENT (entry)
442   {
443     /* Run trough the symbols and work out what to do with them */
444     unsigned int i;
445
446     /* Add one for the filename symbol if needed */
447     if (create_object_symbols
448         != (lang_output_section_statement_type *) NULL)
449       {
450         asection *s;
451         for (s = entry->the_bfd->sections;
452              s != (asection *) NULL;
453              s = s->next)
454           {
455             if (s->output_section == create_object_symbols->bfd_section)
456               {
457                 /* Add symbol to this section */
458                 asymbol *newsym =
459                 (asymbol *) bfd_make_empty_symbol (entry->the_bfd);
460                 newsym->name = entry->local_sym_name;
461                 /* The symbol belongs to the output file's text section */
462
463                 /* The value is the start of this section in the output file*/
464                 newsym->value = 0;
465                 /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as
466              "used by the linker" and I can't find any other code that
467              uses it.  Should be a cleaner way of doing this (like an
468              "application flags" field in the symbol structure?).  */
469                 newsym->flags = BSF_LOCAL | BSF_KEEP_G;
470                 newsym->section = s;
471                 *output_buffer++ = newsym;
472                 break;
473               }
474           }
475       }
476     for (i = 0; i < entry->symbol_count; i++)
477       {
478         asymbol *p = entry->asymbols[i];
479         /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
480
481         if (p->section == 0)
482           p->section = &bfd_abs_section;
483         if (flag_is_global (p->flags))
484           {
485             /* We are only interested in outputting
486            globals at this stage in special circumstances */
487             if (bfd_asymbol_bfd (p) == entry->the_bfd
488                 && flag_is_not_at_end (p->flags))
489               {
490                 /* And this is one of them */
491                 *(output_buffer++) = p;
492                 p->flags |= BSF_KEEP;
493               }
494           }
495         else
496           {
497             if (p->section == &bfd_ind_section)
498               {
499                 /* Dont think about indirect symbols */
500               }
501             else if (flag_is_debugger (p->flags))
502               {
503                 /* Only keep the debugger symbols if no stripping required */
504                 if (strip_symbols == STRIP_NONE)
505                   {
506                     *output_buffer++ = p;
507                   }
508               }
509             else if (p->section == &bfd_und_section
510                      || bfd_is_com_section (p->section))
511               {
512                 /* These must be global.  */
513               }
514             else if (flag_is_ordinary_local (p->flags))
515               {
516                 if (discard_locals == DISCARD_ALL)
517                   {
518                   }
519                 else if (discard_locals == DISCARD_L &&
520                          (p->name[0] == lprefix))
521                   {
522                   }
523                 else if (p->flags == BSF_WARNING)
524                   {
525                   }
526                 else
527                   {
528                     *output_buffer++ = p;
529                   }
530               }
531             else if (p->flags & BSF_CTOR)
532               {
533                 /* Throw it away */
534               }
535             else
536               {
537                 FAIL ();
538               }
539           }
540       }
541
542
543   }
544   return output_buffer;
545 }
546
547
548 static asymbol **
549 write_file_globals (symbol_table)
550      asymbol **symbol_table;
551 {
552   FOR_EACH_LDSYM (sp)
553   {
554     if (sp->flags & SYM_INDIRECT)
555       {
556         asymbol *bufp = (*(sp->srefs_chain));
557         ldsym_type *aliased_to = (ldsym_type *) (sp->sdefs_chain);
558         if (aliased_to->sdefs_chain)
559           {
560             asymbol *p = aliased_to->sdefs_chain[0];
561             bufp->value = p->value;
562             bufp->section = p->section;
563             bufp->flags = p->flags;
564           }
565         else
566           {
567             bufp->value = 0;
568             bufp->flags = 0;
569             bufp->section = &bfd_und_section;
570           }
571         *symbol_table++ = bufp;
572       }
573     else if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **) NULL)
574       {
575         asymbol *bufp = (*(sp->sdefs_chain));
576
577         if ((bufp->flags & BSF_KEEP) == 0)
578           {
579             ASSERT (bufp != (asymbol *) NULL);
580
581             bufp->name = sp->name;
582
583             if (sp->scoms_chain != (asymbol **) NULL)
584
585               {
586                 /*
587                  defined as common but not allocated, this happens
588                  only with -r and not -d, write out a common
589                  definition
590                  */
591                 bufp = *(sp->scoms_chain);
592               }
593             *symbol_table++ = bufp;
594           }
595       }
596     else if (sp->scoms_chain != (asymbol **) NULL)
597       {
598         /* This symbol is a common - just output */
599         asymbol *bufp = (*(sp->scoms_chain));
600         *symbol_table++ = bufp;
601       }
602     else if (sp->srefs_chain != (asymbol **) NULL)
603       {
604         /* This symbol is undefined but has a reference */
605         asymbol *bufp = (*(sp->srefs_chain));
606         *symbol_table++ = bufp;
607       }
608     else
609       {
610         /*
611            This symbol has neither defs nor refs, it must have come
612            from the command line, since noone has used it it has no
613            data attatched, so we'll ignore it
614            */
615       }
616   }
617   return symbol_table;
618 }
619
620 void
621 ldsym_write ()
622 {
623   if (keepsyms_file != 0
624       && strip_symbols != STRIP_SOME)
625     {
626       info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n");
627       strip_symbols = STRIP_SOME;
628     }
629   if (strip_symbols != STRIP_ALL)
630     {
631       /* We know the maximum size of the symbol table -
632        it's the size of all the global symbols ever seen +
633        the size of all the symbols from all the files +
634        the number of files (for the per file symbols)
635        +1 (for the null at the end)
636        */
637       extern unsigned int total_files_seen;
638       extern unsigned int total_symbols_seen;
639
640       asymbol **symbol_table = (asymbol **)
641       ldmalloc ((bfd_size_type) (global_symbol_count +
642                                  total_files_seen +
643                               total_symbols_seen + 1) * sizeof (asymbol *));
644       asymbol **tablep = write_file_locals (symbol_table);
645
646       tablep = write_file_globals (tablep);
647       tablep = process_keepsyms (symbol_table, tablep - symbol_table);
648
649       *tablep = (asymbol *) NULL;
650       bfd_set_symtab (output_bfd, symbol_table, (unsigned) (tablep - symbol_table));
651     }
652 }
653
654 /*
655 return true if the supplied symbol name is not in the
656 linker symbol table
657 */
658 boolean
659 DEFUN (ldsym_undefined, (sym),
660        CONST char *sym)
661 {
662   ldsym_type *from_table = ldsym_get_soft (sym);
663   if (from_table != (ldsym_type *) NULL)
664     {
665       if (from_table->sdefs_chain != (asymbol **) NULL)
666         return false;
667     }
668   return true;
669 }
670
671 void
672 DEFUN_VOID (ldsym_init)
673 {
674   obstack_begin (&global_sym_obstack, 20000);
675 }
This page took 0.06008 seconds and 4 git commands to generate.