+/* Return true iff this is a non-common definition of a symbol. */
+static boolean
+is_global_symbol_definition (abfd, sym)
+ bfd * abfd;
+ Elf_Internal_Sym * sym;
+{
+ /* Local symbols do not count, but target specific ones might. */
+ if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL
+ && ELF_ST_BIND (sym->st_info) < STB_LOOS)
+ return false;
+
+ /* If the section is undefined, then so is the symbol. */
+ if (sym->st_shndx == SHN_UNDEF)
+ return false;
+
+ /* If the symbol is defined in the common section, then
+ it is a common definition and so does not count. */
+ if (sym->st_shndx == SHN_COMMON)
+ return false;
+
+ /* If the symbol is in a target specific section then we
+ must rely upon the backend to tell us what it is. */
+ if (sym->st_shndx >= SHN_LORESERVE && sym->st_shndx < SHN_ABS)
+ /* FIXME - this function is not coded yet:
+
+ return _bfd_is_global_symbol_definition (abfd, sym);
+
+ Instead for now assume that the definition is not global,
+ Even if this is wrong, at least the linker will behave
+ in the same way that it used to do. */
+ return false;
+
+ return true;
+}
+
+
+/* Search the symbol table of the archive element of the archive ABFD
+ whoes archove map contains a mention of SYMDEF, and determine if
+ the symbol is defined in this element. */
+static boolean
+elf_link_is_defined_archive_symbol (abfd, symdef)
+ bfd * abfd;
+ carsym * symdef;
+{
+ Elf_Internal_Shdr * hdr;
+ Elf_External_Sym * esym;
+ Elf_External_Sym * esymend;
+ Elf_External_Sym * buf = NULL;
+ size_t symcount;
+ size_t extsymcount;
+ size_t extsymoff;
+ boolean result = false;
+
+ abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
+ if (abfd == (bfd *) NULL)
+ return false;
+
+ if (! bfd_check_format (abfd, bfd_object))
+ return false;
+
+ /* If we have already included the element containing this symbol in the
+ link then we do not need to include it again. Just claim that any symbol
+ it contains is not a definition, so that our caller will not decide to
+ (re)include this element. */
+ if (abfd->archive_pass)
+ return false;
+
+ /* Select the appropriate symbol table. */
+ if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ else
+ hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+
+ symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+
+ /* The sh_info field of the symtab header tells us where the
+ external symbols start. We don't care about the local symbols. */
+ if (elf_bad_symtab (abfd))
+ {
+ extsymcount = symcount;
+ extsymoff = 0;
+ }
+ else
+ {
+ extsymcount = symcount - hdr->sh_info;
+ extsymoff = hdr->sh_info;
+ }
+
+ buf = ((Elf_External_Sym *)
+ bfd_malloc (extsymcount * sizeof (Elf_External_Sym)));
+ if (buf == NULL && extsymcount != 0)
+ return false;
+
+ /* Read in the symbol table.
+ FIXME: This ought to be cached somewhere. */
+ if (bfd_seek (abfd,
+ hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
+ SEEK_SET) != 0
+ || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
+ != extsymcount * sizeof (Elf_External_Sym)))
+ {
+ free (buf);
+ return false;
+ }
+
+ /* Scan the symbol table looking for SYMDEF. */
+ esymend = buf + extsymcount;
+ for (esym = buf;
+ esym < esymend;
+ esym++)
+ {
+ Elf_Internal_Sym sym;
+ const char * name;
+
+ elf_swap_symbol_in (abfd, esym, & sym);
+
+ name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
+ if (name == (const char *) NULL)
+ break;
+
+ if (strcmp (name, symdef->name) == 0)
+ {
+ result = is_global_symbol_definition (abfd, & sym);
+ break;
+ }
+ }
+
+ free (buf);
+
+ return result;
+}
+\f