-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* All symbol handling for the linker
+ Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
-GLD is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GLD is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
- * $Id$
- *
- * $Log$
- * Revision 1.1 1991/03/21 21:28:58 gumby
- * Initial revision
- *
- * Revision 1.1 1991/03/13 00:48:32 chrisb
- * Initial revision
- *
- * Revision 1.4 1991/03/10 09:31:36 rich
- * Modified Files:
- * Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
- * ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
- * ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
- * ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
- * ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
- *
- * As of this round of changes, ld now builds on all hosts of (Intel960)
- * interest and copy passes my copy test on big endian hosts again.
- *
- * Revision 1.3 1991/03/06 02:28:56 sac
- * Cleaned up
- *
- * Revision 1.2 1991/02/22 17:15:06 sac
- * Added RCS keywords and copyrights
- *
-*/
-
-/*
-
- All symbol handling for the linker
- */
+ We keep a hash table of global symbols. Each entry in a hash table
+ is called an ldsym_type. Each has three chains; a pointer to a
+ chain of definitions for the symbol (hopefully one long), a pointer
+ to a chain of references to the symbol, and a pointer to a chain of
+ common symbols. Each pointer points into the canonical symbol table
+ provided by bfd, each one of which points to an asymbol. During
+ linkage, the linker uses the udata field to point to the next entry
+ in a canonical table....
+
+
+ ld_sym
+ | |
+ +----------+ +----------+
+ | defs | a canonical symbol table
+ +----------+ +----------+
+ | refs | -----> | one entry| -----> asymbol
+ +----------+ +----------+ | |
+ | coms | | | +---------+
+ +----------+ +----------+ | udata |-----> another canonical
+ +---------+ symbol
+
+
+
+ It is very simple to make all the symbol pointers point to the same
+ definition - just run down the chain and make the asymbols pointers
+ within the canonical table point to the asymbol attacthed to the
+ definition of the symbol.
+*/
-#include "sysdep.h"
#include "bfd.h"
+#include "sysdep.h"
#include "ld.h"
#include "ldsym.h"
#include "ldmisc.h"
#include "ldlang.h"
/* IMPORT */
-
+extern int symbol_truncate;
extern bfd *output_bfd;
+extern strip_symbols_type strip_symbols;
+extern discard_locals_type discard_locals;
/* Head and tail of global symbol table chronological list */
-ldsym_type *symbol_head = (ldsym_type *)NULL;
+ldsym_type *symbol_head = (ldsym_type *) NULL;
ldsym_type **symbol_tail_ptr = &symbol_head;
+CONST char *keepsyms_file;
+int kept_syms;
+
+extern ld_config_type config;
+
+struct obstack global_sym_obstack;
+#define obstack_chunk_alloc ldmalloc
+#define obstack_chunk_free free
/*
incremented for each symbol in the ldsym_type table
- no matter what flavour it is
+ no matter what flavour it is
*/
unsigned int global_symbol_count;
/* IMPORTS */
-extern boolean option_longmap ;
-
/* LOCALS */
#define TABSIZE 1009
static ldsym_type *global_symbol_hash_table[TABSIZE];
/* Compute the hash code for symbol name KEY. */
+static
+#ifdef __GNUC__
+ __inline
+#endif
int
hash_string (key)
- char *key;
+ CONST char *key;
{
- register char *cp;
+ register CONST char *cp;
register int k;
-
+ register int l = 0;
cp = key;
k = 0;
- while (*cp)
- k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
-
+ while (*cp && l < symbol_truncate)
+ {
+ k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
+ l++;
+ }
return k;
}
+static
+#ifdef __GNUC__
+ __inline
+#endif
+ ldsym_type *
+search (key, hashval)
+ CONST char *key;
+ int hashval;
+{
+ ldsym_type *bp;
+ for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
+ if (!strncmp (key, bp->name, symbol_truncate))
+ {
+ if (bp->flags & SYM_INDIRECT)
+ {
+ /* Use the symbol we're aliased to instead */
+ return (ldsym_type *) (bp->sdefs_chain);
+ }
+ return bp;
+ }
+ return 0;
+}
+
+
/* Get the symbol table entry for the global symbol named KEY.
Create one if there is none. */
ldsym_type *
ldsym_get (key)
- char *key;
+ CONST char *key;
{
register int hashval;
register ldsym_type *bp;
hashval = hash_string (key) % TABSIZE;
/* Search the bucket. */
-
- for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
- if (! strcmp (key, bp->name))
+ bp = search (key, hashval);
+ if (bp)
+ {
return bp;
+ }
/* Nothing was found; create a new symbol table entry. */
- bp = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
- bp->srefs_chain = (asymbol **)NULL;
- bp->sdefs_chain = (asymbol **)NULL;
- bp->scoms_chain = (asymbol **)NULL;
- bp->name = (char *) ldmalloc (strlen (key) + 1);
- strcpy (bp->name, key);
-
-
-
-
+ bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type) (sizeof (ldsym_type)));
+ bp->srefs_chain = (asymbol **) NULL;
+ bp->sdefs_chain = (asymbol **) NULL;
+ bp->scoms_chain = (asymbol **) NULL;
+ bp->name = obstack_copy (&global_sym_obstack, key, strlen (key) + 1);
+ bp->flags = 0;
/* Add the entry to the bucket. */
bp->link = global_symbol_hash_table[hashval];
ldsym_type *
ldsym_get_soft (key)
- char *key;
+ CONST char *key;
{
register int hashval;
- register ldsym_type *bp;
-
/* Determine which bucket. */
hashval = hash_string (key) % TABSIZE;
/* Search the bucket. */
-
- for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
- if (! strcmp (key, bp->name))
- return bp;
-
- return 0;
+ return search (key, hashval);
}
+static asymbol **
+process_keepsyms (table, size)
+ asymbol **table;
+ int size;
+{
+ struct obstack obstack;
+ char *start_of_obstack;
+ FILE *ks_file = 0;
+ asymbol **out = table;
+ asymbol **end = table + size;
+ asymbol **sym;
+
+ if (!keepsyms_file || size == 0)
+ return end;
+ obstack_init (&obstack);
+ obstack_alloc (&obstack, 1);
+ obstack_finish (&obstack);
+ start_of_obstack = obstack_alloc (&obstack, 1);
+ ks_file = fopen (keepsyms_file, "r");
+ if (!ks_file)
+ {
+ info_msg ("%X%P: cannot open keep-symbols file `%s'\n", keepsyms_file);
+ goto egress;
+ }
+ errno = 0;
+#define KEEP(S) \
+ do { asymbol **p = (S), *tmp = *out; *out = *p; *p = tmp; out++; } while (0)
+ while (!feof (ks_file) && !ferror (ks_file))
+ {
+ int c;
+ char *ptr;
+ int found = 0;
+ obstack_free (&obstack, start_of_obstack);
+ do
+ {
+ c = getc (ks_file);
+ if (c == '\n')
+ c = 0;
+ obstack_1grow (&obstack, c);
+ }
+ while (c > 0);
+ if (c == EOF)
+ {
+ if (!feof (ks_file))
+ /* error occurred */
+ {
+ info_msg ("%X%P: error reading keep-symbols file `%s': %E\n",
+ keepsyms_file);
+ out = end;
+ goto egress;
+ }
+ if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1)
+ /* eof in middle of symbol */
+ {
+ info_msg ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n",
+ keepsyms_file);
+ out = end;
+ goto egress;
+ }
+ /* All okay -- no incomplete lines, EOF reached. */
+ break;
+ }
+ ptr = obstack_next_free (&obstack) - 2;
+ /* discard trailing trash */
+ while (*ptr == ' '
+ || *ptr == '\t')
+ *ptr-- = 0;
+ ptr = obstack_base (&obstack);
+ for (sym = out; sym < end; sym++)
+ if (!strncmp ((*sym)->name, ptr, symbol_truncate))
+ {
+ KEEP (sym);
+ found = 1;
+ }
+ if (!found)
+ info_msg ("%P: symbol `%s' (requested to be kept) not found\n", ptr);
+ }
+ /* It'd be slightly faster to move this pass above the previous one,
+ but that'd mean any symbols preserved in this pass would generate
+ warnings if they were also listed in the keepsyms file. */
+ for (sym = out; sym < end; sym++)
+ {
+ asymbol *s = *sym;
+ if (s->section == &bfd_und_section
+ || bfd_is_com_section (s->section)
+ || s->flags & BSF_KEEP_G)
+ KEEP (sym);
+ }
+egress:
+ obstack_free (&obstack, start_of_obstack);
+ if (ks_file)
+ fclose (ks_file);
+ return out;
+}
static void
list_file_locals (entry)
-lang_input_statement_type *entry;
+ lang_input_statement_type *entry;
{
asymbol **q;
- fprintf (stderr, "\nLocal symbols of ");
- info("%I", entry);
- fprintf (stderr, ":\n\n");
- if (entry->asymbols) {
- for (q = entry->asymbols; *q; q++)
- {
- asymbol *p = *q;
- /* If this is a definition,
+ fprintf (config.map_file, "\nLocal symbols of ");
+ minfo ("%I", entry);
+ fprintf (config.map_file, ":\n\n");
+ if (entry->asymbols)
+ {
+ for (q = entry->asymbols; *q; q++)
+ {
+ asymbol *p = *q;
+ /* If this is a definition,
update it if necessary by this file's start address. */
- if (p->flags & BSF_LOCAL)
- info(" %V %s\n",p->value, p->name);
- }
- }
+ if (p->flags & BSF_LOCAL)
+ info_msg (" %V %s\n", p->value, p->name);
+ }
+ }
}
static void
-print_file_stuff(f)
-lang_input_statement_type *f;
+print_file_stuff (f)
+ lang_input_statement_type * f;
{
- fprintf (stderr, " %s", f->filename);
- fprintf (stderr, " ");
- if (f->just_syms_flag)
+ fprintf (config.map_file, " %s\n", f->filename);
+ if (f->just_syms_flag)
{
- fprintf (stderr, " symbols only\n");
+ fprintf (config.map_file, " symbols only\n");
}
- else
+ else
{
asection *s;
- if (option_longmap) {
- for (s = f->the_bfd->sections;
- s != (asection *)NULL;
- s = s->next) {
- fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
- s->output_offset,
- (unsigned)s->size, s->alignment_power, s->name);
+ if (true)
+ {
+ for (s = f->the_bfd->sections;
+ s != (asection *) NULL;
+ s = s->next)
+ {
+ print_address (s->output_offset);
+ if (s->reloc_done)
+ {
+ fprintf (config.map_file, " %08x 2**%2ud %s\n",
+ (unsigned) bfd_get_section_size_after_reloc (s),
+ s->alignment_power, s->name);
+ }
+
+ else
+ {
+ fprintf (config.map_file, " %08x 2**%2ud %s\n",
+ (unsigned) bfd_get_section_size_before_reloc (s),
+ s->alignment_power, s->name);
+ }
+ }
}
- }
- else {
- for (s = f->the_bfd->sections;
- s != (asection *)NULL;
- s = s->next) {
- fprintf (stderr, "%s %lx(%x) ",
- s->name,
- s->output_offset,
- (unsigned) s->size);
+ else
+ {
+ for (s = f->the_bfd->sections;
+ s != (asection *) NULL;
+ s = s->next)
+ {
+ fprintf (config.map_file, "%s ", s->name);
+ print_address (s->output_offset);
+ fprintf (config.map_file, "(%x)", (unsigned) bfd_get_section_size_after_reloc (s));
+ }
+ fprintf (config.map_file, "hex \n");
}
- fprintf (stderr, "hex \n");
- }
}
+ fprintf (config.map_file, "\n");
}
void
ldsym_print_symbol_table ()
{
- fprintf (stderr, "\nFiles:\n\n");
+ fprintf (config.map_file, "**FILES**\n\n");
- lang_for_each_file(print_file_stuff);
+ lang_for_each_file (print_file_stuff);
- fprintf (stderr, "\nGlobal symbols:\n\n");
+ fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
+ fprintf (config.map_file, "offset section offset symbol\n");
{
register ldsym_type *sp;
for (sp = symbol_head; sp; sp = sp->next)
{
- if (sp->sdefs_chain)
+ if (sp->flags & SYM_INDIRECT)
{
- asymbol *defsym = *(sp->sdefs_chain);
- asection *defsec = bfd_get_section(defsym);
- fprintf(stderr,"%08lx ",defsym->value);
- if (defsec)
+ fprintf (config.map_file, "indirect %s to %s\n",
+ sp->name, (((ldsym_type *) (sp->sdefs_chain))->name));
+ }
+ else
+ {
+ if (sp->sdefs_chain)
{
- fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
- fprintf(stderr,
- "%7s",
- bfd_section_name(output_bfd,
- defsec));
+ asymbol *defsym = *(sp->sdefs_chain);
+ asection *defsec = bfd_get_section (defsym);
+ print_address (defsym->value);
+ if (defsec)
+ {
+ fprintf (config.map_file, " %-10s",
+ bfd_section_name (output_bfd,
+ defsec));
+ print_space ();
+ print_address (defsym->value + defsec->vma);
+
+ }
+ else
+ {
+ fprintf (config.map_file, " .......");
+ }
}
- else
- {
- fprintf(stderr," .......");
- }
- }
- else {
- fprintf(stderr,"undefined");
- }
+ if (sp->scoms_chain)
+ {
+ fprintf (config.map_file, "common ");
+ print_address ((*(sp->scoms_chain))->value);
+ fprintf (config.map_file, " %s ", sp->name);
+ }
+ else if (sp->sdefs_chain)
+ {
+ fprintf (config.map_file, " %s ", sp->name);
+ }
+ else
+ {
+ fprintf (config.map_file, "undefined ");
+ fprintf (config.map_file, "%s ", sp->name);
- if (sp->scoms_chain) {
- fprintf(stderr, " common size %5lu %s",
- (*(sp->scoms_chain))->value, sp->name);
- }
- if (sp->sdefs_chain) {
- fprintf(stderr, " symbol def %08lx %s",
- (*(sp->sdefs_chain))->value,
- sp->name);
- }
- else {
- fprintf(stderr, " undefined %s",
- sp->name);
- }
- fprintf(stderr, "\n");
+ }
+ }
+ print_nl ();
}
}
- lang_for_each_file(list_file_locals);
}
extern lang_output_section_statement_type *create_object_symbols;
extern char lprefix;
static asymbol **
-write_file_locals(output_buffer)
-asymbol **output_buffer;
+write_file_locals (output_buffer)
+ asymbol **output_buffer;
{
-LANG_FOR_EACH_INPUT_STATEMENT(entry)
- {
- /* Run trough the symbols and work out what to do with them */
- unsigned int i;
+ LANG_FOR_EACH_INPUT_STATEMENT (entry)
+ {
+ /* Run trough the symbols and work out what to do with them */
+ unsigned int i;
- /* Add one for the filename symbol if needed */
- if (create_object_symbols
- != (lang_output_section_statement_type *)NULL) {
+ /* Add one for the filename symbol if needed */
+ if (create_object_symbols
+ != (lang_output_section_statement_type *) NULL)
+ {
asection *s;
for (s = entry->the_bfd->sections;
- s != (asection *)NULL;
- s = s->next) {
- if (s->output_section == create_object_symbols->bfd_section) {
- /* Add symbol to this section */
- asymbol * newsym =
- (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
- newsym->name = entry->local_sym_name;
- /* The symbol belongs to the output file's text section */
-
- /* The value is the start of this section in the output file*/
- newsym->value = 0;
- newsym->flags = BSF_LOCAL;
- newsym->section = s;
- *output_buffer++ = newsym;
- break;
+ s != (asection *) NULL;
+ s = s->next)
+ {
+ if (s->output_section == create_object_symbols->bfd_section)
+ {
+ /* Add symbol to this section */
+ asymbol *newsym =
+ (asymbol *) bfd_make_empty_symbol (entry->the_bfd);
+ newsym->name = entry->local_sym_name;
+ /* The symbol belongs to the output file's text section */
+
+ /* The value is the start of this section in the output file*/
+ newsym->value = 0;
+ /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as
+ "used by the linker" and I can't find any other code that
+ uses it. Should be a cleaner way of doing this (like an
+ "application flags" field in the symbol structure?). */
+ newsym->flags = BSF_LOCAL | BSF_KEEP_G;
+ newsym->section = s;
+ *output_buffer++ = newsym;
+ break;
+ }
}
- }
}
- for (i = 0; i < entry->symbol_count; i++)
- {
- asymbol *p = entry->asymbols[i];
+ for (i = 0; i < entry->symbol_count; i++)
+ {
+ asymbol *p = entry->asymbols[i];
+ /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
- if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
- {
- /* We are only interested in outputting
- globals at this stage in special circumstances */
- if (p->the_bfd == entry->the_bfd
- && flag_is_not_at_end(p->flags)) {
- /* And this is one of them */
+ if (p->section == 0)
+ p->section = &bfd_abs_section;
+ if (flag_is_global (p->flags)
+ || flag_is_weak (p->flags))
+ {
+ /* If this symbol is marked as occurring now, rather than
+ at the end, output it now. This is used for COFF C_EXT
+ FCN symbols. FIXME: There must be a better way. */
+ if (bfd_asymbol_bfd (p) == entry->the_bfd
+ && flag_is_not_at_end (p->flags))
+ {
*(output_buffer++) = p;
p->flags |= BSF_KEEP;
}
- }
- else {
- if (flag_is_ordinary_local(p->flags))
+ }
+ else
+ {
+ if (p->section == &bfd_ind_section)
{
- if (discard_locals == DISCARD_ALL)
- { }
- else if (discard_locals == DISCARD_L &&
- (p->name[0] == lprefix))
- { }
- else if (p->flags == BSF_WARNING)
- { }
- else
- { *output_buffer++ = p; }
+ /* Dont think about indirect symbols */
}
- else if (flag_is_debugger(p->flags))
+ else if (flag_is_debugger (p->flags))
{
/* Only keep the debugger symbols if no stripping required */
- if (strip_symbols == STRIP_NONE) {
- *output_buffer++ = p;
- }
+ if (strip_symbols == STRIP_NONE)
+ {
+ *output_buffer++ = p;
+ }
}
- else if (flag_is_undefined(p->flags))
- { /* This must be global */
+ else if (p->section == &bfd_und_section
+ || bfd_is_com_section (p->section))
+ {
+ /* These must be global. */
}
- else if (flag_is_common(p->flags)) {
- /* And so must this */
- }
- else if (p->flags & BSF_CTOR) {
- /* Throw it away */
- }
-else
+ else if (flag_is_ordinary_local (p->flags))
+ {
+ if (discard_locals == DISCARD_ALL)
+ {
+ }
+ else if (discard_locals == DISCARD_L &&
+ (p->name[0] == lprefix))
+ {
+ }
+ else if (p->flags == BSF_WARNING)
+ {
+ }
+ else
+ {
+ *output_buffer++ = p;
+ }
+ }
+ else if (p->flags & BSF_CONSTRUCTOR)
+ {
+ if (strip_symbols != STRIP_ALL)
+ {
+ *output_buffer++ = p;
+ }
+ }
+ else
{
- FAIL();
+ FAIL ();
}
}
- }
+ }
- }
+ }
return output_buffer;
}
static asymbol **
-write_file_globals(symbol_table)
-asymbol **symbol_table;
+write_file_globals (symbol_table)
+ asymbol **symbol_table;
{
- FOR_EACH_LDSYM(sp)
- {
- if (sp->sdefs_chain != (asymbol **)NULL) {
+ FOR_EACH_LDSYM (sp)
+ {
+ if (sp->flags & SYM_INDIRECT)
+ {
+ asymbol *bufp = (*(sp->srefs_chain));
+ ldsym_type *aliased_to = (ldsym_type *) (sp->sdefs_chain);
+ if (aliased_to->sdefs_chain)
+ {
+ asymbol *p = aliased_to->sdefs_chain[0];
+ bufp->value = p->value;
+ bufp->section = p->section;
+ bufp->flags = p->flags;
+ }
+ else
+ {
+ bufp->value = 0;
+ bufp->flags = 0;
+ bufp->section = &bfd_und_section;
+ }
+ *symbol_table++ = bufp;
+ }
+ else if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **) NULL)
+ {
asymbol *bufp = (*(sp->sdefs_chain));
- if ((bufp->flags & BSF_KEEP) ==0) {
- ASSERT(bufp != (asymbol *)NULL);
+ if ((bufp->flags & BSF_KEEP) == 0)
+ {
+ ASSERT (bufp != (asymbol *) NULL);
- bufp->name = sp->name;
+ bufp->name = sp->name;
- if (sp->scoms_chain != (asymbol **)NULL)
+ if (sp->scoms_chain != (asymbol **) NULL)
- {
- /*
+ {
+ /*
defined as common but not allocated, this happens
only with -r and not -d, write out a common
definition
*/
- bufp = *(sp->scoms_chain);
- }
- *symbol_table++ = bufp;
- }
+ bufp = *(sp->scoms_chain);
+ }
+ *symbol_table++ = bufp;
+ }
}
- else if (sp->scoms_chain != (asymbol **)NULL) {
+ else if (sp->scoms_chain != (asymbol **) NULL)
+ {
/* This symbol is a common - just output */
asymbol *bufp = (*(sp->scoms_chain));
*symbol_table++ = bufp;
}
- else if (sp->srefs_chain != (asymbol **)NULL) {
+ else if (sp->srefs_chain != (asymbol **) NULL)
+ {
/* This symbol is undefined but has a reference */
asymbol *bufp = (*(sp->srefs_chain));
*symbol_table++ = bufp;
}
- else {
+ else
+ {
/*
This symbol has neither defs nor refs, it must have come
from the command line, since noone has used it it has no
- data attatched, so we'll ignore it
+ data attatched, so we'll ignore it
*/
}
- }
+ }
return symbol_table;
}
-
-
void
-ldsym_write()
+ldsym_write ()
{
- if (strip_symbols != STRIP_ALL) {
- /* We know the maximum size of the symbol table -
+ if (keepsyms_file != 0
+ && strip_symbols != STRIP_SOME)
+ {
+ info_msg ("%P: `-retain-symbols-file' overrides `-s' and `-S'\n");
+ strip_symbols = STRIP_SOME;
+ }
+ if (strip_symbols != STRIP_ALL)
+ {
+ /* We know the maximum size of the symbol table -
it's the size of all the global symbols ever seen +
the size of all the symbols from all the files +
the number of files (for the per file symbols)
+1 (for the null at the end)
*/
- extern unsigned int total_files_seen;
- extern unsigned int total_symbols_seen;
+ extern unsigned int total_files_seen;
+ extern unsigned int total_symbols_seen;
- asymbol ** symbol_table = (asymbol **)
- ldmalloc ((size_t)(global_symbol_count +
- total_files_seen +
- total_symbols_seen + 1) * sizeof (asymbol *));
- asymbol ** tablep = write_file_locals(symbol_table);
+ asymbol **symbol_table = (asymbol **)
+ ldmalloc ((bfd_size_type) (global_symbol_count +
+ total_files_seen +
+ total_symbols_seen + 1) * sizeof (asymbol *));
+ asymbol **tablep = write_file_locals (symbol_table);
- tablep = write_file_globals(tablep);
+ tablep = write_file_globals (tablep);
+ tablep = process_keepsyms (symbol_table, tablep - symbol_table);
- *tablep = (asymbol *)NULL;
- bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
- }
+ *tablep = (asymbol *) NULL;
+ bfd_set_symtab (output_bfd, symbol_table, (unsigned) (tablep - symbol_table));
+ }
+}
+
+/*
+return true if the supplied symbol name is not in the
+linker symbol table
+*/
+boolean
+ldsym_undefined (sym)
+ CONST char *sym;
+{
+ ldsym_type *from_table = ldsym_get_soft (sym);
+ if (from_table != (ldsym_type *) NULL)
+ {
+ if (from_table->sdefs_chain != (asymbol **) NULL)
+ return false;
+ }
+ return true;
+}
+
+void
+ldsym_init ()
+{
+ obstack_begin (&global_sym_obstack, 20000);
}