1#include <assert.h>2#include <errno.h>3#include <stdio.h>4#include <stdlib.h>5#include <string.h>67#include <scc/mach.h>8#include <scc/scc.h>910#include "ld.h"1112#define NR_SYMBOL 1281314/*15 * struct symtab has a Symbol as first field because16 * the code is going to cast from the symbols to the tab.17 */18struct symtab {19 Symbol sym;20 Obj *where;21 struct symtab *hash;22 struct symtab *next, *prev;23};2425static struct symtab *symtab[NR_SYMBOL];26static struct symtab undef = {.next = &undef, .prev = &undef};27static struct symtab def = {.next = &def, .prev = &def};28static struct symtab common = {.next = &common, .prev = &common};2930static Symbol *31unlinksym(Symbol *sym)32{33 struct symtab *sp = (struct symtab *) sym;3435 sp->next->prev = sp->prev;36 sp->prev->next = sp->next;3738 return sym;39}4041static Symbol *42linksym(struct symtab *lst, Symbol *sym)43{44 struct symtab *sp = (struct symtab *) sym;4546 sp->next = lst;47 sp->prev = lst->prev;48 lst->prev->next = sp;49 lst->prev = sp;5051 return sym;52}5354int55hasref(char *name)56{57 unsigned h;58 struct symtab *sp;5960 h = genhash(name) % NR_SYMBOL;61 for (sp = symtab[h]; sp; sp = sp->hash) {62 if (!strcmp(name, sp->sym.name))63 return sp->sym.type == 'U';64 }65 return 0;66}6768Symbol *69lookupsym(char *name)70{71 unsigned h;72 size_t len;73 char *s;74 Symbol *sym;75 struct symtab *sp;7677 h = genhash(name) % NR_SYMBOL;78 for (sp = symtab[h]; sp; sp = sp->hash) {79 if (!strcmp(name, sp->sym.name))80 return &sp->sym;81 }8283 len = strlen(name) + 1;84 s = malloc(len);85 sp = malloc(sizeof(*sp));86 if (!s || !sp) {87 error(strerror(errno));88 exit(EXIT_FAILURE);89 }9091 sym = &sp->sym;92 sym->name = memcpy(s, name, len);93 sym->value = 0;94 sym->size = 0;95 sym->index = 0;96 sym->type = 'U';97 sp->where = NULL;98 sp->hash = symtab[h];99 symtab[h] = sp;100101 return linksym(&undef, sym);102}103104105int106moreundef(void)107{108 return undef.next != &undef;109}110111void112listundef(void)113{114 struct symtab *sp;115116 for (sp = undef.next; sp != &undef; sp = sp->next)117 error("ld: symbol '%s' not defined", sp->sym.name);118}119120Symbol *121define(Symbol *osym, Obj *obj)122{123 struct symtab *lst;124 Symbol *sym = lookupsym(osym->name);125 struct symtab *sp = (struct symtab *) sym;126127 assert(osym->type != 'U');128 sp->where = obj;129130 switch (sym->type) {131 case 'U':132 sym->value = osym->value;133 sym->size = osym->size;134 lst = (osym->type == 'C') ? &common : &def;135 linksym(lst, unlinksym(sym));136 break;137 case 'C':138 if (osym->type != 'C') {139 sym->size = osym->size;140 sym->value = osym->size;141 linksym(&def, unlinksym(sym));142 } else if (sym->size < osym->size) {143 sym->value = osym->value;144 sym->size = osym->size;145 }146 break;147 defaul:148 error("%s: symbol redefined", sym->name);149 break;150 }151152 return sym;153}154155#ifndef NDEBUG156void157debugsym(void)158{159 struct symtab **spp, *sp;160 Symbol*sym;161162 fputs("Symbols:\n", stderr);163 for (spp = symtab; spp < &symtab[NR_SYMBOL]; spp++) {164 for (sp = *spp; sp; sp = sp->hash) {165 sym = &sp->sym;166 fprintf(stderr,167 "sym: %s (%#llx)\n",168 sym->name,169 sym->value);170 }171 }172}173#endif