aboutsummaryrefslogtreecommitdiff
path: root/ld/ldsym.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldsym.c')
-rw-r--r--ld/ldsym.c564
1 files changed, 310 insertions, 254 deletions
diff --git a/ld/ldsym.c b/ld/ldsym.c
index 2351279..1c83d69 100644
--- a/ld/ldsym.c
+++ b/ld/ldsym.c
@@ -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);
}