diff options
Diffstat (limited to 'gnu/usr.bin/ld/symbol.c')
| -rw-r--r-- | gnu/usr.bin/ld/symbol.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/gnu/usr.bin/ld/symbol.c b/gnu/usr.bin/ld/symbol.c new file mode 100644 index 000000000000..495726565e58 --- /dev/null +++ b/gnu/usr.bin/ld/symbol.c @@ -0,0 +1,159 @@ +/* + * $Id: symbol.c,v 1.4 1994/02/13 20:41:46 jkh Exp $ - symbol table routines + */ + +/* Create the symbol table entries for `etext', `edata' and `end'. */ + +#include <sys/param.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <fcntl.h> +#include <a.out.h> +#include <stab.h> +#include <string.h> + +#include "ld.h" + +symbol *symtab[SYMTABSIZE]; /* The symbol table. */ +int num_hash_tab_syms; /* Number of symbols in symbol hash table. */ + +symbol *edata_symbol; /* the symbol _edata */ +symbol *etext_symbol; /* the symbol _etext */ +symbol *end_symbol; /* the symbol _end */ +symbol *got_symbol; /* the symbol __GLOBAL_OFFSET_TABLE_ */ +symbol *dynamic_symbol; /* the symbol __DYNAMIC */ + +void +symtab_init (relocatable_output) +int relocatable_output; +{ + /* + * Put linker reserved symbols into symbol table. + */ +#ifndef nounderscore +#define ETEXT_SYM "_etext" +#define EDATA_SYM "_edata" +#define END_SYM "_end" +#define DYN_SYM "__DYNAMIC" +#define GOT_SYM "__GLOBAL_OFFSET_TABLE_" +#else +#define ETEXT_SYM "etext" +#define EDATA_SYM "edata" +#define END_SYM "end" +#define DYN_SYM "_DYNAMIC" +#define GOT_SYM "_GLOBAL_OFFSET_TABLE_" +#endif + + dynamic_symbol = getsym (DYN_SYM); + dynamic_symbol->defined = relocatable_output?N_UNDF:(N_DATA | N_EXT); + + got_symbol = getsym (GOT_SYM); + got_symbol->defined = N_DATA | N_EXT; + + if (relocatable_output) + return; + + etext_symbol = getsym (ETEXT_SYM); + edata_symbol = getsym (EDATA_SYM); + end_symbol = getsym (END_SYM); + + etext_symbol->defined = N_TEXT | N_EXT; + edata_symbol->defined = N_DATA | N_EXT; + end_symbol->defined = N_BSS | N_EXT; + + etext_symbol->flags |= GS_REFERENCED; + edata_symbol->flags |= GS_REFERENCED; + end_symbol->flags |= GS_REFERENCED; +} + +/* Compute the hash code for symbol name KEY. */ + +int +hash_string (key) + char *key; +{ + register char *cp; + register int k; + + cp = key; + k = 0; + while (*cp) + k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; + + return k; +} + +/* Get the symbol table entry for the global symbol named KEY. + Create one if there is none. */ + +symbol * +getsym(key) + char *key; +{ + register int hashval; + register symbol *bp; + + /* Determine the proper bucket. */ + hashval = hash_string (key) % SYMTABSIZE; + + /* Search the bucket. */ + for (bp = symtab[hashval]; bp; bp = bp->link) + if (! strcmp (key, bp->name)) + return bp; + + /* Nothing was found; create a new symbol table entry. */ + bp = (symbol *) xmalloc (sizeof (symbol)); + bp->name = (char *) xmalloc (strlen (key) + 1); + strcpy (bp->name, key); + bp->refs = 0; + bp->defined = 0; + bp->value = 0; + bp->common_size = 0; + bp->warning = 0; + bp->undef_refs = 0; + bp->mult_defs = 0; + bp->alias = 0; + bp->setv_count = 0; + bp->symbolnum = 0; + bp->rrs_symbolnum = 0; + + bp->size = 0; + bp->aux = 0; + bp->sorefs = 0; + bp->so_defined = 0; + bp->def_nlist = 0; + bp->jmpslot_offset = -1; + bp->gotslot_offset = -1; + bp->flags = 0; + + /* Add the entry to the bucket. */ + bp->link = symtab[hashval]; + symtab[hashval] = bp; + + ++num_hash_tab_syms; + + return bp; +} + +/* Like `getsym' but return 0 if the symbol is not already known. */ + +symbol * +getsym_soft (key) + char *key; +{ + register int hashval; + register symbol *bp; + + /* Determine which bucket. */ + + hashval = hash_string (key) % SYMTABSIZE; + + /* Search the bucket. */ + + for (bp = symtab[hashval]; bp; bp = bp->link) + if (! strcmp (key, bp->name)) + return bp; + + return 0; +} |
