aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ldindr.c2
-rw-r--r--ld/ldmain.c220
2 files changed, 117 insertions, 105 deletions
diff --git a/ld/ldindr.c b/ld/ldindr.c
index 82efe33..47c9e1d 100644
--- a/ld/ldindr.c
+++ b/ld/ldindr.c
@@ -93,6 +93,8 @@ asymbol **ptr)
{
refize(new, new->scoms_chain);
}
+lgs->sdefs_chain = (asymbol **)new;
+
}
diff --git a/ld/ldmain.c b/ld/ldmain.c
index fa02f26..965aa72 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -348,129 +348,139 @@ DEFUN (Q_enter_global_ref, (nlist_p, name),
flagword this_symbol_flags = sym->flags;
sp = ldsym_get (name);
+ /* If this symbol already has udata, it means that something strange
+ has happened.
+
+ The strange thing is that we've had an undefined symbol resolved by
+ an alias, but the thing the alias defined wasn't in the file. So
+ the symbol got a udata entry, but the file wasn't loaded. Then
+ later on the file was loaded, but we don't need to do this
+ processing again */
- ASSERT (sym->udata == 0);
+
+ if (sym->udata)
+ return;
if (flag_is_constructor (this_symbol_flags))
+ {
+ /* Add this constructor to the list we keep */
+ ldlang_add_constructor (sp);
+ /* Turn any commons into refs */
+ if (sp->scoms_chain != (asymbol **) NULL)
{
- /* Add this constructor to the list we keep */
- ldlang_add_constructor (sp);
- /* Turn any commons into refs */
- if (sp->scoms_chain != (asymbol **) NULL)
- {
- refize (sp, sp->scoms_chain);
- sp->scoms_chain = 0;
- }
+ refize (sp, sp->scoms_chain);
+ sp->scoms_chain = 0;
+ }
- }
+ }
else
+ {
+ if (sym->section == &bfd_com_section)
{
- if (sym->section == &bfd_com_section)
+ /* If we have a definition of this symbol already then
+ this common turns into a reference. Also we only
+ ever point to the largest common, so if we
+ have a common, but it's bigger that the new symbol
+ the turn this into a reference too. */
+ if (sp->sdefs_chain)
+ {
+ /* This is a common symbol, but we already have a definition
+ for it, so just link it into the ref chain as if
+ it were a reference */
+ refize (sp, nlist_p);
+ }
+ else if (sp->scoms_chain)
+ {
+ /* If we have a previous common, keep only the biggest */
+ if ((*(sp->scoms_chain))->value > sym->value)
{
- /* If we have a definition of this symbol already then
- this common turns into a reference. Also we only
- ever point to the largest common, so if we
- have a common, but it's bigger that the new symbol
- the turn this into a reference too. */
- if (sp->sdefs_chain)
- {
- /* This is a common symbol, but we already have a definition
- for it, so just link it into the ref chain as if
- it were a reference */
- refize (sp, nlist_p);
- }
- else if (sp->scoms_chain)
- {
- /* If we have a previous common, keep only the biggest */
- if ((*(sp->scoms_chain))->value > sym->value)
- {
- /* other common is bigger, throw this one away */
- refize (sp, nlist_p);
- }
- else if (sp->scoms_chain != nlist_p)
- {
- /* other common is smaller, throw that away */
- refize (sp, sp->scoms_chain);
- sp->scoms_chain = nlist_p;
- }
- }
- else
- {
- /* This is the first time we've seen a common, so remember it
- - if it was undefined before, we know it's defined now. If
- the symbol has been marked as really being a constructor,
- then treat this as a ref
- */
- if (sp->flags & SYM_CONSTRUCTOR)
- {
- /* Turn this into a ref */
- refize (sp, nlist_p);
- }
- else
- {
- /* treat like a common */
- if (sp->srefs_chain)
- undefined_global_sym_count--;
-
- commons_pending++;
- sp->scoms_chain = nlist_p;
- }
- }
+ /* other common is bigger, throw this one away */
+ refize (sp, nlist_p);
}
-
- else if (sym->section != &bfd_und_section)
+ else if (sp->scoms_chain != nlist_p)
{
- /* This is the definition of a symbol, add to def chain */
- if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section)
- {
- /* Multiple definition */
- asymbol *sy = *(sp->sdefs_chain);
- lang_input_statement_type *stat = (lang_input_statement_type *) sy->the_bfd->usrdata;
- lang_input_statement_type *stat1 = (lang_input_statement_type *) sym->the_bfd->usrdata;
- asymbol **stat1_symbols = stat1 ? stat1->asymbols : 0;
- asymbol **stat_symbols = stat ? stat->asymbols : 0;
-
- multiple_def_count++;
- einfo ("%X%C: multiple definition of `%T'\n",
- sym->the_bfd, sym->section, stat1_symbols, sym->value, sym);
-
- einfo ("%X%C: first seen here\n",
- sy->the_bfd, sy->section, stat_symbols, sy->value);
- }
- else
- {
- sym->udata = (PTR) (sp->sdefs_chain);
- sp->sdefs_chain = nlist_p;
- }
- /* A definition overrides a common symbol */
- if (sp->scoms_chain)
- {
- refize (sp, sp->scoms_chain);
- sp->scoms_chain = 0;
- commons_pending--;
- }
- else if (sp->srefs_chain && relaxing == false)
- {
- /* If previously was undefined, then remember as defined */
- undefined_global_sym_count--;
- }
+ /* other common is smaller, throw that away */
+ refize (sp, sp->scoms_chain);
+ sp->scoms_chain = nlist_p;
}
+ }
else
+ {
+ /* This is the first time we've seen a common, so remember it
+ - if it was undefined before, we know it's defined now. If
+ the symbol has been marked as really being a constructor,
+ then treat this as a ref
+ */
+ if (sp->flags & SYM_CONSTRUCTOR)
{
- if (sp->scoms_chain == (asymbol **) NULL
- && sp->srefs_chain == (asymbol **) NULL
- && sp->sdefs_chain == (asymbol **) NULL)
- {
- /* And it's the first time we've seen it */
- undefined_global_sym_count++;
-
- }
-
+ /* Turn this into a ref */
refize (sp, nlist_p);
}
+ else
+ {
+ /* treat like a common */
+ if (sp->srefs_chain)
+ undefined_global_sym_count--;
+
+ commons_pending++;
+ sp->scoms_chain = nlist_p;
+ }
+ }
+ }
+
+ else if (sym->section != &bfd_und_section)
+ {
+ /* This is the definition of a symbol, add to def chain */
+ if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section)
+ {
+ /* Multiple definition */
+ asymbol *sy = *(sp->sdefs_chain);
+ lang_input_statement_type *stat = (lang_input_statement_type *) sy->the_bfd->usrdata;
+ lang_input_statement_type *stat1 = (lang_input_statement_type *) sym->the_bfd->usrdata;
+ asymbol **stat1_symbols = stat1 ? stat1->asymbols : 0;
+ asymbol **stat_symbols = stat ? stat->asymbols : 0;
+
+ multiple_def_count++;
+ einfo ("%X%C: multiple definition of `%T'\n",
+ sym->the_bfd, sym->section, stat1_symbols, sym->value, sym);
+
+ einfo ("%X%C: first seen here\n",
+ sy->the_bfd, sy->section, stat_symbols, sy->value);
+ }
+ else
+ {
+ sym->udata = (PTR) (sp->sdefs_chain);
+ sp->sdefs_chain = nlist_p;
+ }
+ /* A definition overrides a common symbol */
+ if (sp->scoms_chain)
+ {
+ refize (sp, sp->scoms_chain);
+ sp->scoms_chain = 0;
+ commons_pending--;
+ }
+ else if (sp->srefs_chain && relaxing == false)
+ {
+ /* If previously was undefined, then remember as defined */
+ undefined_global_sym_count--;
+ }
+ }
+ else
+ {
+ if (sp->scoms_chain == (asymbol **) NULL
+ && sp->srefs_chain == (asymbol **) NULL
+ && sp->sdefs_chain == (asymbol **) NULL)
+ {
+ /* And it's the first time we've seen it */
+ undefined_global_sym_count++;
+
+ }
+
+ refize (sp, nlist_p);
}
+ }
ASSERT (sp->sdefs_chain == 0 || sp->scoms_chain == 0);
ASSERT (sp->scoms_chain == 0 || (*(sp->scoms_chain))->udata == 0);