+/* The i386 linker needs to keep track of the number of relocs that it
+ decides to copy in check_relocs for each symbol. This is so that
+ it can discard PC relative relocs if it doesn't need them when
+ linking with -Bsymbolic. We store the information in a field
+ extending the regular ELF linker hash table. */
+
+/* This structure keeps track of the number of PC relative relocs we
+ have copied for a given symbol. */
+
+struct elf_i386_pcrel_relocs_copied
+{
+ /* Next section. */
+ struct elf_i386_pcrel_relocs_copied *next;
+ /* A section in dynobj. */
+ asection *section;
+ /* Number of relocs copied in this section. */
+ bfd_size_type count;
+};
+
+/* i386 ELF linker hash entry. */
+
+struct elf_i386_link_hash_entry
+{
+ struct elf_link_hash_entry root;
+
+ /* Number of PC relative relocs copied for this symbol. */
+ struct elf_i386_pcrel_relocs_copied *pcrel_relocs_copied;
+};
+
+/* i386 ELF linker hash table. */
+
+struct elf_i386_link_hash_table
+{
+ struct elf_link_hash_table root;
+};
+
+/* Declare this now that the above structures are defined. */
+
+static boolean elf_i386_discard_copies
+ PARAMS ((struct elf_i386_link_hash_entry *, PTR));
+
+/* Traverse an i386 ELF linker hash table. */
+
+#define elf_i386_link_hash_traverse(table, func, info) \
+ (elf_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the i386 ELF linker hash table from a link_info structure. */
+
+#define elf_i386_hash_table(p) \
+ ((struct elf_i386_link_hash_table *) ((p)->hash))
+
+/* Create an entry in an i386 ELF linker hash table. */
+
+static struct bfd_hash_entry *
+elf_i386_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct elf_i386_link_hash_entry *ret =
+ (struct elf_i386_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct elf_i386_link_hash_entry *) NULL)
+ ret = ((struct elf_i386_link_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct elf_i386_link_hash_entry)));
+ if (ret == (struct elf_i386_link_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct elf_i386_link_hash_entry *)
+ _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != (struct elf_i386_link_hash_entry *) NULL)
+ {
+ ret->pcrel_relocs_copied = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create an i386 ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+elf_i386_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct elf_i386_link_hash_table *ret;
+
+ ret = ((struct elf_i386_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct elf_i386_link_hash_table)));
+ if (ret == (struct elf_i386_link_hash_table *) NULL)
+ return NULL;
+
+ if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+ elf_i386_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return NULL;
+ }
+
+ return &ret->root.root;
+}
+