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