/* linker.c -- BFD linker routines
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004 Free Software Foundation, Inc.
+ 2003, 2004, 2005 Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
This file is part of BFD, the Binary File Descriptor library.
/* Initialize the local fields. */
h->type = bfd_link_hash_new;
- h->und_next = NULL;
+ memset (&h->u.undef.next, 0,
+ (sizeof (struct bfd_link_hash_entry)
+ - offsetof (struct bfd_link_hash_entry, u.undef.next)));
}
return entry;
bfd_link_add_undef (struct bfd_link_hash_table *table,
struct bfd_link_hash_entry *h)
{
- BFD_ASSERT (h->und_next == NULL);
+ BFD_ASSERT (h->u.undef.next == NULL);
if (table->undefs_tail != NULL)
- table->undefs_tail->und_next = h;
+ table->undefs_tail->u.undef.next = h;
if (table->undefs == NULL)
table->undefs = h;
table->undefs_tail = h;
}
+
+/* The undefs list was designed so that in normal use we don't need to
+ remove entries. However, if symbols on the list are changed from
+ bfd_link_hash_undefined to either bfd_link_hash_undefweak or
+ bfd_link_hash_new for some reason, then they must be removed from the
+ list. Failure to do so might result in the linker attempting to add
+ the symbol to the list again at a later stage. */
+
+void
+bfd_link_repair_undef_list (struct bfd_link_hash_table *table)
+{
+ struct bfd_link_hash_entry **pun;
+
+ pun = &table->undefs;
+ while (*pun != NULL)
+ {
+ struct bfd_link_hash_entry *h = *pun;
+
+ if (h->type == bfd_link_hash_new
+ || h->type == bfd_link_hash_undefweak)
+ {
+ *pun = h->u.undef.next;
+ h->u.undef.next = NULL;
+ if (h == table->undefs_tail)
+ {
+ if (pun == &table->undefs)
+ table->undefs_tail = NULL;
+ else
+ /* pun points at an u.undef.next field. Go back to
+ the start of the link_hash_entry. */
+ table->undefs_tail = (struct bfd_link_hash_entry *)
+ ((char *) pun - ((char *) &h->u.undef.next - (char *) h));
+ break;
+ }
+ }
+ else
+ pun = &h->u.undef.next;
+ }
+}
\f
/* Routine to create an entry in a generic link hash table. */
us to lose track of whether the symbol has been
referenced). */
if (*pundef != info->hash->undefs_tail)
- *pundef = (*pundef)->und_next;
+ *pundef = (*pundef)->u.undef.next;
else
- pundef = &(*pundef)->und_next;
+ pundef = &(*pundef)->u.undef.next;
continue;
}
}
if (arh == NULL)
{
- pundef = &(*pundef)->und_next;
+ pundef = &(*pundef)->u.undef.next;
continue;
}
}
}
}
- pundef = &(*pundef)->und_next;
+ pundef = &(*pundef)->u.undef.next;
}
archive_hash_table_free (&arsym_hash);
/* Make a new weak undefined symbol. */
h->type = bfd_link_hash_undefweak;
h->u.undef.abfd = abfd;
+ h->u.undef.weak = abfd;
break;
case CDEF:
case REF:
/* A reference to a defined symbol. */
- if (h->und_next == NULL && info->hash->undefs_tail != h)
- h->und_next = h;
+ if (h->u.undef.next == NULL && info->hash->undefs_tail != h)
+ h->u.undef.next = h;
break;
case BIG:
&& inh->u.i.link == h)
{
(*_bfd_error_handler)
- (_("%s: indirect symbol `%s' to `%s' is a loop"),
- bfd_archive_filename (abfd), name, string);
+ (_("%B: indirect symbol `%s' to `%s' is a loop"),
+ abfd, name, string);
bfd_set_error (bfd_error_invalid_operation);
return FALSE;
}
case REFC:
/* A reference to an indirect symbol. */
- if (h->und_next == NULL && info->hash->undefs_tail != h)
- h->und_next = h;
+ if (h->u.undef.next == NULL && info->hash->undefs_tail != h)
+ h->u.undef.next = h;
h = h->u.i.link;
cycle = TRUE;
break;
case CWARN:
/* Warn if this symbol has been referenced already,
otherwise add a warning. A symbol has been referenced if
- the und_next field is not NULL, or it is the tail of the
+ the u.undef.next field is not NULL, or it is the tail of the
undefined symbol list. The REF case above helps to
ensure this. */
- if (h->und_next != NULL || info->hash->undefs_tail == h)
+ if (h->u.undef.next != NULL || info->hash->undefs_tail == h)
{
if (! (*info->callbacks->warning) (info, string, h->root.string,
hash_entry_bfd (h), NULL, 0))
abort ();
/* If this symbol is in a section which is not being included
- in the output file, then we don't want to output the symbol.
-
- Gross. .bss and similar sections won't have the linker_mark
- field set. */
- if ((sym->section->flags & SEC_HAS_CONTENTS) != 0
- && ! sym->section->linker_mark)
+ in the output file, then we don't want to output the
+ symbol. .bss and similar sections won't have the linker_mark
+ field set. We also check if its output section has been
+ removed from the output file. */
+ if (((sym->section->flags & SEC_HAS_CONTENTS) != 0
+ && ! sym->section->linker_mark)
+ || bfd_section_removed_from_list (output_bfd,
+ sym->section->output_section))
output = FALSE;
if (output)
abort ();
case bfd_reloc_overflow:
if (! ((*info->callbacks->reloc_overflow)
- (info,
+ (info, NULL,
(link_order->type == bfd_section_reloc_link_order
? bfd_section_name (abfd, link_order->u.reloc.p->u.section)
: link_order->u.reloc.p->u.name),
static struct bfd_hash_table _bfd_section_already_linked_table;
/* Support routines for the hash table used by section_already_linked,
- initialize the table, lookup, fill in an entry and remove the
- table. */
+ initialize the table, traverse, lookup, fill in an entry and remove
+ the table. */
+
+void
+bfd_section_already_linked_table_traverse
+ (bfd_boolean (*func) (struct bfd_section_already_linked_hash_entry *,
+ void *), void *info)
+{
+ bfd_hash_traverse (&_bfd_section_already_linked_table,
+ (bfd_boolean (*) (struct bfd_hash_entry *,
+ void *)) func,
+ info);
+}
struct bfd_section_already_linked_hash_entry *
bfd_section_already_linked_table_lookup (const char *name)
break;
case SEC_LINK_DUPLICATES_ONE_ONLY:
- if (s_comdat == NULL)
- (*_bfd_error_handler)
- (_("%s: %s: warning: ignoring duplicate section `%s'\n"),
- bfd_archive_filename (abfd), name);
- else
- (*_bfd_error_handler)
- (_("%s: %s: warning: ignoring duplicate `%s' section symbol `%s'\n"),
- bfd_archive_filename (abfd), name, s_comdat->name);
+ (*_bfd_error_handler)
+ (_("%B: warning: ignoring duplicate section `%A'\n"),
+ abfd, sec);
break;
case SEC_LINK_DUPLICATES_SAME_CONTENTS:
case SEC_LINK_DUPLICATES_SAME_SIZE:
if (sec->size != l->sec->size)
(*_bfd_error_handler)
- (_("%s: %s: warning: duplicate section `%s' has different size\n"),
- bfd_archive_filename (abfd), name);
+ (_("%B: warning: duplicate section `%A' has different size\n"),
+ abfd, sec);
break;
}