Initial import from FreeBSD RELENG_4:
[dragonfly.git] / gnu / usr.bin / ld / symbol.c
1 /*-
2  * This code is derived from software copyrighted by the Free Software
3  * Foundation.
4  *
5  * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6  *
7  * Modified 1993 by Paul Kranenburg, Erasmus University
8  */
9
10 /* Derived from ld.c: "@(#)ld.c 6.10 (Berkeley) 5/22/91"; */
11
12 /* Linker `ld' for GNU
13    Copyright (C) 1988 Free Software Foundation, Inc.
14
15    This program is free software; you can redistribute it and/or modify
16    it under the terms of the GNU General Public License as published by
17    the Free Software Foundation; either version 1, or (at your option)
18    any later version.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23    GNU General Public License for more details.
24
25    You should have received a copy of the GNU General Public License
26    along with this program; if not, write to the Free Software
27    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
28
29 /* Written by Richard Stallman with some help from Eric Albert.
30    Set, indirect, and warning symbol features added by Randy Smith. */
31
32 /*
33  * symbol table routines
34  * $FreeBSD: src/gnu/usr.bin/ld/symbol.c,v 1.10 1999/08/27 23:36:02 peter Exp $
35  */
36
37 /* Create the symbol table entries for `etext', `edata' and `end'.  */
38
39 #include <sys/param.h>
40 #include <sys/types.h>
41 #include <fcntl.h>
42 #include <a.out.h>
43 #include <stab.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "ld.h"
49 #include "dynamic.h"
50
51 symbol  *symtab[SYMTABSIZE];    /* The symbol table. */
52 int     num_hash_tab_syms;      /* Number of symbols in symbol hash table. */
53
54 symbol  *edata_symbol;          /* the symbol _edata */
55 symbol  *etext_symbol;          /* the symbol _etext */
56 symbol  *end_symbol;            /* the symbol _end */
57 symbol  *got_symbol;            /* the symbol __GLOBAL_OFFSET_TABLE_ */
58 symbol  *dynamic_symbol;        /* the symbol __DYNAMIC */
59
60 void
61 symtab_init(relocatable_output)
62         int     relocatable_output;
63 {
64         /*
65          * Put linker reserved symbols into symbol table.
66          */
67 #ifndef nounderscore
68 #define ETEXT_SYM       "_etext"
69 #define EDATA_SYM       "_edata"
70 #define END_SYM         "_end"
71 #define DYN_SYM         "__DYNAMIC"
72 #define GOT_SYM         "__GLOBAL_OFFSET_TABLE_"
73 #else
74 #define ETEXT_SYM       "etext"
75 #define EDATA_SYM       "edata"
76 #define END_SYM         "end"
77 #define DYN_SYM         "_DYNAMIC"
78 #define GOT_SYM         "_GLOBAL_OFFSET_TABLE_"
79 #endif
80
81         dynamic_symbol = getsym(DYN_SYM);
82         dynamic_symbol->defined = relocatable_output?N_UNDF:(N_DATA | N_EXT);
83
84         got_symbol = getsym(GOT_SYM);
85         got_symbol->defined = N_DATA | N_EXT;
86
87         if (relocatable_output)
88                 return;
89
90         etext_symbol = getsym(ETEXT_SYM);
91         edata_symbol = getsym(EDATA_SYM);
92         end_symbol = getsym(END_SYM);
93
94         etext_symbol->defined = N_TEXT | N_EXT;
95         edata_symbol->defined = N_DATA | N_EXT;
96         end_symbol->defined = N_BSS | N_EXT;
97
98         etext_symbol->flags |= GS_REFERENCED;
99         edata_symbol->flags |= GS_REFERENCED;
100         end_symbol->flags |= GS_REFERENCED;
101 }
102
103 /*
104  * Compute the hash code for symbol name KEY.
105  */
106
107 int
108 hash_string (key)
109      char *key;
110 {
111         register char *cp;
112         register int k;
113
114         cp = key;
115         k = 0;
116         while (*cp)
117                 k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
118
119         return k;
120 }
121
122 /*
123  * Get the symbol table entry for the global symbol named KEY.
124  * Create one if there is none.
125  */
126
127 symbol *
128 getsym(key)
129         char *key;
130 {
131         register int hashval;
132         register symbol *bp;
133
134         /* Determine the proper bucket.  */
135         hashval = hash_string(key) % SYMTABSIZE;
136
137         /* Search the bucket.  */
138         for (bp = symtab[hashval]; bp; bp = bp->link)
139                 if (strcmp(key, bp->name) == 0)
140                         return bp;
141
142         /* Nothing was found; create a new symbol table entry.  */
143         bp = (symbol *)xmalloc(sizeof(symbol));
144         bp->name = (char *)xmalloc(strlen(key) + 1);
145         strcpy (bp->name, key);
146         bp->refs = 0;
147         bp->defined = 0;
148         bp->value = 0;
149         bp->common_size = 0;
150         bp->warning = 0;
151         bp->undef_refs = 0;
152         bp->mult_defs = 0;
153         bp->alias = 0;
154         bp->setv_count = 0;
155         bp->symbolnum = 0;
156         bp->rrs_symbolnum = 0;
157
158         bp->size = 0;
159         bp->aux = 0;
160         bp->sorefs = 0;
161         bp->so_defined = 0;
162         bp->def_lsp = 0;
163         bp->jmpslot_offset = -1;
164         bp->gotslot_offset = -1;
165         bp->flags = 0;
166
167         /* Add the entry to the bucket.  */
168         bp->link = symtab[hashval];
169         symtab[hashval] = bp;
170
171         ++num_hash_tab_syms;
172
173         return bp;
174 }
175
176 /* Like `getsym' but return 0 if the symbol is not already known.  */
177
178 symbol *
179 getsym_soft (key)
180         char *key;
181 {
182         register int hashval;
183         register symbol *bp;
184
185         /* Determine which bucket. */
186         hashval = hash_string(key) % SYMTABSIZE;
187
188         /* Search the bucket. */
189         for (bp = symtab[hashval]; bp; bp = bp->link)
190                 if (strcmp(key, bp->name) == 0)
191                         return bp;
192
193         return 0;
194 }