/*
* $Id$
*
- * $Log$
- * Revision 1.2 1991/03/22 23:02:38 steve
- * Brought up to sync with Intel again.
- *
- * Revision 1.1 1991/03/13 00:48:32 chrisb
- * Initial revision
- *
- * Revision 1.4 1991/03/10 09:31:36 rich
- * Modified Files:
- * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
- * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
- * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
- * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
- * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
- *
- * As of this round of changes, ld now builds on all hosts of (Intel960)
- * interest and copy passes my copy test on big endian hosts again.
- *
- * Revision 1.3 1991/03/06 02:28:56 sac
- * Cleaned up
- *
- * Revision 1.2 1991/02/22 17:15:06 sac
- * Added RCS keywords and copyrights
*
*/
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"
/* IMPORT */
extern bfd *output_bfd;
+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;
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 *
-ldsym_get (key)
- char *key;
+DEFUN(ldsym_get,(key),
+ CONST char *key)
{
register int hashval;
register ldsym_type *bp;
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 = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
+ bp = (ldsym_type *) ldmalloc ((bfd_size_type)(sizeof (ldsym_type)));
bp->srefs_chain = (asymbol **)NULL;
bp->sdefs_chain = (asymbol **)NULL;
bp->scoms_chain = (asymbol **)NULL;
- bp->name = (char *) ldmalloc (strlen (key) + 1);
- strcpy (bp->name, key);
-
-
-
-
+ bp->name = buystring(key);
+ bp->flags = 0;
/* Add the entry to the bucket. */
bp->link = global_symbol_hash_table[hashval];
/* Like `ldsym_get' but return 0 if the symbol is not already known. */
ldsym_type *
-ldsym_get_soft (key)
- char *key;
+DEFUN(ldsym_get_soft,(key),
+ CONST char *key)
{
register int hashval;
register ldsym_type *bp;
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);
}
lang_input_statement_type *entry;
{
asymbol **q;
- fprintf (stderr, "\nLocal symbols of ");
+ printf ( "\nLocal symbols of ");
info("%I", entry);
- fprintf (stderr, ":\n\n");
+ printf (":\n\n");
if (entry->asymbols) {
for (q = entry->asymbols; *q; q++)
{
print_file_stuff(f)
lang_input_statement_type *f;
{
- fprintf (stderr, " %s", f->filename);
- fprintf (stderr, " ");
+ fprintf (stdout, " %s\n", f->filename);
if (f->just_syms_flag)
- {
- fprintf (stderr, " symbols only\n");
- }
+ {
+ fprintf (stdout, " symbols only\n");
+ }
else
- {
- asection *s;
- if (option_longmap) {
- for (s = f->the_bfd->sections;
- s != (asection *)NULL;
- s = s->next) {
- fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
- s->output_offset,
- (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) {
- fprintf (stderr, "%s %lx(%x) ",
- s->name,
- s->output_offset,
- (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");
}
- fprintf (stderr, "hex \n");
}
- }
+ fprintf (stdout, "\n");
}
void
ldsym_print_symbol_table ()
{
- fprintf (stderr, "\nFiles:\n\n");
+ fprintf (stdout, "**FILES**\n\n");
lang_for_each_file(print_file_stuff);
- fprintf (stderr, "\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);
asection *defsec = bfd_get_section(defsym);
- fprintf(stderr,"%08lx ",defsym->value);
+ print_address(defsym->value);
if (defsec)
{
- fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
- fprintf(stderr,
- "%7s",
+ printf(" %-10s",
bfd_section_name(output_bfd,
defsec));
+ print_space();
+ print_address(defsym->value+defsec->vma);
}
else
{
- fprintf(stderr," .......");
+ printf(" .......");
}
}
- else {
- fprintf(stderr,"undefined");
- }
if (sp->scoms_chain) {
- fprintf(stderr, " common size %5lu %s",
- (*(sp->scoms_chain))->value, sp->name);
+ printf("common ");
+ print_address((*(sp->scoms_chain))->value);
+ printf(" %s ",sp->name);
}
- if (sp->sdefs_chain) {
- fprintf(stderr, " symbol def %08lx %s",
- (*(sp->sdefs_chain))->value,
- sp->name);
+ else if (sp->sdefs_chain) {
+ printf(" %s ",sp->name);
}
else {
- fprintf(stderr, " undefined %s",
- sp->name);
+ printf("undefined ");
+ printf("%s ",sp->name);
+
}
- fprintf(stderr, "\n");
+ }
+ 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) {
extern unsigned int total_symbols_seen;
asymbol ** symbol_table = (asymbol **)
- ldmalloc ((size_t)(global_symbol_count +
+ ldmalloc ((bfd_size_type)(global_symbol_count +
total_files_seen +
total_symbols_seen + 1) * sizeof (asymbol *));
asymbol ** tablep = write_file_locals(symbol_table);
bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
}
}
+
+/*
+return true if the supplied symbol name is not in the
+linker symbol table
+*/
+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;
+ }
+ return true;
+}