Checkpoint before a merge
[deliverable/binutils-gdb.git] / ld / ldsym.c
CommitLineData
2fa0b342
DHW
1/* Copyright (C) 1991 Free Software Foundation, Inc.
2
3This file is part of GLD, the Gnu Linker.
4
5GLD is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 1, or (at your option)
8any later version.
9
10GLD is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with GLD; see the file COPYING. If not, write to
17the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19/*
20 * $Id$
21 *
2fa0b342
DHW
22 *
23*/
24
25/*
26 Written by Steve Chamberlain steve@cygnus.com
27
28 All symbol handling for the linker
29 */
30
31
32#include "sysdep.h"
33#include "bfd.h"
34
35#include "ld.h"
36#include "ldsym.h"
37#include "ldmisc.h"
38#include "ldlang.h"
39/* IMPORT */
40
41extern bfd *output_bfd;
42/* Head and tail of global symbol table chronological list */
43
44ldsym_type *symbol_head = (ldsym_type *)NULL;
45ldsym_type **symbol_tail_ptr = &symbol_head;
46
47/*
48 incremented for each symbol in the ldsym_type table
49 no matter what flavour it is
50*/
51unsigned int global_symbol_count;
52
53/* IMPORTS */
54
55extern boolean option_longmap ;
56
57/* LOCALS */
58#define TABSIZE 1009
59static ldsym_type *global_symbol_hash_table[TABSIZE];
60
61/* Compute the hash code for symbol name KEY. */
62
63int
64hash_string (key)
65 char *key;
66{
67 register char *cp;
68 register int k;
69
70 cp = key;
71 k = 0;
72 while (*cp)
73 k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
74
75 return k;
76}
77
78/* Get the symbol table entry for the global symbol named KEY.
79 Create one if there is none. */
80ldsym_type *
81ldsym_get (key)
82 char *key;
83{
84 register int hashval;
85 register ldsym_type *bp;
86
87 /* Determine the proper bucket. */
88
89 hashval = hash_string (key) % TABSIZE;
90
91 /* Search the bucket. */
92
93 for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
94 if (! strcmp (key, bp->name))
95 return bp;
96
97 /* Nothing was found; create a new symbol table entry. */
98
99 bp = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
100 bp->srefs_chain = (asymbol **)NULL;
101 bp->sdefs_chain = (asymbol **)NULL;
102 bp->scoms_chain = (asymbol **)NULL;
103 bp->name = (char *) ldmalloc (strlen (key) + 1);
104 strcpy (bp->name, key);
105
106
107
108
109 /* Add the entry to the bucket. */
110
111 bp->link = global_symbol_hash_table[hashval];
112 global_symbol_hash_table[hashval] = bp;
113
114 /* Keep the chronological list up to date too */
115 *symbol_tail_ptr = bp;
116 symbol_tail_ptr = &bp->next;
117 bp->next = 0;
118 global_symbol_count++;
119
120 return bp;
121}
122
123/* Like `ldsym_get' but return 0 if the symbol is not already known. */
124
125ldsym_type *
126ldsym_get_soft (key)
127 char *key;
128{
129 register int hashval;
130 register ldsym_type *bp;
131
132 /* Determine which bucket. */
133
134 hashval = hash_string (key) % TABSIZE;
135
136 /* Search the bucket. */
137
138 for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
139 if (! strcmp (key, bp->name))
140 return bp;
141
142 return 0;
143}
144
145
146
147
148
149static void
150list_file_locals (entry)
151lang_input_statement_type *entry;
152{
153 asymbol **q;
154 fprintf (stderr, "\nLocal symbols of ");
155 info("%I", entry);
156 fprintf (stderr, ":\n\n");
157 if (entry->asymbols) {
158 for (q = entry->asymbols; *q; q++)
159 {
160 asymbol *p = *q;
161 /* If this is a definition,
162 update it if necessary by this file's start address. */
163 if (p->flags & BSF_LOCAL)
164 info(" %V %s\n",p->value, p->name);
165 }
166 }
167}
168
169
170static void
171print_file_stuff(f)
172lang_input_statement_type *f;
173{
174 fprintf (stderr, " %s", f->filename);
175 fprintf (stderr, " ");
176 if (f->just_syms_flag)
177 {
178 fprintf (stderr, " symbols only\n");
179 }
180 else
181 {
182 asection *s;
183 if (option_longmap) {
184 for (s = f->the_bfd->sections;
185 s != (asection *)NULL;
186 s = s->next) {
187 fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
188 s->output_offset,
189 (unsigned)s->size, s->alignment_power, s->name);
190 }
191 }
192 else {
193 for (s = f->the_bfd->sections;
194 s != (asection *)NULL;
195 s = s->next) {
196 fprintf (stderr, "%s %lx(%x) ",
197 s->name,
198 s->output_offset,
199 (unsigned) s->size);
200 }
201 fprintf (stderr, "hex \n");
202 }
203 }
204}
205
206void
207ldsym_print_symbol_table ()
208{
209 fprintf (stderr, "\nFiles:\n\n");
210
211 lang_for_each_file(print_file_stuff);
212
213 fprintf (stderr, "\nGlobal symbols:\n\n");
214 {
215 register ldsym_type *sp;
216
217 for (sp = symbol_head; sp; sp = sp->next)
218 {
219 if (sp->sdefs_chain)
220 {
221 asymbol *defsym = *(sp->sdefs_chain);
222 asection *defsec = bfd_get_section(defsym);
223 fprintf(stderr,"%08lx ",defsym->value);
224 if (defsec)
225 {
226 fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
227 fprintf(stderr,
228 "%7s",
229 bfd_section_name(output_bfd,
230 defsec));
231
232 }
233 else
234 {
235 fprintf(stderr," .......");
236 }
237
238 }
239 else {
240 fprintf(stderr,"undefined");
241 }
242
243
244 if (sp->scoms_chain) {
245 fprintf(stderr, " common size %5lu %s",
246 (*(sp->scoms_chain))->value, sp->name);
247 }
248 if (sp->sdefs_chain) {
249 fprintf(stderr, " symbol def %08lx %s",
250 (*(sp->sdefs_chain))->value,
251 sp->name);
252 }
253 else {
254 fprintf(stderr, " undefined %s",
255 sp->name);
256 }
257 fprintf(stderr, "\n");
258
259 }
260 }
261 lang_for_each_file(list_file_locals);
262}
263
264extern lang_output_section_statement_type *create_object_symbols;
265extern char lprefix;
266static asymbol **
267write_file_locals(output_buffer)
268asymbol **output_buffer;
269{
270LANG_FOR_EACH_INPUT_STATEMENT(entry)
271 {
272 /* Run trough the symbols and work out what to do with them */
273 unsigned int i;
274
275 /* Add one for the filename symbol if needed */
276 if (create_object_symbols
277 != (lang_output_section_statement_type *)NULL) {
278 asection *s;
279 for (s = entry->the_bfd->sections;
280 s != (asection *)NULL;
281 s = s->next) {
282 if (s->output_section == create_object_symbols->bfd_section) {
283 /* Add symbol to this section */
284 asymbol * newsym =
285 (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
286 newsym->name = entry->local_sym_name;
287 /* The symbol belongs to the output file's text section */
288
289 /* The value is the start of this section in the output file*/
290 newsym->value = 0;
291 newsym->flags = BSF_LOCAL;
292 newsym->section = s;
293 *output_buffer++ = newsym;
294 break;
295 }
296 }
297 }
298 for (i = 0; i < entry->symbol_count; i++)
299 {
300 asymbol *p = entry->asymbols[i];
301
302 if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
303 {
304 /* We are only interested in outputting
305 globals at this stage in special circumstances */
306 if (p->the_bfd == entry->the_bfd
307 && flag_is_not_at_end(p->flags)) {
308 /* And this is one of them */
309 *(output_buffer++) = p;
310 p->flags |= BSF_KEEP;
311 }
312 }
313 else {
314 if (flag_is_ordinary_local(p->flags))
315 {
316 if (discard_locals == DISCARD_ALL)
317 { }
318 else if (discard_locals == DISCARD_L &&
319 (p->name[0] == lprefix))
320 { }
321 else if (p->flags == BSF_WARNING)
322 { }
323 else
324 { *output_buffer++ = p; }
325 }
326 else if (flag_is_debugger(p->flags))
327 {
328 /* Only keep the debugger symbols if no stripping required */
329 if (strip_symbols == STRIP_NONE) {
330 *output_buffer++ = p;
331 }
332 }
333 else if (flag_is_undefined(p->flags))
334 { /* This must be global */
335 }
336 else if (flag_is_common(p->flags)) {
337 /* And so must this */
338 }
339 else if (p->flags & BSF_CTOR) {
340 /* Throw it away */
341 }
342else
343 {
344 FAIL();
345 }
346 }
347 }
348
349
350 }
351 return output_buffer;
352}
353
354
355static asymbol **
356write_file_globals(symbol_table)
357asymbol **symbol_table;
358{
359 FOR_EACH_LDSYM(sp)
360 {
361 if (sp->sdefs_chain != (asymbol **)NULL) {
362 asymbol *bufp = (*(sp->sdefs_chain));
363
364 if ((bufp->flags & BSF_KEEP) ==0) {
365 ASSERT(bufp != (asymbol *)NULL);
366
367 bufp->name = sp->name;
368
369 if (sp->scoms_chain != (asymbol **)NULL)
370
371 {
372 /*
373 defined as common but not allocated, this happens
374 only with -r and not -d, write out a common
375 definition
376 */
377 bufp = *(sp->scoms_chain);
378 }
379 *symbol_table++ = bufp;
380 }
381 }
382 else if (sp->scoms_chain != (asymbol **)NULL) {
383 /* This symbol is a common - just output */
384 asymbol *bufp = (*(sp->scoms_chain));
385 *symbol_table++ = bufp;
386 }
387 else if (sp->srefs_chain != (asymbol **)NULL) {
388 /* This symbol is undefined but has a reference */
389 asymbol *bufp = (*(sp->srefs_chain));
390 *symbol_table++ = bufp;
391 }
392 else {
393 /*
394 This symbol has neither defs nor refs, it must have come
395 from the command line, since noone has used it it has no
396 data attatched, so we'll ignore it
397 */
398 }
399 }
400 return symbol_table;
401}
402
403
404
405void
406ldsym_write()
407{
408 if (strip_symbols != STRIP_ALL) {
409 /* We know the maximum size of the symbol table -
410 it's the size of all the global symbols ever seen +
411 the size of all the symbols from all the files +
412 the number of files (for the per file symbols)
413 +1 (for the null at the end)
414 */
415 extern unsigned int total_files_seen;
416 extern unsigned int total_symbols_seen;
417
418 asymbol ** symbol_table = (asymbol **)
419 ldmalloc ((size_t)(global_symbol_count +
420 total_files_seen +
421 total_symbols_seen + 1) * sizeof (asymbol *));
422 asymbol ** tablep = write_file_locals(symbol_table);
423
424 tablep = write_file_globals(tablep);
425
426 *tablep = (asymbol *)NULL;
427 bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
428 }
429}
c660714f
SC
430
431/*
432return true if the supplied symbol name is not in the
433linker symbol table
434*/
435boolean
436ldsym_undefined(sym)
437char *sym;
438{
439 ldsym_type *from_table = ldsym_get_soft(sym);
440 if (from_table != (ldsym_type *)NULL) {
441 if (from_table->sdefs_chain != (asymbol **)NULL) return false;
442 }
443 return true;
444}
This page took 0.039238 seconds and 4 git commands to generate.