Written by Steve Chamberlain steve@cygnus.com
All symbol handling for the linker
- */
+
+
+ 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
+ to a chain of references to the symbol, and a pointer to a chain of
+ common symbols. Each pointer points into the canonical symbol table
+ provided by bfd, each one of which points to an asymbol. Duringing
+ linkage, the linker uses the udata field to point to the next entry
+ in a canonical table....
+
+
+ ld_sym
+ | |
+ +----------+ +----------+
+ | defs | a canonical symbol table
+ +----------+ +----------+
+ | refs | -----> | one entry| -----> asymbol
+ +----------+ +----------+ | |
+ | coms | | | +---------+
+ +----------+ +----------+ | udata |-----> another canonical symbol
+ +---------+
+
+
+
+ It is very simple to make all the symbol pointers point to the same
+ definition - just run down the chain and make the asymbols pointers
+ within the canonical table point to the asymbol attacthed to the
+ definition of the symbol.
+
+*/
+
#include "sysdep.h"
#include "bfd.h"
static ldsym_type *global_symbol_hash_table[TABSIZE];
/* Compute the hash code for symbol name KEY. */
-
+static
+#ifdef __GNUC__
+inline
+#endif
int
-hash_string (key)
- char *key;
+DEFUN(hash_string,(key),
+ CONST char *key)
{
- register char *cp;
+ register CONST char *cp;
register int k;
cp = key;
return k;
}
+static
+#ifdef __GNUC__
+inline
+#endif ldsym_type *bp;
+ldsym_type *
+DEFUN(search,(key,hashval) ,
+ CONST char *key AND
+ int hashval)
+{
+ ldsym_type *bp;
+ for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
+ if (! strcmp (key, bp->name)) {
+ if (bp->flags & SYM_INDIRECT) {
+ /* Use the symbol we're aliased to instead */
+ return (ldsym_type *)(bp->sdefs_chain);
+ }
+ return bp;
+ }
+ return 0;
+}
+
+
/* Get the symbol table entry for the global symbol named KEY.
Create one if there is none. */
ldsym_type *
hashval = hash_string (key) % TABSIZE;
/* Search the bucket. */
-
- for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
- if (! strcmp (key, bp->name))
- return bp;
+ bp = search(key, hashval);
+ if(bp) {
+ return bp;
+ }
/* Nothing was found; create a new symbol table entry. */
bp->sdefs_chain = (asymbol **)NULL;
bp->scoms_chain = (asymbol **)NULL;
bp->name = buystring(key);
-
+ bp->flags = 0;
/* Add the entry to the bucket. */
bp->link = global_symbol_hash_table[hashval];
hashval = hash_string (key) % TABSIZE;
/* Search the bucket. */
-
- for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
- if (! strcmp (key, bp->name))
- return bp;
-
- return 0;
+return search(key, hashval);
}
print_file_stuff(f)
lang_input_statement_type *f;
{
- fprintf (stdout, " %s", f->filename);
- fprintf (stdout, " ");
+ fprintf (stdout, " %s\n", f->filename);
if (f->just_syms_flag)
- {
- fprintf (stdout, " symbols only\n");
- }
+ {
+ fprintf (stdout, " 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);
- printf ( "%08x 2**%2ud %s\n",
- (unsigned)s->size, s->alignment_power, s->name);
+ {
+ asection *s;
+ if (true || option_longmap) {
+ for (s = f->the_bfd->sections;
+ s != (asection *)NULL;
+ s = s->next) {
+ print_address(s->output_offset);
+ printf (" %08x 2**%2ud %s\n",
+ (unsigned)s->size, s->alignment_power, s->name);
+ }
}
- }
- else {
- for (s = f->the_bfd->sections;
- s != (asection *)NULL;
- s = s->next) {
- printf("%s ", s->name);
- print_address(s->output_offset);
- printf("(%x)", (unsigned)s->size);
+ else {
+ for (s = f->the_bfd->sections;
+ s != (asection *)NULL;
+ s = s->next) {
+ printf("%s ", s->name);
+ print_address(s->output_offset);
+ printf("(%x)", (unsigned)s->size);
+ }
+ printf("hex \n");
}
- printf("hex \n");
}
- }
+ fprintf (stdout, "\n");
}
void
ldsym_print_symbol_table ()
{
- fprintf (stdout, "\nFiles:\n\n");
+ fprintf (stdout, "**FILES**\n\n");
lang_for_each_file(print_file_stuff);
- fprintf (stdout, "\nGlobal symbols:\n\n");
+ fprintf(stdout, "**GLOBAL SYMBOLS**\n\n");
+ fprintf(stdout, "offset section offset symbol\n");
{
register ldsym_type *sp;
for (sp = symbol_head; sp; sp = sp->next)
{
+ if (sp->flags & SYM_INDIRECT) {
+ fprintf(stdout,"indirect %s to %s\n",
+ sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
+ }
+ else {
if (sp->sdefs_chain)
{
asymbol *defsym = *(sp->sdefs_chain);
print_address(defsym->value);
if (defsec)
{
- print_space();
- print_address(defsym->value+defsec->vma);
- printf("%7s",
+ printf(" %-10s",
bfd_section_name(output_bfd,
defsec));
+ print_space();
+ print_address(defsym->value+defsec->vma);
}
else
}
}
- else {
- printf("undefined");
- }
if (sp->scoms_chain) {
- printf(" common size ");
+ printf("common ");
print_address((*(sp->scoms_chain))->value);
- printf("%s ",sp->name);
+ printf(" %s ",sp->name);
}
- if (sp->sdefs_chain) {
- printf(" symbol def ");
- print_address((*(sp->sdefs_chain))->value);
- printf("%s ",sp->name);
+ else if (sp->sdefs_chain) {
+ printf(" %s ",sp->name);
}
else {
- printf(" undefined ");
+ printf("undefined ");
printf("%s ",sp->name);
+
}
+ }
print_nl();
}
{
FOR_EACH_LDSYM(sp)
{
- if (sp->sdefs_chain != (asymbol **)NULL) {
+ if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) {
asymbol *bufp = (*(sp->sdefs_chain));
if ((bufp->flags & BSF_KEEP) ==0) {