diff options
Diffstat (limited to 'ld/ldsym.c')
-rw-r--r-- | ld/ldsym.c | 564 |
1 files changed, 310 insertions, 254 deletions
@@ -1,7 +1,7 @@ /* All symbol handling for the linker Copyright (C) 1991 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com - + This file is part of GLD, the Gnu Linker. This program is free software; you can redistribute it and/or modify @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* +/* We keep a hash table of global symbols. Each entry in a hash table is called an ldsym_type. Each has three chains; a pointer to a chain of definitions for the symbol (hopefully one long), a pointer @@ -38,7 +38,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +----------+ +----------+ | | | coms | | | +---------+ +----------+ +----------+ | udata |-----> another canonical symbol - +---------+ + +---------+ @@ -63,7 +63,7 @@ extern strip_symbols_type strip_symbols; extern discard_locals_type discard_locals; /* Head and tail of global symbol table chronological list */ -ldsym_type *symbol_head = (ldsym_type *)NULL; +ldsym_type *symbol_head = (ldsym_type *) NULL; ldsym_type **symbol_tail_ptr = &symbol_head; CONST char *keepsyms_file; int kept_syms; @@ -76,58 +76,61 @@ struct obstack global_sym_obstack; /* incremented for each symbol in the ldsym_type table - no matter what flavour it is + no matter what flavour it is */ unsigned int global_symbol_count; /* IMPORTS */ -extern boolean option_longmap ; +extern boolean option_longmap; /* LOCALS */ #define TABSIZE 1009 static ldsym_type *global_symbol_hash_table[TABSIZE]; /* Compute the hash code for symbol name KEY. */ -static +static #ifdef __GNUC__ -__inline + __inline #endif int -DEFUN(hash_string,(key), - CONST char *key) +DEFUN (hash_string, (key), + CONST char *key) { register CONST char *cp; register int k; register int l = 0; cp = key; k = 0; - while (*cp && l < symbol_truncate) { - k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; - l++; - } + while (*cp && l < symbol_truncate) + { + k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; + l++; + } return k; } static #ifdef __GNUC__ -__inline + __inline #endif -ldsym_type * -DEFUN(search,(key,hashval) , - CONST char *key AND - int hashval) + ldsym_type * +DEFUN (search, (key, hashval), + CONST char *key AND + int hashval) { - ldsym_type *bp; + ldsym_type *bp; for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link) - if (! strncmp (key, bp->name, symbol_truncate)) { - if (bp->flags & SYM_INDIRECT) { - /* Use the symbol we're aliased to instead */ - return (ldsym_type *)(bp->sdefs_chain); + if (!strncmp (key, bp->name, symbol_truncate)) + { + if (bp->flags & SYM_INDIRECT) + { + /* Use the symbol we're aliased to instead */ + return (ldsym_type *) (bp->sdefs_chain); + } + return bp; } - return bp; - } return 0; } @@ -135,8 +138,8 @@ DEFUN(search,(key,hashval) , /* Get the symbol table entry for the global symbol named KEY. Create one if there is none. */ ldsym_type * -DEFUN(ldsym_get,(key), - CONST char *key) +DEFUN (ldsym_get, (key), + CONST char *key) { register int hashval; register ldsym_type *bp; @@ -146,18 +149,19 @@ DEFUN(ldsym_get,(key), hashval = hash_string (key) % TABSIZE; /* Search the bucket. */ - bp = search(key, hashval); - if(bp) { - return bp; - } + bp = search (key, hashval); + if (bp) + { + return bp; + } /* Nothing was found; create a new symbol table entry. */ - bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type)(sizeof (ldsym_type))); - bp->srefs_chain = (asymbol **)NULL; - bp->sdefs_chain = (asymbol **)NULL; - bp->scoms_chain = (asymbol **)NULL; - bp->name = obstack_copy(&global_sym_obstack, key, strlen(key)+1); + bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type) (sizeof (ldsym_type))); + bp->srefs_chain = (asymbol **) NULL; + bp->sdefs_chain = (asymbol **) NULL; + bp->scoms_chain = (asymbol **) NULL; + bp->name = obstack_copy (&global_sym_obstack, key, strlen (key) + 1); bp->flags = 0; /* Add the entry to the bucket. */ @@ -176,8 +180,8 @@ DEFUN(ldsym_get,(key), /* Like `ldsym_get' but return 0 if the symbol is not already known. */ ldsym_type * -DEFUN(ldsym_get_soft,(key), - CONST char *key) +DEFUN (ldsym_get_soft, (key), + CONST char *key) { register int hashval; /* Determine which bucket. */ @@ -185,12 +189,12 @@ DEFUN(ldsym_get_soft,(key), hashval = hash_string (key) % TABSIZE; /* Search the bucket. */ - return search(key, hashval); + return search (key, hashval); } static asymbol ** process_keepsyms (table, size) - asymbol ** table; + asymbol **table; int size; { struct obstack obstack; @@ -279,7 +283,7 @@ process_keepsyms (table, size) || s->flags & BSF_KEEP_G) KEEP (sym); } - egress: +egress: obstack_free (&obstack, start_of_obstack); if (ks_file) fclose (ks_file); @@ -288,69 +292,73 @@ process_keepsyms (table, size) static void list_file_locals (entry) -lang_input_statement_type *entry; + lang_input_statement_type *entry; { asymbol **q; fprintf (config.map_file, "\nLocal symbols of "); - minfo("%I", entry); + minfo ("%I", entry); fprintf (config.map_file, ":\n\n"); - if (entry->asymbols) { - for (q = entry->asymbols; *q; q++) - { - asymbol *p = *q; - /* If this is a definition, + if (entry->asymbols) + { + for (q = entry->asymbols; *q; q++) + { + asymbol *p = *q; + /* If this is a definition, update it if necessary by this file's start address. */ - if (p->flags & BSF_LOCAL) - info(" %V %s\n",p->value, p->name); - } - } + if (p->flags & BSF_LOCAL) + info (" %V %s\n", p->value, p->name); + } + } } static void -DEFUN(print_file_stuff,(f), - lang_input_statement_type *f) +DEFUN (print_file_stuff, (f), + lang_input_statement_type * f) { - fprintf (config.map_file," %s\n", f->filename); - if (f->just_syms_flag) - { - fprintf (config.map_file, " symbols only\n"); - } - else - { - asection *s; - if (true || option_longmap) { - for (s = f->the_bfd->sections; - s != (asection *)NULL; - s = s->next) { - print_address(s->output_offset); - if (s->reloc_done) + fprintf (config.map_file, " %s\n", f->filename); + if (f->just_syms_flag) + { + fprintf (config.map_file, " symbols only\n"); + } + else + { + asection *s; + if (true || option_longmap) { - fprintf (config.map_file, " %08x 2**%2ud %s\n", - (unsigned)bfd_get_section_size_after_reloc(s), - s->alignment_power, s->name); + for (s = f->the_bfd->sections; + s != (asection *) NULL; + s = s->next) + { + print_address (s->output_offset); + if (s->reloc_done) + { + fprintf (config.map_file, " %08x 2**%2ud %s\n", + (unsigned) bfd_get_section_size_after_reloc (s), + s->alignment_power, s->name); + } + + else + { + fprintf (config.map_file, " %08x 2**%2ud %s\n", + (unsigned) bfd_get_section_size_before_reloc (s), + s->alignment_power, s->name); + } + } } - - else + else { - fprintf (config.map_file, " %08x 2**%2ud %s\n", - (unsigned)bfd_get_section_size_before_reloc(s), - s->alignment_power, s->name); + for (s = f->the_bfd->sections; + s != (asection *) NULL; + s = s->next) + { + fprintf (config.map_file, "%s ", s->name); + print_address (s->output_offset); + fprintf (config.map_file, "(%x)", (unsigned) bfd_get_section_size_after_reloc (s)); + } + fprintf (config.map_file, "hex \n"); } - } } - else - { - for (s = f->the_bfd->sections; - s != (asection *)NULL; - s = s->next) { - fprintf(config.map_file, "%s ", s->name); - print_address(s->output_offset); - fprintf(config.map_file, "(%x)", (unsigned)bfd_get_section_size_after_reloc(s)); - } - fprintf(config.map_file, "hex \n"); - } - } fprintf (config.map_file, "\n"); } @@ -359,155 +367,177 @@ ldsym_print_symbol_table () { fprintf (config.map_file, "**FILES**\n\n"); - lang_for_each_file(print_file_stuff); + lang_for_each_file (print_file_stuff); - fprintf(config.map_file, "**GLOBAL SYMBOLS**\n\n"); - fprintf(config.map_file, "offset section offset symbol\n"); + fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n"); + fprintf (config.map_file, "offset section offset symbol\n"); { register ldsym_type *sp; for (sp = symbol_head; sp; sp = sp->next) { - if (sp->flags & SYM_INDIRECT) { - fprintf(config.map_file,"indirect %s to %s\n", - sp->name, (((ldsym_type *)(sp->sdefs_chain))->name)); - } - else { - if (sp->sdefs_chain) - { - asymbol *defsym = *(sp->sdefs_chain); - asection *defsec = bfd_get_section(defsym); - print_address(defsym->value); - if (defsec) - { - fprintf(config.map_file, " %-10s", - bfd_section_name(output_bfd, - defsec)); - print_space(); - print_address(defsym->value+defsec->vma); - - } - else - { - fprintf(config.map_file, " ......."); - } - - } - - - if (sp->scoms_chain) { - fprintf(config.map_file, "common "); - print_address((*(sp->scoms_chain))->value); - fprintf(config.map_file, " %s ",sp->name); - } - else if (sp->sdefs_chain) { - fprintf(config.map_file, " %s ",sp->name); + if (sp->flags & SYM_INDIRECT) + { + fprintf (config.map_file, "indirect %s to %s\n", + sp->name, (((ldsym_type *) (sp->sdefs_chain))->name)); } - else { - fprintf(config.map_file, "undefined "); - fprintf(config.map_file, "%s ",sp->name); - + else + { + if (sp->sdefs_chain) + { + asymbol *defsym = *(sp->sdefs_chain); + asection *defsec = bfd_get_section (defsym); + print_address (defsym->value); + if (defsec) + { + fprintf (config.map_file, " %-10s", + bfd_section_name (output_bfd, + defsec)); + print_space (); + print_address (defsym->value + defsec->vma); + + } + else + { + fprintf (config.map_file, " ......."); + } + + } + + + if (sp->scoms_chain) + { + fprintf (config.map_file, "common "); + print_address ((*(sp->scoms_chain))->value); + fprintf (config.map_file, " %s ", sp->name); + } + else if (sp->sdefs_chain) + { + fprintf (config.map_file, " %s ", sp->name); + } + else + { + fprintf (config.map_file, "undefined "); + fprintf (config.map_file, "%s ", sp->name); + + } } - } - print_nl(); + print_nl (); } } - if (option_longmap) { - lang_for_each_file(list_file_locals); - } + if (option_longmap) + { + lang_for_each_file (list_file_locals); + } } extern lang_output_section_statement_type *create_object_symbols; extern char lprefix; static asymbol ** -write_file_locals(output_buffer) -asymbol **output_buffer; +write_file_locals (output_buffer) + asymbol **output_buffer; { - LANG_FOR_EACH_INPUT_STATEMENT(entry) + LANG_FOR_EACH_INPUT_STATEMENT (entry) { /* Run trough the symbols and work out what to do with them */ unsigned int i; /* Add one for the filename symbol if needed */ - if (create_object_symbols - != (lang_output_section_statement_type *)NULL) { - asection *s; - for (s = entry->the_bfd->sections; - s != (asection *)NULL; - s = s->next) { - if (s->output_section == create_object_symbols->bfd_section) { - /* Add symbol to this section */ - asymbol * newsym = - (asymbol *)bfd_make_empty_symbol(entry->the_bfd); - newsym->name = entry->local_sym_name; - /* The symbol belongs to the output file's text section */ - - /* The value is the start of this section in the output file*/ - newsym->value = 0; - /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as + if (create_object_symbols + != (lang_output_section_statement_type *) NULL) + { + asection *s; + for (s = entry->the_bfd->sections; + s != (asection *) NULL; + s = s->next) + { + if (s->output_section == create_object_symbols->bfd_section) + { + /* Add symbol to this section */ + asymbol *newsym = + (asymbol *) bfd_make_empty_symbol (entry->the_bfd); + newsym->name = entry->local_sym_name; + /* The symbol belongs to the output file's text section */ + + /* The value is the start of this section in the output file*/ + newsym->value = 0; + /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as "used by the linker" and I can't find any other code that uses it. Should be a cleaner way of doing this (like an "application flags" field in the symbol structure?). */ - newsym->flags = BSF_LOCAL | BSF_KEEP_G; - newsym->section = s; - *output_buffer++ = newsym; - break; - } + newsym->flags = BSF_LOCAL | BSF_KEEP_G; + newsym->section = s; + *output_buffer++ = newsym; + break; + } + } } - } - for (i = 0; i < entry->symbol_count; i++) - { - asymbol *p = entry->asymbols[i]; - /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */ - - if (p->section == 0) - p->section = &bfd_abs_section; - if (flag_is_global(p->flags) ) + for (i = 0; i < entry->symbol_count; i++) { - /* We are only interested in outputting + asymbol *p = entry->asymbols[i]; + /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */ + + if (p->section == 0) + p->section = &bfd_abs_section; + if (flag_is_global (p->flags)) + { + /* We are only interested in outputting globals at this stage in special circumstances */ - if (bfd_asymbol_bfd(p) == entry->the_bfd - && flag_is_not_at_end(p->flags)) { - /* And this is one of them */ - *(output_buffer++) = p; - p->flags |= BSF_KEEP; - } - } - else { - if (flag_is_debugger(p->flags)) - { - /* Only keep the debugger symbols if no stripping required */ - if (strip_symbols == STRIP_NONE) { - *output_buffer++ = p; + if (bfd_asymbol_bfd (p) == entry->the_bfd + && flag_is_not_at_end (p->flags)) + { + /* And this is one of them */ + *(output_buffer++) = p; + p->flags |= BSF_KEEP; + } } - } - else if (p->section == &bfd_und_section - || bfd_is_com_section (p->section)) - { - /* These must be global. */ - } - else if (flag_is_ordinary_local(p->flags)) - { - if (discard_locals == DISCARD_ALL) - { } - else if (discard_locals == DISCARD_L && - (p->name[0] == lprefix)) - { } - else if (p->flags == BSF_WARNING) - { } - else - { *output_buffer++ = p; } - } - else if (p->flags & BSF_CTOR) { - /* Throw it away */ - } else - { - FAIL(); - } + { + if (p->section == &bfd_ind_section) + { + /* Dont think about indirect symbols */ + } + else if (flag_is_debugger (p->flags)) + { + /* Only keep the debugger symbols if no stripping required */ + if (strip_symbols == STRIP_NONE) + { + *output_buffer++ = p; + } + } + else if (p->section == &bfd_und_section + || bfd_is_com_section (p->section)) + { + /* These must be global. */ + } + else if (flag_is_ordinary_local (p->flags)) + { + if (discard_locals == DISCARD_ALL) + { + } + else if (discard_locals == DISCARD_L && + (p->name[0] == lprefix)) + { + } + else if (p->flags == BSF_WARNING) + { + } + else + { + *output_buffer++ = p; + } + } + else if (p->flags & BSF_CTOR) + { + /* Throw it away */ + } + else + { + FAIL (); + } + } } - } } @@ -516,55 +546,79 @@ asymbol **output_buffer; static asymbol ** -write_file_globals(symbol_table) -asymbol **symbol_table; +write_file_globals (symbol_table) + asymbol **symbol_table; { - FOR_EACH_LDSYM(sp) - { - if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) { + FOR_EACH_LDSYM (sp) + { + if (sp->flags & SYM_INDIRECT) + { + asymbol *bufp = (*(sp->srefs_chain)); + ldsym_type *aliased_to = (ldsym_type *) (sp->sdefs_chain); + if (aliased_to->sdefs_chain) + { + asymbol *p = aliased_to->sdefs_chain[0]; + bufp->value = p->value; + bufp->section = p->section; + bufp->flags = p->flags; + } + else + { + bufp->value = 0; + bufp->flags = 0; + bufp->section = &bfd_und_section; + } + *symbol_table++ = bufp; + } + else if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **) NULL) + { asymbol *bufp = (*(sp->sdefs_chain)); - if ((bufp->flags & BSF_KEEP) ==0) { - ASSERT(bufp != (asymbol *)NULL); + if ((bufp->flags & BSF_KEEP) == 0) + { + ASSERT (bufp != (asymbol *) NULL); - bufp->name = sp->name; + bufp->name = sp->name; - if (sp->scoms_chain != (asymbol **)NULL) + if (sp->scoms_chain != (asymbol **) NULL) - { - /* + { + /* defined as common but not allocated, this happens only with -r and not -d, write out a common definition */ - bufp = *(sp->scoms_chain); - } - *symbol_table++ = bufp; - } + bufp = *(sp->scoms_chain); + } + *symbol_table++ = bufp; + } } - else if (sp->scoms_chain != (asymbol **)NULL) { + else if (sp->scoms_chain != (asymbol **) NULL) + { /* This symbol is a common - just output */ asymbol *bufp = (*(sp->scoms_chain)); *symbol_table++ = bufp; } - else if (sp->srefs_chain != (asymbol **)NULL) { + else if (sp->srefs_chain != (asymbol **) NULL) + { /* This symbol is undefined but has a reference */ asymbol *bufp = (*(sp->srefs_chain)); *symbol_table++ = bufp; } - else { + else + { /* This symbol has neither defs nor refs, it must have come from the command line, since noone has used it it has no - data attatched, so we'll ignore it + data attatched, so we'll ignore it */ } - } + } return symbol_table; } void -ldsym_write() +ldsym_write () { if (keepsyms_file != 0 && strip_symbols != STRIP_SOME) @@ -572,48 +626,50 @@ ldsym_write() info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n"); strip_symbols = STRIP_SOME; } - if (strip_symbols != STRIP_ALL) { - /* We know the maximum size of the symbol table - + if (strip_symbols != STRIP_ALL) + { + /* We know the maximum size of the symbol table - it's the size of all the global symbols ever seen + the size of all the symbols from all the files + the number of files (for the per file symbols) +1 (for the null at the end) */ - extern unsigned int total_files_seen; - extern unsigned int total_symbols_seen; + extern unsigned int total_files_seen; + extern unsigned int total_symbols_seen; - asymbol ** symbol_table = (asymbol **) - ldmalloc ((bfd_size_type)(global_symbol_count + - total_files_seen + - total_symbols_seen + 1) * sizeof (asymbol *)); - asymbol ** tablep = write_file_locals(symbol_table); + asymbol **symbol_table = (asymbol **) + ldmalloc ((bfd_size_type) (global_symbol_count + + total_files_seen + + total_symbols_seen + 1) * sizeof (asymbol *)); + asymbol **tablep = write_file_locals (symbol_table); - tablep = write_file_globals(tablep); - tablep = process_keepsyms (symbol_table, tablep - symbol_table); + tablep = write_file_globals (tablep); + tablep = process_keepsyms (symbol_table, tablep - symbol_table); - *tablep = (asymbol *)NULL; - bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table)); - } + *tablep = (asymbol *) NULL; + bfd_set_symtab (output_bfd, symbol_table, (unsigned) (tablep - symbol_table)); + } } /* -return true if the supplied symbol name is not in the +return true if the supplied symbol name is not in the linker symbol table */ -boolean -DEFUN(ldsym_undefined,(sym), - CONST char *sym) +boolean +DEFUN (ldsym_undefined, (sym), + CONST char *sym) { - ldsym_type *from_table = ldsym_get_soft(sym); - if (from_table != (ldsym_type *)NULL) - { - if (from_table->sdefs_chain != (asymbol **)NULL) return false; - } + ldsym_type *from_table = ldsym_get_soft (sym); + if (from_table != (ldsym_type *) NULL) + { + if (from_table->sdefs_chain != (asymbol **) NULL) + return false; + } return true; } void -DEFUN_VOID(ldsym_init) +DEFUN_VOID (ldsym_init) { - obstack_begin(&global_sym_obstack, 20000); + obstack_begin (&global_sym_obstack, 20000); } |