]>
Commit | Line | Data |
---|---|---|
2d1a2445 PB |
1 | /* All symbol handling for the linker |
2 | Copyright (C) 1991 Free Software Foundation, Inc. | |
3 | Written by Steve Chamberlain [email protected] | |
29f33467 | 4 | |
2fa0b342 DHW |
5 | This file is part of GLD, the Gnu Linker. |
6 | ||
2d1a2445 | 7 | This program is free software; you can redistribute it and/or modify |
2fa0b342 | 8 | it under the terms of the GNU General Public License as published by |
2d1a2445 PB |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. | |
2fa0b342 | 11 | |
2d1a2445 | 12 | This program is distributed in the hope that it will be useful, |
2fa0b342 DHW |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
2d1a2445 PB |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
2fa0b342 | 20 | |
29f33467 | 21 | /* |
1af27af8 SC |
22 | We keep a hash table of global symbols. Each entry in a hash table |
23 | is called an ldsym_type. Each has three chains; a pointer to a | |
24 | chain of definitions for the symbol (hopefully one long), a pointer | |
25 | to a chain of references to the symbol, and a pointer to a chain of | |
26 | common symbols. Each pointer points into the canonical symbol table | |
32846f9c | 27 | provided by bfd, each one of which points to an asymbol. During |
1af27af8 SC |
28 | linkage, the linker uses the udata field to point to the next entry |
29 | in a canonical table.... | |
30 | ||
31 | ||
32 | ld_sym | |
33 | | | | |
34 | +----------+ +----------+ | |
35 | | defs | a canonical symbol table | |
36 | +----------+ +----------+ | |
37 | | refs | -----> | one entry| -----> asymbol | |
38 | +----------+ +----------+ | | | |
39 | | coms | | | +---------+ | |
40 | +----------+ +----------+ | udata |-----> another canonical symbol | |
29f33467 | 41 | +---------+ |
1af27af8 SC |
42 | |
43 | ||
44 | ||
45 | It is very simple to make all the symbol pointers point to the same | |
46 | definition - just run down the chain and make the asymbols pointers | |
47 | within the canonical table point to the asymbol attacthed to the | |
48 | definition of the symbol. | |
49 | ||
50 | */ | |
51 | ||
2fa0b342 | 52 | #include "bfd.h" |
f177a611 | 53 | #include "sysdep.h" |
2fa0b342 DHW |
54 | |
55 | #include "ld.h" | |
56 | #include "ldsym.h" | |
57 | #include "ldmisc.h" | |
58 | #include "ldlang.h" | |
59 | /* IMPORT */ | |
0b5995da | 60 | extern int symbol_truncate; |
2fa0b342 | 61 | extern bfd *output_bfd; |
d646b568 SC |
62 | extern strip_symbols_type strip_symbols; |
63 | extern discard_locals_type discard_locals; | |
2fa0b342 DHW |
64 | /* Head and tail of global symbol table chronological list */ |
65 | ||
29f33467 | 66 | ldsym_type *symbol_head = (ldsym_type *) NULL; |
2fa0b342 | 67 | ldsym_type **symbol_tail_ptr = &symbol_head; |
f3b36ecb KR |
68 | CONST char *keepsyms_file; |
69 | int kept_syms; | |
2fa0b342 | 70 | |
6fd50a20 SC |
71 | extern ld_config_type config; |
72 | ||
bfbdc80f SC |
73 | struct obstack global_sym_obstack; |
74 | #define obstack_chunk_alloc ldmalloc | |
75 | #define obstack_chunk_free free | |
76 | ||
2fa0b342 DHW |
77 | /* |
78 | incremented for each symbol in the ldsym_type table | |
29f33467 | 79 | no matter what flavour it is |
2fa0b342 DHW |
80 | */ |
81 | unsigned int global_symbol_count; | |
82 | ||
83 | /* IMPORTS */ | |
84 | ||
29f33467 | 85 | extern boolean option_longmap; |
2fa0b342 DHW |
86 | |
87 | /* LOCALS */ | |
88 | #define TABSIZE 1009 | |
89 | static ldsym_type *global_symbol_hash_table[TABSIZE]; | |
90 | ||
91 | /* Compute the hash code for symbol name KEY. */ | |
29f33467 | 92 | static |
1af27af8 | 93 | #ifdef __GNUC__ |
29f33467 | 94 | __inline |
1af27af8 | 95 | #endif |
b773e0e5 | 96 | |
2fa0b342 | 97 | int |
29f33467 SC |
98 | DEFUN (hash_string, (key), |
99 | CONST char *key) | |
2fa0b342 | 100 | { |
1af27af8 | 101 | register CONST char *cp; |
2fa0b342 | 102 | register int k; |
0b5995da | 103 | register int l = 0; |
2fa0b342 DHW |
104 | cp = key; |
105 | k = 0; | |
29f33467 SC |
106 | while (*cp && l < symbol_truncate) |
107 | { | |
108 | k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff; | |
109 | l++; | |
110 | } | |
2fa0b342 DHW |
111 | return k; |
112 | } | |
113 | ||
1af27af8 SC |
114 | static |
115 | #ifdef __GNUC__ | |
29f33467 | 116 | __inline |
04dd7520 | 117 | #endif |
29f33467 SC |
118 | ldsym_type * |
119 | DEFUN (search, (key, hashval), | |
120 | CONST char *key AND | |
121 | int hashval) | |
1af27af8 | 122 | { |
29f33467 | 123 | ldsym_type *bp; |
1af27af8 | 124 | for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link) |
29f33467 SC |
125 | if (!strncmp (key, bp->name, symbol_truncate)) |
126 | { | |
127 | if (bp->flags & SYM_INDIRECT) | |
128 | { | |
129 | /* Use the symbol we're aliased to instead */ | |
130 | return (ldsym_type *) (bp->sdefs_chain); | |
131 | } | |
132 | return bp; | |
1af27af8 | 133 | } |
1af27af8 SC |
134 | return 0; |
135 | } | |
136 | ||
137 | ||
2fa0b342 DHW |
138 | /* Get the symbol table entry for the global symbol named KEY. |
139 | Create one if there is none. */ | |
140 | ldsym_type * | |
29f33467 SC |
141 | DEFUN (ldsym_get, (key), |
142 | CONST char *key) | |
2fa0b342 DHW |
143 | { |
144 | register int hashval; | |
145 | register ldsym_type *bp; | |
146 | ||
147 | /* Determine the proper bucket. */ | |
148 | ||
149 | hashval = hash_string (key) % TABSIZE; | |
150 | ||
151 | /* Search the bucket. */ | |
29f33467 SC |
152 | bp = search (key, hashval); |
153 | if (bp) | |
154 | { | |
155 | return bp; | |
156 | } | |
2fa0b342 DHW |
157 | |
158 | /* Nothing was found; create a new symbol table entry. */ | |
159 | ||
29f33467 SC |
160 | bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type) (sizeof (ldsym_type))); |
161 | bp->srefs_chain = (asymbol **) NULL; | |
162 | bp->sdefs_chain = (asymbol **) NULL; | |
163 | bp->scoms_chain = (asymbol **) NULL; | |
164 | bp->name = obstack_copy (&global_sym_obstack, key, strlen (key) + 1); | |
81016051 | 165 | bp->flags = 0; |
2fa0b342 DHW |
166 | /* Add the entry to the bucket. */ |
167 | ||
168 | bp->link = global_symbol_hash_table[hashval]; | |
169 | global_symbol_hash_table[hashval] = bp; | |
170 | ||
171 | /* Keep the chronological list up to date too */ | |
172 | *symbol_tail_ptr = bp; | |
173 | symbol_tail_ptr = &bp->next; | |
174 | bp->next = 0; | |
175 | global_symbol_count++; | |
176 | ||
177 | return bp; | |
178 | } | |
179 | ||
180 | /* Like `ldsym_get' but return 0 if the symbol is not already known. */ | |
181 | ||
182 | ldsym_type * | |
29f33467 SC |
183 | DEFUN (ldsym_get_soft, (key), |
184 | CONST char *key) | |
2fa0b342 DHW |
185 | { |
186 | register int hashval; | |
2fa0b342 DHW |
187 | /* Determine which bucket. */ |
188 | ||
189 | hashval = hash_string (key) % TABSIZE; | |
190 | ||
191 | /* Search the bucket. */ | |
29f33467 | 192 | return search (key, hashval); |
2fa0b342 DHW |
193 | } |
194 | ||
f3b36ecb KR |
195 | static asymbol ** |
196 | process_keepsyms (table, size) | |
29f33467 | 197 | asymbol **table; |
f3b36ecb KR |
198 | int size; |
199 | { | |
200 | struct obstack obstack; | |
201 | char *start_of_obstack; | |
202 | FILE *ks_file = 0; | |
203 | asymbol **out = table; | |
204 | asymbol **end = table + size; | |
205 | asymbol **sym; | |
206 | ||
207 | if (!keepsyms_file || size == 0) | |
208 | return end; | |
209 | obstack_init (&obstack); | |
210 | obstack_alloc (&obstack, 1); | |
211 | obstack_finish (&obstack); | |
212 | start_of_obstack = obstack_alloc (&obstack, 1); | |
213 | ks_file = fopen (keepsyms_file, "r"); | |
214 | if (!ks_file) | |
215 | { | |
216 | info ("%X%P: can't open keep-symbols file `%s'\n", keepsyms_file); | |
217 | goto egress; | |
218 | } | |
219 | errno = 0; | |
2fa0b342 | 220 | |
f3b36ecb | 221 | #define KEEP(S) \ |
26483cc6 | 222 | do { asymbol **p = (S), *tmp = *out; *out = *p; *p = tmp; out++; } while (0) |
2fa0b342 | 223 | |
f3b36ecb KR |
224 | while (!feof (ks_file) && !ferror (ks_file)) |
225 | { | |
226 | int c; | |
227 | char *ptr; | |
228 | int found = 0; | |
2fa0b342 | 229 | |
f3b36ecb KR |
230 | obstack_free (&obstack, start_of_obstack); |
231 | do | |
232 | { | |
233 | c = getc (ks_file); | |
234 | if (c == '\n') | |
235 | c = 0; | |
236 | obstack_1grow (&obstack, c); | |
237 | } | |
238 | while (c > 0); | |
239 | if (c == EOF) | |
240 | { | |
241 | if (!feof (ks_file)) | |
242 | /* error occurred */ | |
243 | { | |
244 | info ("%X%P: error reading keep-symbols file `%s': %E\n", | |
245 | keepsyms_file); | |
246 | out = end; | |
247 | goto egress; | |
248 | } | |
249 | if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1) | |
250 | /* eof in middle of symbol */ | |
251 | { | |
252 | info ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n", | |
253 | keepsyms_file); | |
254 | out = end; | |
255 | goto egress; | |
256 | } | |
257 | /* All okay -- no incomplete lines, EOF reached. */ | |
258 | break; | |
259 | } | |
260 | ptr = obstack_next_free (&obstack) - 2; | |
261 | /* discard trailing trash */ | |
262 | while (*ptr == ' ' | |
263 | || *ptr == '\t') | |
264 | *ptr-- = 0; | |
265 | ptr = obstack_base (&obstack); | |
266 | for (sym = out; sym < end; sym++) | |
0b5995da | 267 | if (!strncmp ((*sym)->name, ptr, symbol_truncate)) |
f3b36ecb KR |
268 | { |
269 | KEEP (sym); | |
270 | found = 1; | |
271 | } | |
272 | if (!found) | |
273 | info ("%P: symbol `%s' (requested to be kept) not found\n", ptr); | |
274 | } | |
275 | /* It'd be slightly faster to move this pass above the previous one, | |
276 | but that'd mean any symbols preserved in this pass would generate | |
277 | warnings if they were also listed in the keepsyms file. */ | |
278 | for (sym = out; sym < end; sym++) | |
279 | { | |
280 | asymbol *s = *sym; | |
281 | if (s->section == &bfd_und_section | |
8a045e50 | 282 | || bfd_is_com_section (s->section) |
f3b36ecb KR |
283 | || s->flags & BSF_KEEP_G) |
284 | KEEP (sym); | |
285 | } | |
29f33467 | 286 | egress: |
f3b36ecb KR |
287 | obstack_free (&obstack, start_of_obstack); |
288 | if (ks_file) | |
289 | fclose (ks_file); | |
290 | return out; | |
291 | } | |
2fa0b342 DHW |
292 | |
293 | static void | |
294 | list_file_locals (entry) | |
29f33467 | 295 | lang_input_statement_type *entry; |
2fa0b342 DHW |
296 | { |
297 | asymbol **q; | |
6fd50a20 | 298 | fprintf (config.map_file, "\nLocal symbols of "); |
29f33467 | 299 | minfo ("%I", entry); |
6fd50a20 | 300 | fprintf (config.map_file, ":\n\n"); |
29f33467 SC |
301 | if (entry->asymbols) |
302 | { | |
303 | for (q = entry->asymbols; *q; q++) | |
304 | { | |
305 | asymbol *p = *q; | |
306 | /* If this is a definition, | |
2fa0b342 | 307 | update it if necessary by this file's start address. */ |
29f33467 SC |
308 | if (p->flags & BSF_LOCAL) |
309 | info (" %V %s\n", p->value, p->name); | |
310 | } | |
311 | } | |
2fa0b342 DHW |
312 | } |
313 | ||
314 | ||
315 | static void | |
29f33467 SC |
316 | DEFUN (print_file_stuff, (f), |
317 | lang_input_statement_type * f) | |
2fa0b342 | 318 | { |
29f33467 SC |
319 | fprintf (config.map_file, " %s\n", f->filename); |
320 | if (f->just_syms_flag) | |
321 | { | |
322 | fprintf (config.map_file, " symbols only\n"); | |
323 | } | |
324 | else | |
325 | { | |
326 | asection *s; | |
327 | if (true || option_longmap) | |
bfbdc80f | 328 | { |
29f33467 SC |
329 | for (s = f->the_bfd->sections; |
330 | s != (asection *) NULL; | |
331 | s = s->next) | |
332 | { | |
333 | print_address (s->output_offset); | |
334 | if (s->reloc_done) | |
335 | { | |
336 | fprintf (config.map_file, " %08x 2**%2ud %s\n", | |
337 | (unsigned) bfd_get_section_size_after_reloc (s), | |
338 | s->alignment_power, s->name); | |
339 | } | |
340 | ||
341 | else | |
342 | { | |
343 | fprintf (config.map_file, " %08x 2**%2ud %s\n", | |
344 | (unsigned) bfd_get_section_size_before_reloc (s), | |
345 | s->alignment_power, s->name); | |
346 | } | |
347 | } | |
bfbdc80f | 348 | } |
29f33467 | 349 | else |
bfbdc80f | 350 | { |
29f33467 SC |
351 | for (s = f->the_bfd->sections; |
352 | s != (asection *) NULL; | |
353 | s = s->next) | |
354 | { | |
355 | fprintf (config.map_file, "%s ", s->name); | |
356 | print_address (s->output_offset); | |
357 | fprintf (config.map_file, "(%x)", (unsigned) bfd_get_section_size_after_reloc (s)); | |
358 | } | |
359 | fprintf (config.map_file, "hex \n"); | |
bfbdc80f | 360 | } |
bfbdc80f | 361 | } |
6fd50a20 | 362 | fprintf (config.map_file, "\n"); |
2fa0b342 DHW |
363 | } |
364 | ||
365 | void | |
366 | ldsym_print_symbol_table () | |
367 | { | |
6fd50a20 | 368 | fprintf (config.map_file, "**FILES**\n\n"); |
2fa0b342 | 369 | |
29f33467 | 370 | lang_for_each_file (print_file_stuff); |
2fa0b342 | 371 | |
29f33467 SC |
372 | fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n"); |
373 | fprintf (config.map_file, "offset section offset symbol\n"); | |
2fa0b342 DHW |
374 | { |
375 | register ldsym_type *sp; | |
376 | ||
377 | for (sp = symbol_head; sp; sp = sp->next) | |
378 | { | |
29f33467 SC |
379 | if (sp->flags & SYM_INDIRECT) |
380 | { | |
381 | fprintf (config.map_file, "indirect %s to %s\n", | |
382 | sp->name, (((ldsym_type *) (sp->sdefs_chain))->name)); | |
d9c53949 | 383 | } |
29f33467 SC |
384 | else |
385 | { | |
386 | if (sp->sdefs_chain) | |
387 | { | |
388 | asymbol *defsym = *(sp->sdefs_chain); | |
389 | asection *defsec = bfd_get_section (defsym); | |
390 | print_address (defsym->value); | |
391 | if (defsec) | |
392 | { | |
393 | fprintf (config.map_file, " %-10s", | |
394 | bfd_section_name (output_bfd, | |
395 | defsec)); | |
396 | print_space (); | |
397 | print_address (defsym->value + defsec->vma); | |
398 | ||
399 | } | |
400 | else | |
401 | { | |
402 | fprintf (config.map_file, " ......."); | |
403 | } | |
404 | ||
405 | } | |
406 | ||
407 | ||
408 | if (sp->scoms_chain) | |
409 | { | |
410 | fprintf (config.map_file, "common "); | |
411 | print_address ((*(sp->scoms_chain))->value); | |
412 | fprintf (config.map_file, " %s ", sp->name); | |
413 | } | |
414 | else if (sp->sdefs_chain) | |
415 | { | |
416 | fprintf (config.map_file, " %s ", sp->name); | |
417 | } | |
418 | else | |
419 | { | |
420 | fprintf (config.map_file, "undefined "); | |
421 | fprintf (config.map_file, "%s ", sp->name); | |
422 | ||
423 | } | |
d9c53949 | 424 | } |
29f33467 | 425 | print_nl (); |
2fa0b342 DHW |
426 | |
427 | } | |
428 | } | |
29f33467 SC |
429 | if (option_longmap) |
430 | { | |
431 | lang_for_each_file (list_file_locals); | |
432 | } | |
2fa0b342 DHW |
433 | } |
434 | ||
435 | extern lang_output_section_statement_type *create_object_symbols; | |
436 | extern char lprefix; | |
437 | static asymbol ** | |
29f33467 SC |
438 | write_file_locals (output_buffer) |
439 | asymbol **output_buffer; | |
2fa0b342 | 440 | { |
29f33467 | 441 | LANG_FOR_EACH_INPUT_STATEMENT (entry) |
bfbdc80f SC |
442 | { |
443 | /* Run trough the symbols and work out what to do with them */ | |
444 | unsigned int i; | |
445 | ||
446 | /* Add one for the filename symbol if needed */ | |
29f33467 SC |
447 | if (create_object_symbols |
448 | != (lang_output_section_statement_type *) NULL) | |
449 | { | |
450 | asection *s; | |
451 | for (s = entry->the_bfd->sections; | |
452 | s != (asection *) NULL; | |
453 | s = s->next) | |
454 | { | |
455 | if (s->output_section == create_object_symbols->bfd_section) | |
456 | { | |
457 | /* Add symbol to this section */ | |
458 | asymbol *newsym = | |
459 | (asymbol *) bfd_make_empty_symbol (entry->the_bfd); | |
460 | newsym->name = entry->local_sym_name; | |
461 | /* The symbol belongs to the output file's text section */ | |
462 | ||
463 | /* The value is the start of this section in the output file*/ | |
464 | newsym->value = 0; | |
465 | /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as | |
f3b36ecb KR |
466 | "used by the linker" and I can't find any other code that |
467 | uses it. Should be a cleaner way of doing this (like an | |
468 | "application flags" field in the symbol structure?). */ | |
29f33467 SC |
469 | newsym->flags = BSF_LOCAL | BSF_KEEP_G; |
470 | newsym->section = s; | |
471 | *output_buffer++ = newsym; | |
472 | break; | |
473 | } | |
474 | } | |
bfbdc80f | 475 | } |
29f33467 | 476 | for (i = 0; i < entry->symbol_count; i++) |
bfbdc80f | 477 | { |
29f33467 SC |
478 | asymbol *p = entry->asymbols[i]; |
479 | /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */ | |
480 | ||
481 | if (p->section == 0) | |
482 | p->section = &bfd_abs_section; | |
483 | if (flag_is_global (p->flags)) | |
484 | { | |
485 | /* We are only interested in outputting | |
bfbdc80f | 486 | globals at this stage in special circumstances */ |
29f33467 SC |
487 | if (bfd_asymbol_bfd (p) == entry->the_bfd |
488 | && flag_is_not_at_end (p->flags)) | |
489 | { | |
490 | /* And this is one of them */ | |
491 | *(output_buffer++) = p; | |
492 | p->flags |= BSF_KEEP; | |
493 | } | |
571c4c26 | 494 | } |
bfbdc80f | 495 | else |
29f33467 SC |
496 | { |
497 | if (p->section == &bfd_ind_section) | |
498 | { | |
499 | /* Dont think about indirect symbols */ | |
500 | } | |
501 | else if (flag_is_debugger (p->flags)) | |
502 | { | |
503 | /* Only keep the debugger symbols if no stripping required */ | |
504 | if (strip_symbols == STRIP_NONE) | |
505 | { | |
506 | *output_buffer++ = p; | |
507 | } | |
508 | } | |
509 | else if (p->section == &bfd_und_section | |
510 | || bfd_is_com_section (p->section)) | |
511 | { | |
512 | /* These must be global. */ | |
513 | } | |
514 | else if (flag_is_ordinary_local (p->flags)) | |
515 | { | |
516 | if (discard_locals == DISCARD_ALL) | |
517 | { | |
518 | } | |
519 | else if (discard_locals == DISCARD_L && | |
520 | (p->name[0] == lprefix)) | |
521 | { | |
522 | } | |
523 | else if (p->flags == BSF_WARNING) | |
524 | { | |
525 | } | |
526 | else | |
527 | { | |
528 | *output_buffer++ = p; | |
529 | } | |
530 | } | |
531 | else if (p->flags & BSF_CTOR) | |
532 | { | |
533 | /* Throw it away */ | |
534 | } | |
535 | else | |
536 | { | |
537 | FAIL (); | |
538 | } | |
539 | } | |
bfbdc80f | 540 | } |
2fa0b342 DHW |
541 | |
542 | ||
bfbdc80f | 543 | } |
2fa0b342 DHW |
544 | return output_buffer; |
545 | } | |
546 | ||
547 | ||
548 | static asymbol ** | |
29f33467 SC |
549 | write_file_globals (symbol_table) |
550 | asymbol **symbol_table; | |
2fa0b342 | 551 | { |
29f33467 SC |
552 | FOR_EACH_LDSYM (sp) |
553 | { | |
554 | if (sp->flags & SYM_INDIRECT) | |
555 | { | |
556 | asymbol *bufp = (*(sp->srefs_chain)); | |
557 | ldsym_type *aliased_to = (ldsym_type *) (sp->sdefs_chain); | |
558 | if (aliased_to->sdefs_chain) | |
559 | { | |
560 | asymbol *p = aliased_to->sdefs_chain[0]; | |
561 | bufp->value = p->value; | |
562 | bufp->section = p->section; | |
563 | bufp->flags = p->flags; | |
564 | } | |
565 | else | |
566 | { | |
567 | bufp->value = 0; | |
568 | bufp->flags = 0; | |
569 | bufp->section = &bfd_und_section; | |
570 | } | |
571 | *symbol_table++ = bufp; | |
572 | } | |
573 | else if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **) NULL) | |
574 | { | |
2fa0b342 DHW |
575 | asymbol *bufp = (*(sp->sdefs_chain)); |
576 | ||
29f33467 SC |
577 | if ((bufp->flags & BSF_KEEP) == 0) |
578 | { | |
579 | ASSERT (bufp != (asymbol *) NULL); | |
2fa0b342 | 580 | |
29f33467 | 581 | bufp->name = sp->name; |
2fa0b342 | 582 | |
29f33467 | 583 | if (sp->scoms_chain != (asymbol **) NULL) |
2fa0b342 | 584 | |
29f33467 SC |
585 | { |
586 | /* | |
2fa0b342 DHW |
587 | defined as common but not allocated, this happens |
588 | only with -r and not -d, write out a common | |
589 | definition | |
590 | */ | |
29f33467 SC |
591 | bufp = *(sp->scoms_chain); |
592 | } | |
593 | *symbol_table++ = bufp; | |
594 | } | |
2fa0b342 | 595 | } |
29f33467 SC |
596 | else if (sp->scoms_chain != (asymbol **) NULL) |
597 | { | |
2fa0b342 DHW |
598 | /* This symbol is a common - just output */ |
599 | asymbol *bufp = (*(sp->scoms_chain)); | |
600 | *symbol_table++ = bufp; | |
601 | } | |
29f33467 SC |
602 | else if (sp->srefs_chain != (asymbol **) NULL) |
603 | { | |
2fa0b342 DHW |
604 | /* This symbol is undefined but has a reference */ |
605 | asymbol *bufp = (*(sp->srefs_chain)); | |
606 | *symbol_table++ = bufp; | |
607 | } | |
29f33467 SC |
608 | else |
609 | { | |
2fa0b342 DHW |
610 | /* |
611 | This symbol has neither defs nor refs, it must have come | |
612 | from the command line, since noone has used it it has no | |
29f33467 | 613 | data attatched, so we'll ignore it |
2fa0b342 DHW |
614 | */ |
615 | } | |
29f33467 | 616 | } |
2fa0b342 DHW |
617 | return symbol_table; |
618 | } | |
619 | ||
2fa0b342 | 620 | void |
29f33467 | 621 | ldsym_write () |
2fa0b342 | 622 | { |
f3b36ecb KR |
623 | if (keepsyms_file != 0 |
624 | && strip_symbols != STRIP_SOME) | |
625 | { | |
626 | info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n"); | |
627 | strip_symbols = STRIP_SOME; | |
628 | } | |
29f33467 SC |
629 | if (strip_symbols != STRIP_ALL) |
630 | { | |
631 | /* We know the maximum size of the symbol table - | |
2fa0b342 DHW |
632 | it's the size of all the global symbols ever seen + |
633 | the size of all the symbols from all the files + | |
634 | the number of files (for the per file symbols) | |
635 | +1 (for the null at the end) | |
636 | */ | |
29f33467 SC |
637 | extern unsigned int total_files_seen; |
638 | extern unsigned int total_symbols_seen; | |
2fa0b342 | 639 | |
29f33467 SC |
640 | asymbol **symbol_table = (asymbol **) |
641 | ldmalloc ((bfd_size_type) (global_symbol_count + | |
642 | total_files_seen + | |
643 | total_symbols_seen + 1) * sizeof (asymbol *)); | |
644 | asymbol **tablep = write_file_locals (symbol_table); | |
2fa0b342 | 645 | |
29f33467 SC |
646 | tablep = write_file_globals (tablep); |
647 | tablep = process_keepsyms (symbol_table, tablep - symbol_table); | |
2fa0b342 | 648 | |
29f33467 SC |
649 | *tablep = (asymbol *) NULL; |
650 | bfd_set_symtab (output_bfd, symbol_table, (unsigned) (tablep - symbol_table)); | |
651 | } | |
2fa0b342 | 652 | } |
c660714f SC |
653 | |
654 | /* | |
29f33467 | 655 | return true if the supplied symbol name is not in the |
c660714f SC |
656 | linker symbol table |
657 | */ | |
29f33467 SC |
658 | boolean |
659 | DEFUN (ldsym_undefined, (sym), | |
660 | CONST char *sym) | |
c660714f | 661 | { |
29f33467 SC |
662 | ldsym_type *from_table = ldsym_get_soft (sym); |
663 | if (from_table != (ldsym_type *) NULL) | |
664 | { | |
665 | if (from_table->sdefs_chain != (asymbol **) NULL) | |
666 | return false; | |
667 | } | |
c660714f SC |
668 | return true; |
669 | } | |
bfbdc80f SC |
670 | |
671 | void | |
29f33467 | 672 | DEFUN_VOID (ldsym_init) |
bfbdc80f | 673 | { |
29f33467 | 674 | obstack_begin (&global_sym_obstack, 20000); |
bfbdc80f | 675 | } |