1 /* Copyright (C) 1991 Free Software Foundation, Inc.
3 This file is part of GLD, the Gnu Linker.
5 GLD is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 1, or (at your option)
10 GLD is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GLD; see the file COPYING. If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 Written by Steve Chamberlain steve@cygnus.com
28 All symbol handling for the linker
41 extern bfd
*output_bfd
;
42 /* Head and tail of global symbol table chronological list */
44 ldsym_type
*symbol_head
= (ldsym_type
*)NULL
;
45 ldsym_type
**symbol_tail_ptr
= &symbol_head
;
48 incremented for each symbol in the ldsym_type table
49 no matter what flavour it is
51 unsigned int global_symbol_count
;
55 extern boolean option_longmap
;
59 static ldsym_type
*global_symbol_hash_table
[TABSIZE
];
61 /* Compute the hash code for symbol name KEY. */
73 k
= (((k
<< 1) + (k
>> 14)) ^ (*cp
++)) & 0x3fff;
78 /* Get the symbol table entry for the global symbol named KEY.
79 Create one if there is none. */
85 register ldsym_type
*bp
;
87 /* Determine the proper bucket. */
89 hashval
= hash_string (key
) % TABSIZE
;
91 /* Search the bucket. */
93 for (bp
= global_symbol_hash_table
[hashval
]; bp
; bp
= bp
->link
)
94 if (! strcmp (key
, bp
->name
))
97 /* Nothing was found; create a new symbol table entry. */
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
);
109 /* Add the entry to the bucket. */
111 bp
->link
= global_symbol_hash_table
[hashval
];
112 global_symbol_hash_table
[hashval
] = bp
;
114 /* Keep the chronological list up to date too */
115 *symbol_tail_ptr
= bp
;
116 symbol_tail_ptr
= &bp
->next
;
118 global_symbol_count
++;
123 /* Like `ldsym_get' but return 0 if the symbol is not already known. */
129 register int hashval
;
130 register ldsym_type
*bp
;
132 /* Determine which bucket. */
134 hashval
= hash_string (key
) % TABSIZE
;
136 /* Search the bucket. */
138 for (bp
= global_symbol_hash_table
[hashval
]; bp
; bp
= bp
->link
)
139 if (! strcmp (key
, bp
->name
))
150 list_file_locals (entry
)
151 lang_input_statement_type
*entry
;
154 fprintf (stderr
, "\nLocal symbols of ");
156 fprintf (stderr
, ":\n\n");
157 if (entry
->asymbols
) {
158 for (q
= entry
->asymbols
; *q
; 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
);
172 lang_input_statement_type
*f
;
174 fprintf (stderr
, " %s", f
->filename
);
175 fprintf (stderr
, " ");
176 if (f
->just_syms_flag
)
178 fprintf (stderr
, " symbols only\n");
183 if (option_longmap
) {
184 for (s
= f
->the_bfd
->sections
;
185 s
!= (asection
*)NULL
;
187 fprintf (stderr
, "%08lx %08x 2**%2ud %s\n",
189 (unsigned)s
->size
, s
->alignment_power
, s
->name
);
193 for (s
= f
->the_bfd
->sections
;
194 s
!= (asection
*)NULL
;
196 fprintf (stderr
, "%s %lx(%x) ",
201 fprintf (stderr
, "hex \n");
207 ldsym_print_symbol_table ()
209 fprintf (stderr
, "\nFiles:\n\n");
211 lang_for_each_file(print_file_stuff
);
213 fprintf (stderr
, "\nGlobal symbols:\n\n");
215 register ldsym_type
*sp
;
217 for (sp
= symbol_head
; sp
; sp
= sp
->next
)
221 asymbol
*defsym
= *(sp
->sdefs_chain
);
222 asection
*defsec
= bfd_get_section(defsym
);
223 fprintf(stderr
,"%08lx ",defsym
->value
);
226 fprintf(stderr
,"%08lx ",defsym
->value
+defsec
->vma
);
229 bfd_section_name(output_bfd
,
235 fprintf(stderr
," .......");
240 fprintf(stderr
,"undefined");
244 if (sp
->scoms_chain
) {
245 fprintf(stderr
, " common size %5lu %s",
246 (*(sp
->scoms_chain
))->value
, sp
->name
);
248 if (sp
->sdefs_chain
) {
249 fprintf(stderr
, " symbol def %08lx %s",
250 (*(sp
->sdefs_chain
))->value
,
254 fprintf(stderr
, " undefined %s",
257 fprintf(stderr
, "\n");
261 lang_for_each_file(list_file_locals
);
264 extern lang_output_section_statement_type
*create_object_symbols
;
267 write_file_locals(output_buffer
)
268 asymbol
**output_buffer
;
270 LANG_FOR_EACH_INPUT_STATEMENT(entry
)
272 /* Run trough the symbols and work out what to do with them */
275 /* Add one for the filename symbol if needed */
276 if (create_object_symbols
277 != (lang_output_section_statement_type
*)NULL
) {
279 for (s
= entry
->the_bfd
->sections
;
280 s
!= (asection
*)NULL
;
282 if (s
->output_section
== create_object_symbols
->bfd_section
) {
283 /* Add symbol to this section */
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 */
289 /* The value is the start of this section in the output file*/
291 newsym
->flags
= BSF_LOCAL
;
293 *output_buffer
++ = newsym
;
298 for (i
= 0; i
< entry
->symbol_count
; i
++)
300 asymbol
*p
= entry
->asymbols
[i
];
302 if (flag_is_global(p
->flags
) || flag_is_absolute(p
->flags
))
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
;
314 if (flag_is_ordinary_local(p
->flags
))
316 if (discard_locals
== DISCARD_ALL
)
318 else if (discard_locals
== DISCARD_L
&&
319 (p
->name
[0] == lprefix
))
321 else if (p
->flags
== BSF_WARNING
)
324 { *output_buffer
++ = p
; }
326 else if (flag_is_debugger(p
->flags
))
328 /* Only keep the debugger symbols if no stripping required */
329 if (strip_symbols
== STRIP_NONE
) {
330 *output_buffer
++ = p
;
333 else if (flag_is_undefined(p
->flags
))
334 { /* This must be global */
336 else if (flag_is_common(p
->flags
)) {
337 /* And so must this */
339 else if (p
->flags
& BSF_CTOR
) {
351 return output_buffer
;
356 write_file_globals(symbol_table
)
357 asymbol
**symbol_table
;
361 if (sp
->sdefs_chain
!= (asymbol
**)NULL
) {
362 asymbol
*bufp
= (*(sp
->sdefs_chain
));
364 if ((bufp
->flags
& BSF_KEEP
) ==0) {
365 ASSERT(bufp
!= (asymbol
*)NULL
);
367 bufp
->name
= sp
->name
;
369 if (sp
->scoms_chain
!= (asymbol
**)NULL
)
373 defined as common but not allocated, this happens
374 only with -r and not -d, write out a common
377 bufp
= *(sp
->scoms_chain
);
379 *symbol_table
++ = bufp
;
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
;
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
;
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
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)
415 extern unsigned int total_files_seen
;
416 extern unsigned int total_symbols_seen
;
418 asymbol
** symbol_table
= (asymbol
**)
419 ldmalloc ((size_t)(global_symbol_count
+
421 total_symbols_seen
+ 1) * sizeof (asymbol
*));
422 asymbol
** tablep
= write_file_locals(symbol_table
);
424 tablep
= write_file_globals(tablep
);
426 *tablep
= (asymbol
*)NULL
;
427 bfd_set_symtab(output_bfd
, symbol_table
, (unsigned)( tablep
- symbol_table
));
432 return true if the supplied symbol name is not in the
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;