OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elflink.c] - Diff between revs 157 and 225

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 157 Rev 225
Line 1... Line 1...
/* ELF linking support for BFD.
/* ELF linking support for BFD.
   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
   2005, 2006, 2007, 2008, 2009
 
   Free Software Foundation, Inc.
 
 
   This file is part of BFD, the Binary File Descriptor library.
   This file is part of BFD, the Binary File Descriptor library.
 
 
   This program 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
   it under the terms of the GNU General Public License as published by
Line 27... Line 28...
#include "elf-bfd.h"
#include "elf-bfd.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#include "libiberty.h"
#include "libiberty.h"
#include "objalloc.h"
#include "objalloc.h"
 
 
 
/* This struct is used to pass information to routines called via
 
   elf_link_hash_traverse which must return failure.  */
 
 
 
struct elf_info_failed
 
{
 
  struct bfd_link_info *info;
 
  struct bfd_elf_version_tree *verdefs;
 
  bfd_boolean failed;
 
};
 
 
 
/* This structure is used to pass information to
 
   _bfd_elf_link_find_version_dependencies.  */
 
 
 
struct elf_find_verdep_info
 
{
 
  /* General link information.  */
 
  struct bfd_link_info *info;
 
  /* The number of dependencies.  */
 
  unsigned int vers;
 
  /* Whether we had a failure.  */
 
  bfd_boolean failed;
 
};
 
 
 
static bfd_boolean _bfd_elf_fix_symbol_flags
 
  (struct elf_link_hash_entry *, struct elf_info_failed *);
 
 
/* Define a symbol in a dynamic linkage section.  */
/* Define a symbol in a dynamic linkage section.  */
 
 
struct elf_link_hash_entry *
struct elf_link_hash_entry *
_bfd_elf_define_linkage_sym (bfd *abfd,
_bfd_elf_define_linkage_sym (bfd *abfd,
                             struct bfd_link_info *info,
                             struct bfd_link_info *info,
Line 72... Line 99...
{
{
  flagword flags;
  flagword flags;
  asection *s;
  asection *s;
  struct elf_link_hash_entry *h;
  struct elf_link_hash_entry *h;
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  int ptralign;
  struct elf_link_hash_table *htab = elf_hash_table (info);
 
 
  /* This function may be called more than once.  */
  /* This function may be called more than once.  */
  s = bfd_get_section_by_name (abfd, ".got");
  s = bfd_get_section_by_name (abfd, ".got");
  if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
  if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
    return TRUE;
    return TRUE;
 
 
  switch (bed->s->arch_size)
  flags = bed->dynamic_sec_flags;
    {
 
    case 32:
 
      ptralign = 2;
 
      break;
 
 
 
    case 64:
 
      ptralign = 3;
 
      break;
 
 
 
    default:
  s = bfd_make_section_with_flags (abfd,
      bfd_set_error (bfd_error_bad_value);
                                   (bed->rela_plts_and_copies_p
 
                                    ? ".rela.got" : ".rel.got"),
 
                                   (bed->dynamic_sec_flags
 
                                    | SEC_READONLY));
 
  if (s == NULL
 
      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
      return FALSE;
      return FALSE;
    }
  htab->srelgot = s;
 
 
  flags = bed->dynamic_sec_flags;
 
 
 
  s = bfd_make_section_with_flags (abfd, ".got", flags);
  s = bfd_make_section_with_flags (abfd, ".got", flags);
  if (s == NULL
  if (s == NULL
      || !bfd_set_section_alignment (abfd, s, ptralign))
      || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
    return FALSE;
    return FALSE;
 
  htab->sgot = s;
 
 
  if (bed->want_got_plt)
  if (bed->want_got_plt)
    {
    {
      s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
      s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
      if (s == NULL
      if (s == NULL
          || !bfd_set_section_alignment (abfd, s, ptralign))
          || !bfd_set_section_alignment (abfd, s,
 
                                         bed->s->log_file_align))
        return FALSE;
        return FALSE;
 
      htab->sgotplt = s;
    }
    }
 
 
 
  /* The first bit of the global offset table is the header.  */
 
  s->size += bed->got_header_size;
 
 
  if (bed->want_got_sym)
  if (bed->want_got_sym)
    {
    {
      /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
      /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
         (or .got.plt) section.  We don't do this in the linker script
         (or .got.plt) section.  We don't do this in the linker script
         because we don't want to define the symbol if we are not creating
         because we don't want to define the symbol if we are not creating
         a global offset table.  */
         a global offset table.  */
      h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
      h = _bfd_elf_define_linkage_sym (abfd, info, s,
 
                                       "_GLOBAL_OFFSET_TABLE_");
      elf_hash_table (info)->hgot = h;
      elf_hash_table (info)->hgot = h;
      if (h == NULL)
      if (h == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  /* The first bit of the global offset table is the header.  */
 
  s->size += bed->got_header_size;
 
 
 
  return TRUE;
  return TRUE;
}
}


/* Create a strtab to hold the dynamic symbol names.  */
/* Create a strtab to hold the dynamic symbol names.  */
static bfd_boolean
static bfd_boolean
Line 274... Line 300...
{
{
  flagword flags, pltflags;
  flagword flags, pltflags;
  struct elf_link_hash_entry *h;
  struct elf_link_hash_entry *h;
  asection *s;
  asection *s;
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
  struct elf_link_hash_table *htab = elf_hash_table (info);
 
 
  /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
  /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
     .rel[a].bss sections.  */
     .rel[a].bss sections.  */
  flags = bed->dynamic_sec_flags;
  flags = bed->dynamic_sec_flags;
 
 
Line 294... Line 321...
 
 
  s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
  s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
  if (s == NULL
  if (s == NULL
      || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
      || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
    return FALSE;
    return FALSE;
 
  htab->splt = s;
 
 
  /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
  /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
     .plt section.  */
     .plt section.  */
  if (bed->want_plt_sym)
  if (bed->want_plt_sym)
    {
    {
Line 307... Line 335...
      if (h == NULL)
      if (h == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  s = bfd_make_section_with_flags (abfd,
  s = bfd_make_section_with_flags (abfd,
                                   (bed->default_use_rela_p
                                   (bed->rela_plts_and_copies_p
                                    ? ".rela.plt" : ".rel.plt"),
                                    ? ".rela.plt" : ".rel.plt"),
                                   flags | SEC_READONLY);
                                   flags | SEC_READONLY);
  if (s == NULL
  if (s == NULL
      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
    return FALSE;
    return FALSE;
 
  htab->srelplt = s;
 
 
  if (! _bfd_elf_create_got_section (abfd, info))
  if (! _bfd_elf_create_got_section (abfd, info))
    return FALSE;
    return FALSE;
 
 
  if (bed->want_dynbss)
  if (bed->want_dynbss)
Line 345... Line 374...
         section when generating a shared object, since they do not use
         section when generating a shared object, since they do not use
         copy relocs.  */
         copy relocs.  */
      if (! info->shared)
      if (! info->shared)
        {
        {
          s = bfd_make_section_with_flags (abfd,
          s = bfd_make_section_with_flags (abfd,
                                           (bed->default_use_rela_p
                                           (bed->rela_plts_and_copies_p
                                            ? ".rela.bss" : ".rel.bss"),
                                            ? ".rela.bss" : ".rel.bss"),
                                           flags | SEC_READONLY);
                                           flags | SEC_READONLY);
          if (s == NULL
          if (s == NULL
              || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
              || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
            return FALSE;
            return FALSE;
Line 435... Line 464...
  return TRUE;
  return TRUE;
}
}


/* Mark a symbol dynamic.  */
/* Mark a symbol dynamic.  */
 
 
void
static void
bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
                                  struct elf_link_hash_entry *h,
                                  struct elf_link_hash_entry *h,
                                  Elf_Internal_Sym *sym)
                                  Elf_Internal_Sym *sym)
{
{
  struct bfd_elf_dynamic_list *d = info->dynamic_list;
  struct bfd_elf_dynamic_list *d = info->dynamic_list;
Line 603... Line 632...
  for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
  for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next)
    if (entry->input_bfd == input_bfd && entry->input_indx == input_indx)
    if (entry->input_bfd == input_bfd && entry->input_indx == input_indx)
      return 1;
      return 1;
 
 
  amt = sizeof (*entry);
  amt = sizeof (*entry);
  entry = bfd_alloc (input_bfd, amt);
  entry = (struct elf_link_local_dynamic_entry *) bfd_alloc (input_bfd, amt);
  if (entry == NULL)
  if (entry == NULL)
    return 0;
    return 0;
 
 
  /* Go find the symbol, so that we can find it's name.  */
  /* Go find the symbol, so that we can find it's name.  */
  if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr,
  if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr,
Line 616... Line 645...
      bfd_release (input_bfd, entry);
      bfd_release (input_bfd, entry);
      return 0;
      return 0;
    }
    }
 
 
  if (entry->isym.st_shndx != SHN_UNDEF
  if (entry->isym.st_shndx != SHN_UNDEF
      && (entry->isym.st_shndx < SHN_LORESERVE
      && entry->isym.st_shndx < SHN_LORESERVE)
          || entry->isym.st_shndx > SHN_HIRESERVE))
 
    {
    {
      asection *s;
      asection *s;
 
 
      s = bfd_section_from_elf_index (input_bfd, entry->isym.st_shndx);
      s = bfd_section_from_elf_index (input_bfd, entry->isym.st_shndx);
      if (s == NULL || bfd_is_abs_section (s->output_section))
      if (s == NULL || bfd_is_abs_section (s->output_section))
Line 689... Line 717...
 
 
static bfd_boolean
static bfd_boolean
elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h,
elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h,
                                      void *data)
                                      void *data)
{
{
  size_t *count = data;
  size_t *count = (size_t *) data;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 
  if (h->forced_local)
  if (h->forced_local)
Line 711... Line 739...
 
 
static bfd_boolean
static bfd_boolean
elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h,
                                            void *data)
                                            void *data)
{
{
  size_t *count = data;
  size_t *count = (size_t *) data;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 
  if (!h->forced_local)
  if (!h->forced_local)
Line 821... Line 849...
 
 
  elf_hash_table (info)->dynsymcount = dynsymcount;
  elf_hash_table (info)->dynsymcount = dynsymcount;
  return dynsymcount;
  return dynsymcount;
}
}
 
 
 
/* Merge st_other field.  */
 
 
 
static void
 
elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
 
                    Elf_Internal_Sym *isym, bfd_boolean definition,
 
                    bfd_boolean dynamic)
 
{
 
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
 
 
  /* If st_other has a processor-specific meaning, specific
 
     code might be needed here. We never merge the visibility
 
     attribute with the one from a dynamic object.  */
 
  if (bed->elf_backend_merge_symbol_attribute)
 
    (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
 
                                                dynamic);
 
 
 
  /* If this symbol has default visibility and the user has requested
 
     we not re-export it, then mark it as hidden.  */
 
  if (definition
 
      && !dynamic
 
      && (abfd->no_export
 
          || (abfd->my_archive && abfd->my_archive->no_export))
 
      && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
 
    isym->st_other = (STV_HIDDEN
 
                      | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
 
 
 
  if (!dynamic && ELF_ST_VISIBILITY (isym->st_other) != 0)
 
    {
 
      unsigned char hvis, symvis, other, nvis;
 
 
 
      /* Only merge the visibility. Leave the remainder of the
 
         st_other field to elf_backend_merge_symbol_attribute.  */
 
      other = h->other & ~ELF_ST_VISIBILITY (-1);
 
 
 
      /* Combine visibilities, using the most constraining one.  */
 
      hvis = ELF_ST_VISIBILITY (h->other);
 
      symvis = ELF_ST_VISIBILITY (isym->st_other);
 
      if (! hvis)
 
        nvis = symvis;
 
      else if (! symvis)
 
        nvis = hvis;
 
      else
 
        nvis = hvis < symvis ? hvis : symvis;
 
 
 
      h->other = other | nvis;
 
    }
 
}
 
 
/* This function is called when we want to define a new symbol.  It
/* This function is called when we want to define a new symbol.  It
   handles the various cases which arise when we find a definition in
   handles the various cases which arise when we find a definition in
   a dynamic object, or when there is already a definition in a
   a dynamic object, or when there is already a definition in a
   dynamic object.  The new symbol is described by NAME, SYM, PSEC,
   dynamic object.  The new symbol is described by NAME, SYM, PSEC,
   and PVALUE.  We set SYM_HASH to the hash table entry.  We set
   and PVALUE.  We set SYM_HASH to the hash table entry.  We set
Line 853... Line 929...
  struct elf_link_hash_entry *h;
  struct elf_link_hash_entry *h;
  struct elf_link_hash_entry *flip;
  struct elf_link_hash_entry *flip;
  int bind;
  int bind;
  bfd *oldbfd;
  bfd *oldbfd;
  bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
  bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
  bfd_boolean newweak, oldweak;
  bfd_boolean newweak, oldweak, newfunc, oldfunc;
  const struct elf_backend_data *bed;
  const struct elf_backend_data *bed;
 
 
  *skip = FALSE;
  *skip = FALSE;
  *override = FALSE;
  *override = FALSE;
 
 
Line 880... Line 956...
         bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, FALSE, FALSE));
         bfd_wrapped_link_hash_lookup (abfd, info, name, TRUE, FALSE, FALSE));
  if (h == NULL)
  if (h == NULL)
    return FALSE;
    return FALSE;
  *sym_hash = h;
  *sym_hash = h;
 
 
 
  bed = get_elf_backend_data (abfd);
 
 
  /* This code is for coping with dynamic objects, and is only useful
  /* This code is for coping with dynamic objects, and is only useful
     if we are doing an ELF link.  */
     if we are doing an ELF link.  */
  if (info->output_bfd->xvec != abfd->xvec)
  if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
    return TRUE;
    return TRUE;
 
 
  /* For merging, we only care about real symbols.  */
  /* For merging, we only care about real symbols.  */
 
 
  while (h->root.type == bfd_link_hash_indirect
  while (h->root.type == bfd_link_hash_indirect
Line 969... Line 1047...
 
 
  olddef = (h->root.type != bfd_link_hash_undefined
  olddef = (h->root.type != bfd_link_hash_undefined
            && h->root.type != bfd_link_hash_undefweak
            && h->root.type != bfd_link_hash_undefweak
            && h->root.type != bfd_link_hash_common);
            && h->root.type != bfd_link_hash_common);
 
 
  bed = get_elf_backend_data (abfd);
  /* NEWFUNC and OLDFUNC indicate whether the new or old symbol,
 
     respectively, appear to be a function.  */
 
 
 
  newfunc = (ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
 
             && bed->is_function_type (ELF_ST_TYPE (sym->st_info)));
 
 
 
  oldfunc = (h->type != STT_NOTYPE
 
             && bed->is_function_type (h->type));
 
 
  /* When we try to create a default indirect symbol from the dynamic
  /* When we try to create a default indirect symbol from the dynamic
     definition with the default version, we skip it if its type and
     definition with the default version, we skip it if its type and
     the type of existing regular definition mismatch.  We only do it
     the type of existing regular definition mismatch.  We only do it
     if the existing regular definition won't be dynamic.  */
     if the existing regular definition won't be dynamic.  */
  if (pold_alignment == NULL
  if (pold_alignment == NULL
Line 985... Line 1071...
      && !olddyn
      && !olddyn
      && (olddef || h->root.type == bfd_link_hash_common)
      && (olddef || h->root.type == bfd_link_hash_common)
      && ELF_ST_TYPE (sym->st_info) != h->type
      && ELF_ST_TYPE (sym->st_info) != h->type
      && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
      && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
      && h->type != STT_NOTYPE
      && h->type != STT_NOTYPE
      && !(bed->is_function_type (ELF_ST_TYPE (sym->st_info))
      && !(newfunc && oldfunc))
           && bed->is_function_type (h->type)))
 
    {
    {
      *skip = TRUE;
      *skip = TRUE;
      return TRUE;
      return TRUE;
    }
    }
 
 
Line 1161... Line 1246...
  /* Differentiate strong and weak symbols.  */
  /* Differentiate strong and weak symbols.  */
  newweak = bind == STB_WEAK;
  newweak = bind == STB_WEAK;
  oldweak = (h->root.type == bfd_link_hash_defweak
  oldweak = (h->root.type == bfd_link_hash_defweak
             || h->root.type == bfd_link_hash_undefweak);
             || h->root.type == bfd_link_hash_undefweak);
 
 
 
  if (bind == STB_GNU_UNIQUE)
 
    h->unique_global = 1;
 
 
  /* If a new weak symbol definition comes from a regular file and the
  /* If a new weak symbol definition comes from a regular file and the
     old symbol comes from a dynamic library, we treat the new one as
     old symbol comes from a dynamic library, we treat the new one as
     strong.  Similarly, an old weak symbol definition from a regular
     strong.  Similarly, an old weak symbol definition from a regular
     file is treated as strong when the new symbol comes from a dynamic
     file is treated as strong when the new symbol comes from a dynamic
     library.  Further, an old weak symbol from a dynamic library is
     library.  Further, an old weak symbol from a dynamic library is
Line 1177... Line 1265...
  if (newdef && !newdyn && olddyn)
  if (newdef && !newdyn && olddyn)
    newweak = FALSE;
    newweak = FALSE;
  if (olddef && newdyn)
  if (olddef && newdyn)
    oldweak = FALSE;
    oldweak = FALSE;
 
 
  /* Allow changes between different types of funciton symbol.  */
  /* Allow changes between different types of function symbol.  */
  if (bed->is_function_type (ELF_ST_TYPE (sym->st_info))
  if (newfunc && oldfunc)
      && bed->is_function_type (h->type))
 
    *type_change_ok = TRUE;
    *type_change_ok = TRUE;
 
 
  /* It's OK to change the type if either the existing symbol or the
  /* It's OK to change the type if either the existing symbol or the
     new symbol is weak.  A type change is also OK if the old symbol
     new symbol is weak.  A type change is also OK if the old symbol
     is undefined and the new symbol is defined.  */
     is undefined and the new symbol is defined.  */
Line 1228... Line 1315...
      && newdef
      && newdef
      && !newweak
      && !newweak
      && (sec->flags & SEC_ALLOC) != 0
      && (sec->flags & SEC_ALLOC) != 0
      && (sec->flags & SEC_LOAD) == 0
      && (sec->flags & SEC_LOAD) == 0
      && sym->st_size > 0
      && sym->st_size > 0
      && !bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
      && !newfunc)
    newdyncommon = TRUE;
    newdyncommon = TRUE;
  else
  else
    newdyncommon = FALSE;
    newdyncommon = FALSE;
 
 
  if (olddyn
  if (olddyn
Line 1240... Line 1327...
      && h->root.type == bfd_link_hash_defined
      && h->root.type == bfd_link_hash_defined
      && h->def_dynamic
      && h->def_dynamic
      && (h->root.u.def.section->flags & SEC_ALLOC) != 0
      && (h->root.u.def.section->flags & SEC_ALLOC) != 0
      && (h->root.u.def.section->flags & SEC_LOAD) == 0
      && (h->root.u.def.section->flags & SEC_LOAD) == 0
      && h->size > 0
      && h->size > 0
      && !bed->is_function_type (h->type))
      && !oldfunc)
    olddyncommon = TRUE;
    olddyncommon = TRUE;
  else
  else
    olddyncommon = FALSE;
    olddyncommon = FALSE;
 
 
  /* We now know everything about the old and new symbols.  We ask the
  /* We now know everything about the old and new symbols.  We ask the
Line 1300... Line 1387...
 
 
  if (newdyn
  if (newdyn
      && newdef
      && newdef
      && (olddef
      && (olddef
          || (h->root.type == bfd_link_hash_common
          || (h->root.type == bfd_link_hash_common
              && (newweak
              && (newweak || newfunc))))
                  || bed->is_function_type (ELF_ST_TYPE (sym->st_info))))))
 
    {
    {
      *override = TRUE;
      *override = TRUE;
      newdef = FALSE;
      newdef = FALSE;
      newdyncommon = FALSE;
      newdyncommon = FALSE;
 
 
Line 1339... Line 1425...
      *size_change_ok = TRUE;
      *size_change_ok = TRUE;
    }
    }
 
 
  /* Skip weak definitions of symbols that are already defined.  */
  /* Skip weak definitions of symbols that are already defined.  */
  if (newdef && olddef && newweak)
  if (newdef && olddef && newweak)
 
    {
    *skip = TRUE;
    *skip = TRUE;
 
 
 
      /* Merge st_other.  If the symbol already has a dynamic index,
 
         but visibility says it should not be visible, turn it into a
 
         local symbol.  */
 
      elf_merge_st_other (abfd, h, sym, newdef, newdyn);
 
      if (h->dynindx != -1)
 
        switch (ELF_ST_VISIBILITY (h->other))
 
          {
 
          case STV_INTERNAL:
 
          case STV_HIDDEN:
 
            (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 
            break;
 
          }
 
    }
 
 
  /* If the old symbol is from a dynamic object, and the new symbol is
  /* If the old symbol is from a dynamic object, and the new symbol is
     a definition which is not from a dynamic object, then the new
     a definition which is not from a dynamic object, then the new
     symbol overrides the old symbol.  Symbols from regular files
     symbol overrides the old symbol.  Symbols from regular files
     always take precedence over symbols from dynamic objects, even if
     always take precedence over symbols from dynamic objects, even if
     they are defined after the dynamic object in the link.
     they are defined after the dynamic object in the link.
Line 1355... Line 1456...
 
 
  flip = NULL;
  flip = NULL;
  if (!newdyn
  if (!newdyn
      && (newdef
      && (newdef
          || (bfd_is_com_section (sec)
          || (bfd_is_com_section (sec)
              && (oldweak
              && (oldweak || oldfunc)))
                  || bed->is_function_type (h->type))))
 
      && olddyn
      && olddyn
      && olddef
      && olddef
      && h->def_dynamic)
      && h->def_dynamic)
    {
    {
      /* Change the hash table entry to undefined, and let
      /* Change the hash table entry to undefined, and let
Line 1376... Line 1476...
 
 
      /* We again permit a type change when a common symbol may be
      /* We again permit a type change when a common symbol may be
         overriding a function.  */
         overriding a function.  */
 
 
      if (bfd_is_com_section (sec))
      if (bfd_is_com_section (sec))
 
        {
 
          if (oldfunc)
 
            {
 
              /* If a common symbol overrides a function, make sure
 
                 that it isn't defined dynamically nor has type
 
                 function.  */
 
              h->def_dynamic = 0;
 
              h->type = STT_NOTYPE;
 
            }
        *type_change_ok = TRUE;
        *type_change_ok = TRUE;
 
        }
 
 
      if ((*sym_hash)->root.type == bfd_link_hash_indirect)
      if ((*sym_hash)->root.type == bfd_link_hash_indirect)
        flip = *sym_hash;
        flip = *sym_hash;
      else
      else
        /* This union may have been set to be non-NULL when this symbol
        /* This union may have been set to be non-NULL when this symbol
Line 1457... Line 1567...
/* This function is called to create an indirect symbol from the
/* This function is called to create an indirect symbol from the
   default for the symbol with the default version if needed. The
   default for the symbol with the default version if needed. The
   symbol is described by H, NAME, SYM, PSEC, VALUE, and OVERRIDE.  We
   symbol is described by H, NAME, SYM, PSEC, VALUE, and OVERRIDE.  We
   set DYNSYM if the new indirect symbol is dynamic.  */
   set DYNSYM if the new indirect symbol is dynamic.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_add_default_symbol (bfd *abfd,
_bfd_elf_add_default_symbol (bfd *abfd,
                             struct bfd_link_info *info,
                             struct bfd_link_info *info,
                             struct elf_link_hash_entry *h,
                             struct elf_link_hash_entry *h,
                             const char *name,
                             const char *name,
                             Elf_Internal_Sym *sym,
                             Elf_Internal_Sym *sym,
Line 1512... Line 1622...
  bed = get_elf_backend_data (abfd);
  bed = get_elf_backend_data (abfd);
  collect = bed->collect;
  collect = bed->collect;
  dynamic = (abfd->flags & DYNAMIC) != 0;
  dynamic = (abfd->flags & DYNAMIC) != 0;
 
 
  shortlen = p - name;
  shortlen = p - name;
  shortname = bfd_hash_allocate (&info->hash->table, shortlen + 1);
  shortname = (char *) bfd_hash_allocate (&info->hash->table, shortlen + 1);
  if (shortname == NULL)
  if (shortname == NULL)
    return FALSE;
    return FALSE;
  memcpy (shortname, name, shortlen);
  memcpy (shortname, name, shortlen);
  shortname[shortlen] = '\0';
  shortname[shortlen] = '\0';
 
 
Line 1623... Line 1733...
  /* We also need to define an indirection from the nondefault version
  /* We also need to define an indirection from the nondefault version
     of the symbol.  */
     of the symbol.  */
 
 
nondefault:
nondefault:
  len = strlen (name);
  len = strlen (name);
  shortname = bfd_hash_allocate (&info->hash->table, len);
  shortname = (char *) bfd_hash_allocate (&info->hash->table, len);
  if (shortname == NULL)
  if (shortname == NULL)
    return FALSE;
    return FALSE;
  memcpy (shortname, name, shortlen);
  memcpy (shortname, name, shortlen);
  memcpy (shortname + shortlen, p + 1, len - shortlen);
  memcpy (shortname + shortlen, p + 1, len - shortlen);
 
 
Line 1694... Line 1804...
}
}


/* This routine is used to export all defined symbols into the dynamic
/* This routine is used to export all defined symbols into the dynamic
   symbol table.  It is called via elf_link_hash_traverse.  */
   symbol table.  It is called via elf_link_hash_traverse.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
_bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
{
{
  struct elf_info_failed *eif = data;
  struct elf_info_failed *eif = (struct elf_info_failed *) data;
 
 
  /* Ignore this if we won't export it.  */
  /* Ignore this if we won't export it.  */
  if (!eif->info->export_dynamic && !h->dynamic)
  if (!eif->info->export_dynamic && !h->dynamic)
    return TRUE;
    return TRUE;
 
 
Line 1714... Line 1824...
 
 
  if (h->dynindx == -1
  if (h->dynindx == -1
      && (h->def_regular
      && (h->def_regular
          || h->ref_regular))
          || h->ref_regular))
    {
    {
      struct bfd_elf_version_tree *t;
      bfd_boolean hide;
      struct bfd_elf_version_expr *d;
 
 
 
      for (t = eif->verdefs; t != NULL; t = t->next)
      if (eif->verdefs == NULL
        {
          || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
          if (t->globals.list != NULL)
              && !hide))
            {
            {
              d = (*t->match) (&t->globals, NULL, h->root.root.string);
 
              if (d != NULL)
 
                goto doit;
 
            }
 
 
 
          if (t->locals.list != NULL)
 
            {
 
              d = (*t->match) (&t->locals, NULL, h->root.root.string);
 
              if (d != NULL)
 
                return TRUE;
 
            }
 
        }
 
 
 
      if (!eif->verdefs)
 
        {
 
        doit:
 
          if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
          if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
            {
            {
              eif->failed = TRUE;
              eif->failed = TRUE;
              return FALSE;
              return FALSE;
            }
            }
Line 1753... Line 1846...
/* Look through the symbols which are defined in other shared
/* Look through the symbols which are defined in other shared
   libraries and referenced here.  Update the list of version
   libraries and referenced here.  Update the list of version
   dependencies.  This will be put into the .gnu.version_r section.
   dependencies.  This will be put into the .gnu.version_r section.
   This function is called via elf_link_hash_traverse.  */
   This function is called via elf_link_hash_traverse.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
_bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h,
                                         void *data)
                                         void *data)
{
{
  struct elf_find_verdep_info *rinfo = data;
  struct elf_find_verdep_info *rinfo = (struct elf_find_verdep_info *) data;
  Elf_Internal_Verneed *t;
  Elf_Internal_Verneed *t;
  Elf_Internal_Vernaux *a;
  Elf_Internal_Vernaux *a;
  bfd_size_type amt;
  bfd_size_type amt;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
Line 1774... Line 1867...
      || h->dynindx == -1
      || h->dynindx == -1
      || h->verinfo.verdef == NULL)
      || h->verinfo.verdef == NULL)
    return TRUE;
    return TRUE;
 
 
  /* See if we already know about this version.  */
  /* See if we already know about this version.  */
  for (t = elf_tdata (rinfo->output_bfd)->verref; t != NULL; t = t->vn_nextref)
  for (t = elf_tdata (rinfo->info->output_bfd)->verref;
 
       t != NULL;
 
       t = t->vn_nextref)
    {
    {
      if (t->vn_bfd != h->verinfo.verdef->vd_bfd)
      if (t->vn_bfd != h->verinfo.verdef->vd_bfd)
        continue;
        continue;
 
 
      for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
      for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
Line 1791... Line 1886...
  /* This is a new version.  Add it to tree we are building.  */
  /* This is a new version.  Add it to tree we are building.  */
 
 
  if (t == NULL)
  if (t == NULL)
    {
    {
      amt = sizeof *t;
      amt = sizeof *t;
      t = bfd_zalloc (rinfo->output_bfd, amt);
      t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd, amt);
      if (t == NULL)
      if (t == NULL)
        {
        {
          rinfo->failed = TRUE;
          rinfo->failed = TRUE;
          return FALSE;
          return FALSE;
        }
        }
 
 
      t->vn_bfd = h->verinfo.verdef->vd_bfd;
      t->vn_bfd = h->verinfo.verdef->vd_bfd;
      t->vn_nextref = elf_tdata (rinfo->output_bfd)->verref;
      t->vn_nextref = elf_tdata (rinfo->info->output_bfd)->verref;
      elf_tdata (rinfo->output_bfd)->verref = t;
      elf_tdata (rinfo->info->output_bfd)->verref = t;
    }
    }
 
 
  amt = sizeof *a;
  amt = sizeof *a;
  a = bfd_zalloc (rinfo->output_bfd, amt);
  a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt);
  if (a == NULL)
  if (a == NULL)
    {
    {
      rinfo->failed = TRUE;
      rinfo->failed = TRUE;
      return FALSE;
      return FALSE;
    }
    }
Line 1835... Line 1930...
/* Figure out appropriate versions for all the symbols.  We may not
/* Figure out appropriate versions for all the symbols.  We may not
   have the version number script until we have read all of the input
   have the version number script until we have read all of the input
   files, so until that point we don't know which symbols should be
   files, so until that point we don't know which symbols should be
   local.  This function is called via elf_link_hash_traverse.  */
   local.  This function is called via elf_link_hash_traverse.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
_bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
{
{
  struct elf_assign_sym_version_info *sinfo;
  struct elf_info_failed *sinfo;
  struct bfd_link_info *info;
  struct bfd_link_info *info;
  const struct elf_backend_data *bed;
  const struct elf_backend_data *bed;
  struct elf_info_failed eif;
  struct elf_info_failed eif;
  char *p;
  char *p;
  bfd_size_type amt;
  bfd_size_type amt;
 
 
  sinfo = data;
  sinfo = (struct elf_info_failed *) data;
  info = sinfo->info;
  info = sinfo->info;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 
Line 1866... Line 1961...
  /* We only need version numbers for symbols defined in regular
  /* We only need version numbers for symbols defined in regular
     objects.  */
     objects.  */
  if (!h->def_regular)
  if (!h->def_regular)
    return TRUE;
    return TRUE;
 
 
  bed = get_elf_backend_data (sinfo->output_bfd);
  bed = get_elf_backend_data (info->output_bfd);
  p = strchr (h->root.root.string, ELF_VER_CHR);
  p = strchr (h->root.root.string, ELF_VER_CHR);
  if (p != NULL && h->verinfo.vertree == NULL)
  if (p != NULL && h->verinfo.vertree == NULL)
    {
    {
      struct bfd_elf_version_tree *t;
      struct bfd_elf_version_tree *t;
      bfd_boolean hidden;
      bfd_boolean hidden;
Line 1902... Line 1997...
              size_t len;
              size_t len;
              char *alc;
              char *alc;
              struct bfd_elf_version_expr *d;
              struct bfd_elf_version_expr *d;
 
 
              len = p - h->root.root.string;
              len = p - h->root.root.string;
              alc = bfd_malloc (len);
              alc = (char *) bfd_malloc (len);
              if (alc == NULL)
              if (alc == NULL)
                {
                {
                  sinfo->failed = TRUE;
                  sinfo->failed = TRUE;
                  return FALSE;
                  return FALSE;
                }
                }
Line 1949... Line 2044...
             to worry about it.  */
             to worry about it.  */
          if (h->dynindx == -1)
          if (h->dynindx == -1)
            return TRUE;
            return TRUE;
 
 
          amt = sizeof *t;
          amt = sizeof *t;
          t = bfd_zalloc (sinfo->output_bfd, amt);
          t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, amt);
          if (t == NULL)
          if (t == NULL)
            {
            {
              sinfo->failed = TRUE;
              sinfo->failed = TRUE;
              return FALSE;
              return FALSE;
            }
            }
Line 1978... Line 2073...
        {
        {
          /* We could not find the version for a symbol when
          /* We could not find the version for a symbol when
             generating a shared archive.  Return an error.  */
             generating a shared archive.  Return an error.  */
          (*_bfd_error_handler)
          (*_bfd_error_handler)
            (_("%B: version node not found for symbol %s"),
            (_("%B: version node not found for symbol %s"),
             sinfo->output_bfd, h->root.root.string);
             info->output_bfd, h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
          bfd_set_error (bfd_error_bad_value);
          sinfo->failed = TRUE;
          sinfo->failed = TRUE;
          return FALSE;
          return FALSE;
        }
        }
 
 
Line 1992... Line 2087...
 
 
  /* If we don't have a version for this symbol, see if we can find
  /* If we don't have a version for this symbol, see if we can find
     something.  */
     something.  */
  if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL)
  if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL)
    {
    {
      struct bfd_elf_version_tree *t;
      bfd_boolean hide;
      struct bfd_elf_version_tree *local_ver;
 
      struct bfd_elf_version_expr *d;
 
 
 
      /* See if can find what version this symbol is in.  If the
 
         symbol is supposed to be local, then don't actually register
 
         it.  */
 
      local_ver = NULL;
 
      for (t = sinfo->verdefs; t != NULL; t = t->next)
 
        {
 
          if (t->globals.list != NULL)
 
            {
 
              bfd_boolean matched;
 
 
 
              matched = FALSE;
      h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs,
              d = NULL;
                                                 h->root.root.string, &hide);
              while ((d = (*t->match) (&t->globals, d,
      if (h->verinfo.vertree != NULL && hide)
                                       h->root.root.string)) != NULL)
 
                if (d->symver)
 
                  matched = TRUE;
 
                else
 
                  {
 
                    /* There is a version without definition.  Make
 
                       the symbol the default definition for this
 
                       version.  */
 
                    h->verinfo.vertree = t;
 
                    local_ver = NULL;
 
                    d->script = 1;
 
                    break;
 
                  }
 
              if (d != NULL)
 
                break;
 
              else if (matched)
 
                /* There is no undefined version for this symbol. Hide the
 
                   default one.  */
 
                (*bed->elf_backend_hide_symbol) (info, h, TRUE);
                (*bed->elf_backend_hide_symbol) (info, h, TRUE);
            }
            }
 
 
          if (t->locals.list != NULL)
 
            {
 
              d = NULL;
 
              while ((d = (*t->match) (&t->locals, d,
 
                                       h->root.root.string)) != NULL)
 
                {
 
                  local_ver = t;
 
                  /* If the match is "*", keep looking for a more
 
                     explicit, perhaps even global, match.
 
                     XXX: Shouldn't this be !d->wildcard instead?  */
 
                  if (d->pattern[0] != '*' || d->pattern[1] != '\0')
 
                    break;
 
                }
 
 
 
              if (d != NULL)
 
                break;
 
            }
 
        }
 
 
 
      if (local_ver != NULL)
 
        {
 
          h->verinfo.vertree = local_ver;
 
          if (h->dynindx != -1
 
              && ! info->export_dynamic)
 
            {
 
              (*bed->elf_backend_hide_symbol) (info, h, TRUE);
 
            }
 
        }
 
    }
 
 
 
  return TRUE;
  return TRUE;
}
}


/* Read and swap the relocs from the section indicated by SHDR.  This
/* Read and swap the relocs from the section indicated by SHDR.  This
   may be either a REL or a RELA section.  The relocations are
   may be either a REL or a RELA section.  The relocations are
Line 2096... Line 2131...
  /* Read the relocations.  */
  /* Read the relocations.  */
  if (bfd_bread (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
  if (bfd_bread (external_relocs, shdr->sh_size, abfd) != shdr->sh_size)
    return FALSE;
    return FALSE;
 
 
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  nsyms = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
  nsyms = NUM_SHDR_ENTRIES (symtab_hdr);
 
 
  bed = get_elf_backend_data (abfd);
  bed = get_elf_backend_data (abfd);
 
 
  /* Convert the external relocations to the internal format.  */
  /* Convert the external relocations to the internal format.  */
  if (shdr->sh_entsize == bed->s->sizeof_rel)
  if (shdr->sh_entsize == bed->s->sizeof_rel)
Line 2111... Line 2146...
    {
    {
      bfd_set_error (bfd_error_wrong_format);
      bfd_set_error (bfd_error_wrong_format);
      return FALSE;
      return FALSE;
    }
    }
 
 
  erela = external_relocs;
  erela = (const bfd_byte *) external_relocs;
  erelaend = erela + shdr->sh_size;
  erelaend = erela + shdr->sh_size;
  irela = internal_relocs;
  irela = internal_relocs;
  while (erela < erelaend)
  while (erela < erelaend)
    {
    {
      bfd_vma r_symndx;
      bfd_vma r_symndx;
 
 
      (*swap_in) (abfd, erela, irela);
      (*swap_in) (abfd, erela, irela);
      r_symndx = ELF32_R_SYM (irela->r_info);
      r_symndx = ELF32_R_SYM (irela->r_info);
      if (bed->s->arch_size == 64)
      if (bed->s->arch_size == 64)
        r_symndx >>= 24;
        r_symndx >>= 24;
 
      if (nsyms > 0)
 
        {
      if ((size_t) r_symndx >= nsyms)
      if ((size_t) r_symndx >= nsyms)
        {
        {
          (*_bfd_error_handler)
          (*_bfd_error_handler)
            (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
            (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
               " for offset 0x%lx in section `%A'"),
               " for offset 0x%lx in section `%A'"),
             abfd, sec,
             abfd, sec,
             (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
             (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
          bfd_set_error (bfd_error_bad_value);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
          return FALSE;
        }
        }
 
        }
 
      else if (r_symndx != 0)
 
        {
 
          (*_bfd_error_handler)
 
            (_("%B: non-zero symbol index (0x%lx) for offset 0x%lx in section `%A'"
 
               " when the object file has no symbol table"),
 
             abfd, sec,
 
             (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
 
          bfd_set_error (bfd_error_bad_value);
 
          return FALSE;
 
        }
      irela += bed->s->int_rels_per_ext_rel;
      irela += bed->s->int_rels_per_ext_rel;
      erela += shdr->sh_entsize;
      erela += shdr->sh_entsize;
    }
    }
 
 
  return TRUE;
  return TRUE;
Line 2176... Line 2224...
      bfd_size_type size;
      bfd_size_type size;
 
 
      size = o->reloc_count;
      size = o->reloc_count;
      size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
      size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
      if (keep_memory)
      if (keep_memory)
        internal_relocs = bfd_alloc (abfd, size);
        internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
      else
      else
        internal_relocs = alloc2 = bfd_malloc (size);
        internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
      if (internal_relocs == NULL)
      if (internal_relocs == NULL)
        goto error_return;
        goto error_return;
    }
    }
 
 
  if (external_relocs == NULL)
  if (external_relocs == NULL)
Line 2224... Line 2272...
 
 
 error_return:
 error_return:
  if (alloc1 != NULL)
  if (alloc1 != NULL)
    free (alloc1);
    free (alloc1);
  if (alloc2 != NULL)
  if (alloc2 != NULL)
 
    {
 
      if (keep_memory)
 
        bfd_release (abfd, alloc2);
 
      else
    free (alloc2);
    free (alloc2);
 
    }
  return NULL;
  return NULL;
}
}
 
 
/* Compute the size of, and allocate space for, REL_HDR which is the
/* Compute the size of, and allocate space for, REL_HDR which is the
   section header for a section containing relocations for O.  */
   section header for a section containing relocations for O.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_link_size_reloc_section (bfd *abfd,
_bfd_elf_link_size_reloc_section (bfd *abfd,
                                  Elf_Internal_Shdr *rel_hdr,
                                  Elf_Internal_Shdr *rel_hdr,
                                  asection *o)
                                  asection *o)
{
{
  bfd_size_type reloc_count;
  bfd_size_type reloc_count;
Line 2256... Line 2309...
 
 
  /* The contents field must last into write_object_contents, so we
  /* The contents field must last into write_object_contents, so we
     allocate it with bfd_alloc rather than malloc.  Also since we
     allocate it with bfd_alloc rather than malloc.  Also since we
     cannot be sure that the contents will actually be filled in,
     cannot be sure that the contents will actually be filled in,
     we zero the allocated space.  */
     we zero the allocated space.  */
  rel_hdr->contents = bfd_zalloc (abfd, rel_hdr->sh_size);
  rel_hdr->contents = (unsigned char *) bfd_zalloc (abfd, rel_hdr->sh_size);
  if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
  if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
    return FALSE;
    return FALSE;
 
 
  /* We only allocate one set of hash entries, so we only do it the
  /* We only allocate one set of hash entries, so we only do it the
     first time we are called.  */
     first time we are called.  */
  if (elf_section_data (o)->rel_hashes == NULL
  if (elf_section_data (o)->rel_hashes == NULL
      && num_rel_hashes)
      && num_rel_hashes)
    {
    {
      struct elf_link_hash_entry **p;
      struct elf_link_hash_entry **p;
 
 
      p = bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *));
      p = (struct elf_link_hash_entry **)
 
          bfd_zmalloc (num_rel_hashes * sizeof (struct elf_link_hash_entry *));
      if (p == NULL)
      if (p == NULL)
        return FALSE;
        return FALSE;
 
 
      elf_section_data (o)->rel_hashes = p;
      elf_section_data (o)->rel_hashes = p;
    }
    }
Line 2370... Line 2424...
   can only be fixed after all the input files are seen.  This is
   can only be fixed after all the input files are seen.  This is
   currently called by both adjust_dynamic_symbol and
   currently called by both adjust_dynamic_symbol and
   assign_sym_version, which is unnecessary but perhaps more robust in
   assign_sym_version, which is unnecessary but perhaps more robust in
   the face of future changes.  */
   the face of future changes.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
_bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h,
                           struct elf_info_failed *eif)
                           struct elf_info_failed *eif)
{
{
  const struct elf_backend_data *bed;
  const struct elf_backend_data *bed;
 
 
Line 2513... Line 2567...
 
 
/* Make the backend pick a good value for a dynamic symbol.  This is
/* Make the backend pick a good value for a dynamic symbol.  This is
   called via elf_link_hash_traverse, and also calls itself
   called via elf_link_hash_traverse, and also calls itself
   recursively.  */
   recursively.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
_bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
{
{
  struct elf_info_failed *eif = data;
  struct elf_info_failed *eif = (struct elf_info_failed *) data;
  bfd *dynobj;
  bfd *dynobj;
  const struct elf_backend_data *bed;
  const struct elf_backend_data *bed;
 
 
  if (! is_elf_hash_table (eif->info->hash))
  if (! is_elf_hash_table (eif->info->hash))
    return FALSE;
    return FALSE;
Line 2550... Line 2604...
     even if no regular object refers to it, if we decided to add it
     even if no regular object refers to it, if we decided to add it
     to the dynamic symbol table.  FIXME: Do we normally need to worry
     to the dynamic symbol table.  FIXME: Do we normally need to worry
     about symbols which are defined by one dynamic object and
     about symbols which are defined by one dynamic object and
     referenced by another one?  */
     referenced by another one?  */
  if (!h->needs_plt
  if (!h->needs_plt
 
      && h->type != STT_GNU_IFUNC
      && (h->def_regular
      && (h->def_regular
          || !h->def_dynamic
          || !h->def_dynamic
          || (!h->ref_regular
          || (!h->ref_regular
              && (h->u.weakdef == NULL || h->u.weakdef->dynindx == -1))))
              && (h->u.weakdef == NULL || h->u.weakdef->dynindx == -1))))
    {
    {
Line 2624... Line 2679...
      (_("warning: type and size of dynamic symbol `%s' are not defined"),
      (_("warning: type and size of dynamic symbol `%s' are not defined"),
       h->root.root.string);
       h->root.root.string);
 
 
  dynobj = elf_hash_table (eif->info)->dynobj;
  dynobj = elf_hash_table (eif->info)->dynobj;
  bed = get_elf_backend_data (dynobj);
  bed = get_elf_backend_data (dynobj);
 
 
  if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
  if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
    {
    {
      eif->failed = TRUE;
      eif->failed = TRUE;
      return FALSE;
      return FALSE;
    }
    }
Line 2682... Line 2738...
}
}
 
 
/* Adjust all external symbols pointing into SEC_MERGE sections
/* Adjust all external symbols pointing into SEC_MERGE sections
   to reflect the object merging within the sections.  */
   to reflect the object merging within the sections.  */
 
 
bfd_boolean
static bfd_boolean
_bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data)
_bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data)
{
{
  asection *sec;
  asection *sec;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
Line 2695... Line 2751...
  if ((h->root.type == bfd_link_hash_defined
  if ((h->root.type == bfd_link_hash_defined
       || h->root.type == bfd_link_hash_defweak)
       || h->root.type == bfd_link_hash_defweak)
      && ((sec = h->root.u.def.section)->flags & SEC_MERGE)
      && ((sec = h->root.u.def.section)->flags & SEC_MERGE)
      && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
      && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
    {
    {
      bfd *output_bfd = data;
      bfd *output_bfd = (bfd *) data;
 
 
      h->root.u.def.value =
      h->root.u.def.value =
        _bfd_merged_section_offset (output_bfd,
        _bfd_merged_section_offset (output_bfd,
                                    &h->root.u.def.section,
                                    &h->root.u.def.section,
                                    elf_section_data (sec)->sec_info,
                                    elf_section_data (sec)->sec_info,
Line 2787... Line 2843...
 
 
  /* If it's a local sym, of course we resolve locally.  */
  /* If it's a local sym, of course we resolve locally.  */
  if (h == NULL)
  if (h == NULL)
    return TRUE;
    return TRUE;
 
 
 
  /* STV_HIDDEN or STV_INTERNAL ones must be local.  */
 
  if (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
 
      || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
 
    return TRUE;
 
 
  /* Common symbols that become definitions don't get the DEF_REGULAR
  /* Common symbols that become definitions don't get the DEF_REGULAR
     flag set, so test it first, and don't bail out.  */
     flag set, so test it first, and don't bail out.  */
  if (ELF_COMMON_DEF_P (h))
  if (ELF_COMMON_DEF_P (h))
    /* Do nothing.  */;
    /* Do nothing.  */;
  /* If we don't have a definition in a regular file, then we can't
  /* If we don't have a definition in a regular file, then we can't
Line 2815... Line 2876...
  /* Now deal with defined dynamic symbols in shared libraries.  Ones
  /* Now deal with defined dynamic symbols in shared libraries.  Ones
     with default visibility might not resolve locally.  */
     with default visibility might not resolve locally.  */
  if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
  if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
    return FALSE;
    return FALSE;
 
 
  /* However, STV_HIDDEN or STV_INTERNAL ones must be local.  */
 
  if (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED)
 
    return TRUE;
 
 
 
  hash_table = elf_hash_table (info);
  hash_table = elf_hash_table (info);
  if (!is_elf_hash_table (hash_table))
  if (!is_elf_hash_table (hash_table))
    return TRUE;
    return TRUE;
 
 
  bed = get_elf_backend_data (hash_table->dynobj);
  bed = get_elf_backend_data (hash_table->dynobj);
Line 3009... Line 3066...
  bed = get_elf_backend_data (hash_table->dynobj);
  bed = get_elf_backend_data (hash_table->dynobj);
  s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
  s = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
  BFD_ASSERT (s != NULL);
  BFD_ASSERT (s != NULL);
 
 
  newsize = s->size + bed->s->sizeof_dyn;
  newsize = s->size + bed->s->sizeof_dyn;
  newcontents = bfd_realloc (s->contents, newsize);
  newcontents = (bfd_byte *) bfd_realloc (s->contents, newsize);
  if (newcontents == NULL)
  if (newcontents == NULL)
    return FALSE;
    return FALSE;
 
 
  dyn.d_tag = tag;
  dyn.d_tag = tag;
  dyn.d_un.d_val = val;
  dyn.d_un.d_val = val;
Line 3086... Line 3143...
    _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
    _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
 
 
  return 0;
  return 0;
}
}
 
 
 
static bfd_boolean
 
on_needed_list (const char *soname, struct bfd_link_needed_list *needed)
 
{
 
  for (; needed != NULL; needed = needed->next)
 
    if (strcmp (soname, needed->name) == 0)
 
      return TRUE;
 
 
 
  return FALSE;
 
}
 
 
/* Sort symbol by value and section.  */
/* Sort symbol by value and section.  */
static int
static int
elf_sort_symbol (const void *arg1, const void *arg2)
elf_sort_symbol (const void *arg1, const void *arg2)
{
{
  const struct elf_link_hash_entry *h1;
  const struct elf_link_hash_entry *h1;
Line 3114... Line 3181...
   dynamic symbols.  This is called via elf_link_hash_traverse.  */
   dynamic symbols.  This is called via elf_link_hash_traverse.  */
 
 
static bfd_boolean
static bfd_boolean
elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data)
elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data)
{
{
  struct elf_strtab_hash *dynstr = data;
  struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 
  if (h->dynindx != -1)
  if (h->dynindx != -1)
Line 3289... Line 3356...
/* Add symbols from an ELF object file to the linker hash table.  */
/* Add symbols from an ELF object file to the linker hash table.  */
 
 
static bfd_boolean
static bfd_boolean
elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
{
{
 
  Elf_Internal_Ehdr *ehdr;
  Elf_Internal_Shdr *hdr;
  Elf_Internal_Shdr *hdr;
  bfd_size_type symcount;
  bfd_size_type symcount;
  bfd_size_type extsymcount;
  bfd_size_type extsymcount;
  bfd_size_type extsymoff;
  bfd_size_type extsymoff;
  struct elf_link_hash_entry **sym_hash;
  struct elf_link_hash_entry **sym_hash;
Line 3344... Line 3412...
            bfd_set_error (bfd_error_wrong_format);
            bfd_set_error (bfd_error_wrong_format);
          goto error_return;
          goto error_return;
        }
        }
    }
    }
 
 
 
  ehdr = elf_elfheader (abfd);
 
  if (info->warn_alternate_em
 
      && bed->elf_machine_code != ehdr->e_machine
 
      && ((bed->elf_machine_alt1 != 0
 
           && ehdr->e_machine == bed->elf_machine_alt1)
 
          || (bed->elf_machine_alt2 != 0
 
              && ehdr->e_machine == bed->elf_machine_alt2)))
 
    info->callbacks->einfo
 
      (_("%P: alternate ELF machine code found (%d) in %B, expecting %d\n"),
 
       ehdr->e_machine, abfd, bed->elf_machine_code);
 
 
  /* As a GNU extension, any input sections which are named
  /* As a GNU extension, any input sections which are named
     .gnu.warning.SYMBOL are treated as warning symbols for the given
     .gnu.warning.SYMBOL are treated as warning symbols for the given
     symbol.  This differs from .gnu.warning sections, which generate
     symbol.  This differs from .gnu.warning sections, which generate
     warnings when they are included in an output file.  */
     warnings when they are included in an output file.  */
  if (info->executable)
  if (info->executable)
Line 3393... Line 3472...
                      continue;
                      continue;
                    }
                    }
                }
                }
 
 
              sz = s->size;
              sz = s->size;
              msg = bfd_alloc (abfd, sz + 1);
              msg = (char *) bfd_alloc (abfd, sz + 1);
              if (msg == NULL)
              if (msg == NULL)
                goto error_return;
                goto error_return;
 
 
              if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
              if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
                goto error_return;
                goto error_return;
Line 3469... Line 3548...
      s = bfd_get_section_by_name (abfd, ".dynamic");
      s = bfd_get_section_by_name (abfd, ".dynamic");
      if (s != NULL)
      if (s != NULL)
        {
        {
          bfd_byte *dynbuf;
          bfd_byte *dynbuf;
          bfd_byte *extdyn;
          bfd_byte *extdyn;
          int elfsec;
          unsigned int elfsec;
          unsigned long shlink;
          unsigned long shlink;
 
 
          if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
          if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
            goto error_free_dyn;
            {
 
error_free_dyn:
 
              free (dynbuf);
 
              goto error_return;
 
            }
 
 
          elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
          elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
          if (elfsec == -1)
          if (elfsec == SHN_BAD)
            goto error_free_dyn;
            goto error_free_dyn;
          shlink = elf_elfsections (abfd)[elfsec]->sh_link;
          shlink = elf_elfsections (abfd)[elfsec]->sh_link;
 
 
          for (extdyn = dynbuf;
          for (extdyn = dynbuf;
               extdyn < dynbuf + s->size;
               extdyn < dynbuf + s->size;
Line 3501... Line 3584...
                  struct bfd_link_needed_list *n, **pn;
                  struct bfd_link_needed_list *n, **pn;
                  char *fnm, *anm;
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
                  unsigned int tagv = dyn.d_un.d_val;
 
 
                  amt = sizeof (struct bfd_link_needed_list);
                  amt = sizeof (struct bfd_link_needed_list);
                  n = bfd_alloc (abfd, amt);
                  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  if (n == NULL || fnm == NULL)
                  if (n == NULL || fnm == NULL)
                    goto error_free_dyn;
                    goto error_free_dyn;
                  amt = strlen (fnm) + 1;
                  amt = strlen (fnm) + 1;
                  anm = bfd_alloc (abfd, amt);
                  anm = (char *) bfd_alloc (abfd, amt);
                  if (anm == NULL)
                  if (anm == NULL)
                    goto error_free_dyn;
                    goto error_free_dyn;
                  memcpy (anm, fnm, amt);
                  memcpy (anm, fnm, amt);
                  n->name = anm;
                  n->name = anm;
                  n->by = abfd;
                  n->by = abfd;
Line 3524... Line 3607...
                  struct bfd_link_needed_list *n, **pn;
                  struct bfd_link_needed_list *n, **pn;
                  char *fnm, *anm;
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
                  unsigned int tagv = dyn.d_un.d_val;
 
 
                  amt = sizeof (struct bfd_link_needed_list);
                  amt = sizeof (struct bfd_link_needed_list);
                  n = bfd_alloc (abfd, amt);
                  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  if (n == NULL || fnm == NULL)
                  if (n == NULL || fnm == NULL)
                    goto error_free_dyn;
                    goto error_free_dyn;
                  amt = strlen (fnm) + 1;
                  amt = strlen (fnm) + 1;
                  anm = bfd_alloc (abfd, amt);
                  anm = (char *) bfd_alloc (abfd, amt);
                  if (anm == NULL)
                  if (anm == NULL)
                    goto error_free_dyn;
                    goto error_free_dyn;
                  memcpy (anm, fnm, amt);
                  memcpy (anm, fnm, amt);
                  n->name = anm;
                  n->name = anm;
                  n->by = abfd;
                  n->by = abfd;
Line 3550... Line 3633...
                  struct bfd_link_needed_list *n, **pn;
                  struct bfd_link_needed_list *n, **pn;
                  char *fnm, *anm;
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
                  unsigned int tagv = dyn.d_un.d_val;
 
 
                  amt = sizeof (struct bfd_link_needed_list);
                  amt = sizeof (struct bfd_link_needed_list);
                  n = bfd_alloc (abfd, amt);
                  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
                  if (n == NULL || fnm == NULL)
                  if (n == NULL || fnm == NULL)
                    goto error_free_dyn;
                    goto error_free_dyn;
                  amt = strlen (fnm) + 1;
                  amt = strlen (fnm) + 1;
                  anm = bfd_alloc (abfd, amt);
                  anm = (char *) bfd_alloc (abfd, amt);
                  if (anm == NULL)
                  if (anm == NULL)
                    {
                    goto error_free_dyn;
                    error_free_dyn:
 
                      free (dynbuf);
 
                      goto error_return;
 
                    }
 
                  memcpy (anm, fnm, amt);
                  memcpy (anm, fnm, amt);
                  n->name = anm;
                  n->name = anm;
                  n->by = abfd;
                  n->by = abfd;
                  n->next = NULL;
                  n->next = NULL;
                  for (pn = & rpath;
                  for (pn = & rpath;
Line 3663... Line 3742...
        goto error_return;
        goto error_return;
 
 
      /* We store a pointer to the hash table entry for each external
      /* We store a pointer to the hash table entry for each external
         symbol.  */
         symbol.  */
      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
      sym_hash = bfd_alloc (abfd, amt);
      sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt);
      if (sym_hash == NULL)
      if (sym_hash == NULL)
        goto error_free_sym;
        goto error_free_sym;
      elf_sym_hashes (abfd) = sym_hash;
      elf_sym_hashes (abfd) = sym_hash;
    }
    }
 
 
Line 3683... Line 3762...
      if (elf_dynversym (abfd) != 0)
      if (elf_dynversym (abfd) != 0)
        {
        {
          Elf_Internal_Shdr *versymhdr;
          Elf_Internal_Shdr *versymhdr;
 
 
          versymhdr = &elf_tdata (abfd)->dynversym_hdr;
          versymhdr = &elf_tdata (abfd)->dynversym_hdr;
          extversym = bfd_malloc (versymhdr->sh_size);
          extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
          if (extversym == NULL)
          if (extversym == NULL)
            goto error_free_sym;
            goto error_free_sym;
          amt = versymhdr->sh_size;
          amt = versymhdr->sh_size;
          if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
          if (bfd_seek (abfd, versymhdr->sh_offset, SEEK_SET) != 0
              || bfd_bread (extversym, amt, abfd) != amt)
              || bfd_bread (extversym, amt, abfd) != amt)
Line 3795... Line 3874...
      value = isym->st_value;
      value = isym->st_value;
      *sym_hash = NULL;
      *sym_hash = NULL;
      common = bed->common_definition (isym);
      common = bed->common_definition (isym);
 
 
      bind = ELF_ST_BIND (isym->st_info);
      bind = ELF_ST_BIND (isym->st_info);
      if (bind == STB_LOCAL)
      switch (bind)
        {
        {
 
        case STB_LOCAL:
          /* This should be impossible, since ELF requires that all
          /* This should be impossible, since ELF requires that all
             global symbols follow all local symbols, and that sh_info
             global symbols follow all local symbols, and that sh_info
             point to the first global symbol.  Unfortunately, Irix 5
             point to the first global symbol.  Unfortunately, Irix 5
             screws this up.  */
             screws this up.  */
          continue;
          continue;
        }
 
      else if (bind == STB_GLOBAL)
        case STB_GLOBAL:
        {
 
          if (isym->st_shndx != SHN_UNDEF && !common)
          if (isym->st_shndx != SHN_UNDEF && !common)
            flags = BSF_GLOBAL;
            flags = BSF_GLOBAL;
        }
          break;
      else if (bind == STB_WEAK)
 
 
        case STB_WEAK:
        flags = BSF_WEAK;
        flags = BSF_WEAK;
      else
          break;
        {
 
 
        case STB_GNU_UNIQUE:
 
          flags = BSF_GNU_UNIQUE;
 
          break;
 
 
 
        default:
          /* Leave it up to the processor backend.  */
          /* Leave it up to the processor backend.  */
 
          break;
        }
        }
 
 
      if (isym->st_shndx == SHN_UNDEF)
      if (isym->st_shndx == SHN_UNDEF)
        sec = bfd_und_section_ptr;
        sec = bfd_und_section_ptr;
      else if (isym->st_shndx < SHN_LORESERVE
      else if (isym->st_shndx == SHN_ABS)
               || isym->st_shndx > SHN_HIRESERVE)
        sec = bfd_abs_section_ptr;
 
      else if (isym->st_shndx == SHN_COMMON)
 
        {
 
          sec = bfd_com_section_ptr;
 
          /* What ELF calls the size we call the value.  What ELF
 
             calls the value we call the alignment.  */
 
          value = isym->st_size;
 
        }
 
      else
        {
        {
          sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
          sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
          if (sec == NULL)
          if (sec == NULL)
            sec = bfd_abs_section_ptr;
            sec = bfd_abs_section_ptr;
          else if (sec->kept_section)
          else if (sec->kept_section)
Line 3833... Line 3927...
              isym->st_shndx = SHN_UNDEF;
              isym->st_shndx = SHN_UNDEF;
            }
            }
          else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
          else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
            value -= sec->vma;
            value -= sec->vma;
        }
        }
      else if (isym->st_shndx == SHN_ABS)
 
        sec = bfd_abs_section_ptr;
 
      else if (isym->st_shndx == SHN_COMMON)
 
        {
 
          sec = bfd_com_section_ptr;
 
          /* What ELF calls the size we call the value.  What ELF
 
             calls the value we call the alignment.  */
 
          value = isym->st_size;
 
        }
 
      else
 
        {
 
          /* Leave it up to the processor backend.  */
 
        }
 
 
 
      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
                                              isym->st_name);
                                              isym->st_name);
      if (name == NULL)
      if (name == NULL)
        goto error_free_vers;
        goto error_free_vers;
Line 3997... Line 4078...
              newlen = namelen + verlen + 2;
              newlen = namelen + verlen + 2;
              if ((iver.vs_vers & VERSYM_HIDDEN) == 0
              if ((iver.vs_vers & VERSYM_HIDDEN) == 0
                  && isym->st_shndx != SHN_UNDEF)
                  && isym->st_shndx != SHN_UNDEF)
                ++newlen;
                ++newlen;
 
 
              newname = bfd_hash_allocate (&htab->root.table, newlen);
              newname = (char *) bfd_hash_allocate (&htab->root.table, newlen);
              if (newname == NULL)
              if (newname == NULL)
                goto error_free_vers;
                goto error_free_vers;
              memcpy (newname, name, namelen);
              memcpy (newname, name, namelen);
              p = newname + namelen;
              p = newname + namelen;
              *p++ = ELF_VER_CHR;
              *p++ = ELF_VER_CHR;
Line 4069... Line 4150...
 
 
      h = *sym_hash;
      h = *sym_hash;
      while (h->root.type == bfd_link_hash_indirect
      while (h->root.type == bfd_link_hash_indirect
             || h->root.type == bfd_link_hash_warning)
             || h->root.type == bfd_link_hash_warning)
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 
      *sym_hash = h;
      *sym_hash = h;
 
      h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
 
 
      new_weakdef = FALSE;
      new_weakdef = FALSE;
      if (dynamic
      if (dynamic
          && definition
          && definition
          && (flags & BSF_WEAK) != 0
          && (flags & BSF_WEAK) != 0
Line 4208... Line 4291...
            h->size = h->root.u.c.size;
            h->size = h->root.u.c.size;
 
 
          if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
          if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
              && (definition || h->type == STT_NOTYPE))
              && (definition || h->type == STT_NOTYPE))
            {
            {
              if (h->type != STT_NOTYPE
              unsigned int type = ELF_ST_TYPE (isym->st_info);
                  && h->type != ELF_ST_TYPE (isym->st_info)
 
                  && ! type_change_ok)
              /* Turn an IFUNC symbol from a DSO into a normal FUNC
 
                 symbol.  */
 
              if (type == STT_GNU_IFUNC
 
                  && (abfd->flags & DYNAMIC) != 0)
 
                type = STT_FUNC;
 
 
 
              if (h->type != type)
 
                {
 
                  if (h->type != STT_NOTYPE && ! type_change_ok)
                (*_bfd_error_handler)
                (*_bfd_error_handler)
                  (_("Warning: type of symbol `%s' changed"
                  (_("Warning: type of symbol `%s' changed"
                     " from %d to %d in %B"),
                     " from %d to %d in %B"),
                   abfd, name, h->type, ELF_ST_TYPE (isym->st_info));
                       abfd, name, h->type, type);
 
 
              h->type = ELF_ST_TYPE (isym->st_info);
                  h->type = type;
            }
            }
 
 
          /* If st_other has a processor-specific meaning, specific
 
             code might be needed here. We never merge the visibility
 
             attribute with the one from a dynamic object.  */
 
          if (bed->elf_backend_merge_symbol_attribute)
 
            (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
 
                                                        dynamic);
 
 
 
          /* If this symbol has default visibility and the user has requested
 
             we not re-export it, then mark it as hidden.  */
 
          if (definition && !dynamic
 
              && (abfd->no_export
 
                  || (abfd->my_archive && abfd->my_archive->no_export))
 
              && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
 
            isym->st_other = (STV_HIDDEN
 
                              | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
 
 
 
          if (ELF_ST_VISIBILITY (isym->st_other) != 0 && !dynamic)
 
            {
 
              unsigned char hvis, symvis, other, nvis;
 
 
 
              /* Only merge the visibility. Leave the remainder of the
 
                 st_other field to elf_backend_merge_symbol_attribute.  */
 
              other = h->other & ~ELF_ST_VISIBILITY (-1);
 
 
 
              /* Combine visibilities, using the most constraining one.  */
 
              hvis   = ELF_ST_VISIBILITY (h->other);
 
              symvis = ELF_ST_VISIBILITY (isym->st_other);
 
              if (! hvis)
 
                nvis = symvis;
 
              else if (! symvis)
 
                nvis = hvis;
 
              else
 
                nvis = hvis < symvis ? hvis : symvis;
 
 
 
              h->other = other | nvis;
 
            }
            }
 
 
 
          /* Merge st_other field.  */
 
          elf_merge_st_other (abfd, h, isym, definition, dynamic);
 
 
          /* Set a flag in the hash table entry indicating the type of
          /* Set a flag in the hash table entry indicating the type of
             reference or definition we just found.  Keep a count of
             reference or definition we just found.  Keep a count of
             the number of dynamic symbols we find.  A dynamic symbol
             the number of dynamic symbols we find.  A dynamic symbol
             is one which is referenced or defined by both a regular
             is one which is referenced or defined by both a regular
             object and a shared object.  */
             object and a shared object.  */
Line 4271... Line 4329...
                  h->ref_regular = 1;
                  h->ref_regular = 1;
                  if (bind != STB_WEAK)
                  if (bind != STB_WEAK)
                    h->ref_regular_nonweak = 1;
                    h->ref_regular_nonweak = 1;
                }
                }
              else
              else
 
                {
                h->def_regular = 1;
                h->def_regular = 1;
 
                  if (h->def_dynamic)
 
                    {
 
                      h->def_dynamic = 0;
 
                      h->ref_dynamic = 1;
 
                      h->dynamic_def = 1;
 
                    }
 
                }
              if (! info->executable
              if (! info->executable
                  || h->def_dynamic
                  || h->def_dynamic
                  || h->ref_dynamic)
                  || h->ref_dynamic)
                dynsym = TRUE;
                dynsym = TRUE;
            }
            }
Line 4291... Line 4357...
                      && ! new_weakdef
                      && ! new_weakdef
                      && h->u.weakdef->dynindx != -1))
                      && h->u.weakdef->dynindx != -1))
                dynsym = TRUE;
                dynsym = TRUE;
            }
            }
 
 
          if (definition && (sec->flags & SEC_DEBUGGING))
          if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
            {
            {
              /* We don't want to make debug symbol dynamic.  */
              /* We don't want to make debug symbol dynamic.  */
              (*bed->elf_backend_hide_symbol) (info, h, TRUE);
              (*bed->elf_backend_hide_symbol) (info, h, TRUE);
              dynsym = FALSE;
              dynsym = FALSE;
            }
            }
Line 4317... Line 4383...
                     aliases can be checked.  */
                     aliases can be checked.  */
                  if (!nondeflt_vers)
                  if (!nondeflt_vers)
                    {
                    {
                      amt = ((isymend - isym + 1)
                      amt = ((isymend - isym + 1)
                             * sizeof (struct elf_link_hash_entry *));
                             * sizeof (struct elf_link_hash_entry *));
                      nondeflt_vers = bfd_malloc (amt);
                      nondeflt_vers =
 
                          (struct elf_link_hash_entry **) bfd_malloc (amt);
                      if (!nondeflt_vers)
                      if (!nondeflt_vers)
                        goto error_free_vers;
                        goto error_free_vers;
                    }
                    }
                  nondeflt_vers[nondeflt_vers_cnt++] = h;
                  nondeflt_vers[nondeflt_vers_cnt++] = h;
                }
                }
Line 4352... Line 4419...
                break;
                break;
              }
              }
 
 
          if (!add_needed
          if (!add_needed
              && definition
              && definition
              && dynsym
              && ((dynsym
              && h->ref_regular)
              && h->ref_regular)
 
                  || (h->ref_dynamic
 
                      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
 
                      && !on_needed_list (elf_dt_name (abfd), htab->needed))))
            {
            {
              int ret;
              int ret;
              const char *soname = elf_dt_name (abfd);
              const char *soname = elf_dt_name (abfd);
 
 
              /* A symbol from a library loaded via DT_NEEDED of some
              /* A symbol from a library loaded via DT_NEEDED of some
Line 4371... Line 4441...
                     abfd, name);
                     abfd, name);
                  bfd_set_error (bfd_error_bad_value);
                  bfd_set_error (bfd_error_bad_value);
                  goto error_free_vers;
                  goto error_free_vers;
                }
                }
 
 
              elf_dyn_lib_class (abfd) &= ~DYN_AS_NEEDED;
              elf_dyn_lib_class (abfd) = (enum dynamic_lib_link_class)
 
                  (elf_dyn_lib_class (abfd) & ~DYN_AS_NEEDED);
 
 
              add_needed = TRUE;
              add_needed = TRUE;
              ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
              ret = elf_add_dt_needed_tag (abfd, info, soname, add_needed);
              if (ret < 0)
              if (ret < 0)
                goto error_free_vers;
                goto error_free_vers;
Line 4477... Line 4548...
              || (h->root.type != bfd_link_hash_defined
              || (h->root.type != bfd_link_hash_defined
                  && h->root.type != bfd_link_hash_defweak))
                  && h->root.type != bfd_link_hash_defweak))
            continue;
            continue;
 
 
          amt = p - h->root.root.string;
          amt = p - h->root.root.string;
          shortname = bfd_malloc (amt + 1);
          shortname = (char *) bfd_malloc (amt + 1);
          if (!shortname)
          if (!shortname)
            goto error_free_vers;
            goto error_free_vers;
          memcpy (shortname, h->root.root.string, amt);
          memcpy (shortname, h->root.root.string, amt);
          shortname[amt] = '\0';
          shortname[amt] = '\0';
 
 
Line 4535... Line 4606...
 
 
      /* Since we have to search the whole symbol list for each weak
      /* Since we have to search the whole symbol list for each weak
         defined symbol, search time for N weak defined symbols will be
         defined symbol, search time for N weak defined symbols will be
         O(N^2). Binary search will cut it down to O(NlogN).  */
         O(N^2). Binary search will cut it down to O(NlogN).  */
      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
      sorted_sym_hash = bfd_malloc (amt);
      sorted_sym_hash = (struct elf_link_hash_entry **) bfd_malloc (amt);
      if (sorted_sym_hash == NULL)
      if (sorted_sym_hash == NULL)
        goto error_return;
        goto error_return;
      sym_hash = sorted_sym_hash;
      sym_hash = sorted_sym_hash;
      hpp = elf_sym_hashes (abfd);
      hpp = elf_sym_hashes (abfd);
      hppend = hpp + extsymcount;
      hppend = hpp + extsymcount;
Line 4628... Line 4699...
                     symbols, make sure the real definition is put
                     symbols, make sure the real definition is put
                     there as well.  */
                     there as well.  */
                  if (hlook->dynindx != -1 && h->dynindx == -1)
                  if (hlook->dynindx != -1 && h->dynindx == -1)
                    {
                    {
                      if (! bfd_elf_link_record_dynamic_symbol (info, h))
                      if (! bfd_elf_link_record_dynamic_symbol (info, h))
 
                        {
 
                        err_free_sym_hash:
 
                          free (sorted_sym_hash);
                        goto error_return;
                        goto error_return;
                    }
                    }
 
                    }
 
 
                  /* If the real definition is in the list of dynamic
                  /* If the real definition is in the list of dynamic
                     symbols, make sure the weak definition is put
                     symbols, make sure the weak definition is put
                     there as well.  If we don't do this, then the
                     there as well.  If we don't do this, then the
                     dynamic loader might not merge the entries for the
                     dynamic loader might not merge the entries for the
                     real definition and the weak definition.  */
                     real definition and the weak definition.  */
                  if (h->dynindx != -1 && hlook->dynindx == -1)
                  if (h->dynindx != -1 && hlook->dynindx == -1)
                    {
                    {
                      if (! bfd_elf_link_record_dynamic_symbol (info, hlook))
                      if (! bfd_elf_link_record_dynamic_symbol (info, hlook))
                        goto error_return;
                        goto err_free_sym_hash;
                    }
                    }
                  break;
                  break;
                }
                }
            }
            }
        }
        }
 
 
      free (sorted_sym_hash);
      free (sorted_sym_hash);
    }
    }
 
 
  if (bed->check_directives)
  if (bed->check_directives
    (*bed->check_directives) (abfd, info);
      && !(*bed->check_directives) (abfd, info))
 
    return FALSE;
 
 
  /* If this object is the same format as the output object, and it is
  /* If this object is the same format as the output object, and it is
     not a shared library, then let the backend look through the
     not a shared library, then let the backend look through the
     relocs.
     relocs.
 
 
Line 4743... Line 4819...
  if (is_elf_hash_table (htab) && add_needed)
  if (is_elf_hash_table (htab) && add_needed)
    {
    {
      /* Add this bfd to the loaded list.  */
      /* Add this bfd to the loaded list.  */
      struct elf_link_loaded_list *n;
      struct elf_link_loaded_list *n;
 
 
      n = bfd_alloc (abfd, sizeof (struct elf_link_loaded_list));
      n = (struct elf_link_loaded_list *)
 
          bfd_alloc (abfd, sizeof (struct elf_link_loaded_list));
      if (n == NULL)
      if (n == NULL)
        goto error_return;
        goto error_return;
      n->abfd = abfd;
      n->abfd = abfd;
      n->next = htab->loaded;
      n->next = htab->loaded;
      htab->loaded = n;
      htab->loaded = n;
Line 4794... Line 4871...
  if (p == NULL || p[1] != ELF_VER_CHR)
  if (p == NULL || p[1] != ELF_VER_CHR)
    return h;
    return h;
 
 
  /* First check with only one `@'.  */
  /* First check with only one `@'.  */
  len = strlen (name);
  len = strlen (name);
  copy = bfd_alloc (abfd, len);
  copy = (char *) bfd_alloc (abfd, len);
  if (copy == NULL)
  if (copy == NULL)
    return (struct elf_link_hash_entry *) 0 - 1;
    return (struct elf_link_hash_entry *) 0 - 1;
 
 
  first = p - name + 1;
  first = p - name + 1;
  memcpy (copy, name, first);
  memcpy (copy, name, first);
Line 4871... Line 4948...
  c = bfd_ardata (abfd)->symdef_count;
  c = bfd_ardata (abfd)->symdef_count;
  if (c == 0)
  if (c == 0)
    return TRUE;
    return TRUE;
  amt = c;
  amt = c;
  amt *= sizeof (bfd_boolean);
  amt *= sizeof (bfd_boolean);
  defined = bfd_zmalloc (amt);
  defined = (bfd_boolean *) bfd_zmalloc (amt);
  included = bfd_zmalloc (amt);
  included = (bfd_boolean *) bfd_zmalloc (amt);
  if (defined == NULL || included == NULL)
  if (defined == NULL || included == NULL)
    goto error_return;
    goto error_return;
 
 
  symdefs = bfd_ardata (abfd)->symdefs;
  symdefs = bfd_ardata (abfd)->symdefs;
  bed = get_elf_backend_data (abfd);
  bed = get_elf_backend_data (abfd);
Line 5036... Line 5113...
   all hash value of the exported symbols in an array.  */
   all hash value of the exported symbols in an array.  */
 
 
static bfd_boolean
static bfd_boolean
elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
{
{
  struct hash_codes_info *inf = data;
  struct hash_codes_info *inf = (struct hash_codes_info *) data;
  const char *name;
  const char *name;
  char *p;
  char *p;
  unsigned long ha;
  unsigned long ha;
  char *alc = NULL;
  char *alc = NULL;
 
 
Line 5053... Line 5130...
 
 
  name = h->root.root.string;
  name = h->root.root.string;
  p = strchr (name, ELF_VER_CHR);
  p = strchr (name, ELF_VER_CHR);
  if (p != NULL)
  if (p != NULL)
    {
    {
      alc = bfd_malloc (p - name + 1);
      alc = (char *) bfd_malloc (p - name + 1);
      if (alc == NULL)
      if (alc == NULL)
        {
        {
          inf->error = TRUE;
          inf->error = TRUE;
          return FALSE;
          return FALSE;
        }
        }
Line 5107... Line 5184...
   all hash value of the exported symbols in an array.  */
   all hash value of the exported symbols in an array.  */
 
 
static bfd_boolean
static bfd_boolean
elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
{
{
  struct collect_gnu_hash_codes *s = data;
  struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data;
  const char *name;
  const char *name;
  char *p;
  char *p;
  unsigned long ha;
  unsigned long ha;
  char *alc = NULL;
  char *alc = NULL;
 
 
Line 5128... Line 5205...
 
 
  name = h->root.root.string;
  name = h->root.root.string;
  p = strchr (name, ELF_VER_CHR);
  p = strchr (name, ELF_VER_CHR);
  if (p != NULL)
  if (p != NULL)
    {
    {
      alc = bfd_malloc (p - name + 1);
      alc = (char *) bfd_malloc (p - name + 1);
      if (alc == NULL)
      if (alc == NULL)
        {
        {
          s->error = TRUE;
          s->error = TRUE;
          return FALSE;
          return FALSE;
        }
        }
Line 5162... Line 5239...
   final dynaminc symbol renumbering.  */
   final dynaminc symbol renumbering.  */
 
 
static bfd_boolean
static bfd_boolean
elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data)
elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data)
{
{
  struct collect_gnu_hash_codes *s = data;
  struct collect_gnu_hash_codes *s = (struct collect_gnu_hash_codes *) data;
  unsigned long int bucket;
  unsigned long int bucket;
  unsigned long int val;
  unsigned long int val;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
Line 5274... Line 5351...
 
 
      /* Create array where we count the collisions in.  We must use bfd_malloc
      /* Create array where we count the collisions in.  We must use bfd_malloc
         since the size could be large.  */
         since the size could be large.  */
      amt = maxsize;
      amt = maxsize;
      amt *= sizeof (unsigned long int);
      amt *= sizeof (unsigned long int);
      counts = bfd_malloc (amt);
      counts = (unsigned long int *) bfd_malloc (amt);
      if (counts == NULL)
      if (counts == NULL)
        return 0;
        return 0;
 
 
      /* Compute the "optimal" size for the hash table.  The criteria is a
      /* Compute the "optimal" size for the hash table.  The criteria is a
         minimal chain length.  The minor criteria is (of course) the size
         minimal chain length.  The minor criteria is (of course) the size
Line 5380... Line 5457...
                               struct bfd_elf_version_tree *verdefs)
                               struct bfd_elf_version_tree *verdefs)
{
{
  bfd_size_type soname_indx;
  bfd_size_type soname_indx;
  bfd *dynobj;
  bfd *dynobj;
  const struct elf_backend_data *bed;
  const struct elf_backend_data *bed;
  struct elf_assign_sym_version_info asvinfo;
  struct elf_info_failed asvinfo;
 
 
  *sinterpptr = NULL;
  *sinterpptr = NULL;
 
 
  soname_indx = (bfd_size_type) -1;
  soname_indx = (bfd_size_type) -1;
 
 
Line 5406... Line 5483...
           inputobj;
           inputobj;
           inputobj = inputobj->link_next)
           inputobj = inputobj->link_next)
        {
        {
          asection *s;
          asection *s;
 
 
          if (inputobj->flags & (DYNAMIC | BFD_LINKER_CREATED))
          if (inputobj->flags & (DYNAMIC | EXEC_P | BFD_LINKER_CREATED))
            continue;
            continue;
          s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
          s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
          if (s)
          if (s)
            {
            {
              if (s->flags & SEC_CODE)
              if (s->flags & SEC_CODE)
Line 5543... Line 5620...
        }
        }
 
 
      /* Make all global versions with definition.  */
      /* Make all global versions with definition.  */
      for (t = verdefs; t != NULL; t = t->next)
      for (t = verdefs; t != NULL; t = t->next)
        for (d = t->globals.list; d != NULL; d = d->next)
        for (d = t->globals.list; d != NULL; d = d->next)
          if (!d->symver && d->symbol)
          if (!d->symver && d->literal)
            {
            {
              const char *verstr, *name;
              const char *verstr, *name;
              size_t namelen, verlen, newlen;
              size_t namelen, verlen, newlen;
              char *newname, *p;
              char *newname, *p;
              struct elf_link_hash_entry *newh;
              struct elf_link_hash_entry *newh;
 
 
              name = d->symbol;
              name = d->pattern;
              namelen = strlen (name);
              namelen = strlen (name);
              verstr = t->name;
              verstr = t->name;
              verlen = strlen (verstr);
              verlen = strlen (verstr);
              newlen = namelen + verlen + 3;
              newlen = namelen + verlen + 3;
 
 
              newname = bfd_malloc (newlen);
              newname = (char *) bfd_malloc (newlen);
              if (newname == NULL)
              if (newname == NULL)
                return FALSE;
                return FALSE;
              memcpy (newname, name, namelen);
              memcpy (newname, name, namelen);
 
 
              /* Check the hidden versioned definition.  */
              /* Check the hidden versioned definition.  */
Line 5591... Line 5668...
                      || newh->root.type == bfd_link_hash_defweak))
                      || newh->root.type == bfd_link_hash_defweak))
                d->symver = 1;
                d->symver = 1;
            }
            }
 
 
      /* Attach all the symbols to their version information.  */
      /* Attach all the symbols to their version information.  */
      asvinfo.output_bfd = output_bfd;
 
      asvinfo.info = info;
      asvinfo.info = info;
      asvinfo.verdefs = verdefs;
      asvinfo.verdefs = verdefs;
      asvinfo.failed = FALSE;
      asvinfo.failed = FALSE;
 
 
      elf_link_hash_traverse (elf_hash_table (info),
      elf_link_hash_traverse (elf_hash_table (info),
Line 5608... Line 5684...
        {
        {
          /* Check if all global versions have a definition.  */
          /* Check if all global versions have a definition.  */
          all_defined = TRUE;
          all_defined = TRUE;
          for (t = verdefs; t != NULL; t = t->next)
          for (t = verdefs; t != NULL; t = t->next)
            for (d = t->globals.list; d != NULL; d = d->next)
            for (d = t->globals.list; d != NULL; d = d->next)
              if (!d->symver && !d->script)
              if (d->literal && !d->symver && !d->script)
                {
                {
                  (*_bfd_error_handler)
                  (*_bfd_error_handler)
                    (_("%s: undefined version: %s"),
                    (_("%s: undefined version: %s"),
                     d->pattern, t->name);
                     d->pattern, t->name);
                  all_defined = FALSE;
                  all_defined = FALSE;
Line 5795... Line 5871...
              for (n = t->deps; n != NULL; n = n->next)
              for (n = t->deps; n != NULL; n = n->next)
                size += sizeof (Elf_External_Verdaux);
                size += sizeof (Elf_External_Verdaux);
            }
            }
 
 
          s->size = size;
          s->size = size;
          s->contents = bfd_alloc (output_bfd, s->size);
          s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
          if (s->contents == NULL && s->size != 0)
          if (s->contents == NULL && s->size != 0)
            return FALSE;
            return FALSE;
 
 
          /* Fill in the version definition section.  */
          /* Fill in the version definition section.  */
 
 
Line 5996... Line 6072...
      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
      s = bfd_get_section_by_name (dynobj, ".gnu.version_r");
      BFD_ASSERT (s != NULL);
      BFD_ASSERT (s != NULL);
      {
      {
        struct elf_find_verdep_info sinfo;
        struct elf_find_verdep_info sinfo;
 
 
        sinfo.output_bfd = output_bfd;
 
        sinfo.info = info;
        sinfo.info = info;
        sinfo.vers = elf_tdata (output_bfd)->cverdefs;
        sinfo.vers = elf_tdata (output_bfd)->cverdefs;
        if (sinfo.vers == 0)
        if (sinfo.vers == 0)
          sinfo.vers = 1;
          sinfo.vers = 1;
        sinfo.failed = FALSE;
        sinfo.failed = FALSE;
Line 6034... Line 6109...
                for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
                for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
                  size += sizeof (Elf_External_Vernaux);
                  size += sizeof (Elf_External_Vernaux);
              }
              }
 
 
            s->size = size;
            s->size = size;
            s->contents = bfd_alloc (output_bfd, s->size);
            s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
            if (s->contents == NULL)
            if (s->contents == NULL)
              return FALSE;
              return FALSE;
 
 
            p = s->contents;
            p = s->contents;
            for (t = elf_tdata (output_bfd)->verref;
            for (t = elf_tdata (output_bfd)->verref;
Line 6134... Line 6209...
void
void
_bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info)
_bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info)
{
{
  asection *s;
  asection *s;
 
 
 
  /* Data first, since setting text_index_section changes
 
     _bfd_elf_link_omit_section_dynsym.  */
  for (s = output_bfd->sections; s != NULL; s = s->next)
  for (s = output_bfd->sections; s != NULL; s = s->next)
    if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
    if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
         == (SEC_ALLOC | SEC_READONLY))
 
        && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
        && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
      {
      {
        elf_hash_table (info)->text_index_section = s;
        elf_hash_table (info)->data_index_section = s;
        break;
        break;
      }
      }
 
 
  for (s = output_bfd->sections; s != NULL; s = s->next)
  for (s = output_bfd->sections; s != NULL; s = s->next)
    if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
    if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
 
         == (SEC_ALLOC | SEC_READONLY))
        && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
        && !_bfd_elf_link_omit_section_dynsym (output_bfd, info, s))
      {
      {
        elf_hash_table (info)->data_index_section = s;
        elf_hash_table (info)->text_index_section = s;
        break;
        break;
      }
      }
 
 
  if (elf_hash_table (info)->text_index_section == NULL)
  if (elf_hash_table (info)->text_index_section == NULL)
    elf_hash_table (info)->text_index_section
    elf_hash_table (info)->text_index_section
Line 6192... Line 6269...
      BFD_ASSERT (s != NULL);
      BFD_ASSERT (s != NULL);
      if (dynsymcount != 0
      if (dynsymcount != 0
          && (s->flags & SEC_EXCLUDE) == 0)
          && (s->flags & SEC_EXCLUDE) == 0)
        {
        {
          s->size = dynsymcount * sizeof (Elf_External_Versym);
          s->size = dynsymcount * sizeof (Elf_External_Versym);
          s->contents = bfd_zalloc (output_bfd, s->size);
          s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
          if (s->contents == NULL)
          if (s->contents == NULL)
            return FALSE;
            return FALSE;
 
 
          if (!_bfd_elf_add_dynamic_entry (info, DT_VERSYM, 0))
          if (!_bfd_elf_add_dynamic_entry (info, DT_VERSYM, 0))
            return FALSE;
            return FALSE;
Line 6212... Line 6289...
      BFD_ASSERT (s != NULL);
      BFD_ASSERT (s != NULL);
      s->size = dynsymcount * bed->s->sizeof_sym;
      s->size = dynsymcount * bed->s->sizeof_sym;
 
 
      if (dynsymcount != 0)
      if (dynsymcount != 0)
        {
        {
          s->contents = bfd_alloc (output_bfd, s->size);
          s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
          if (s->contents == NULL)
          if (s->contents == NULL)
            return FALSE;
            return FALSE;
 
 
          /* The first entry in .dynsym is a dummy symbol.
          /* The first entry in .dynsym is a dummy symbol.
             Clear all the section syms, in case we don't output them all.  */
             Clear all the section syms, in case we don't output them all.  */
Line 6239... Line 6316...
 
 
          /* Compute the hash values for all exported symbols.  At the same
          /* Compute the hash values for all exported symbols.  At the same
             time store the values in an array so that we could use them for
             time store the values in an array so that we could use them for
             optimizations.  */
             optimizations.  */
          amt = dynsymcount * sizeof (unsigned long int);
          amt = dynsymcount * sizeof (unsigned long int);
          hashcodes = bfd_malloc (amt);
          hashcodes = (unsigned long int *) bfd_malloc (amt);
          if (hashcodes == NULL)
          if (hashcodes == NULL)
            return FALSE;
            return FALSE;
          hashinf.hashcodes = hashcodes;
          hashinf.hashcodes = hashcodes;
          hashinf.error = FALSE;
          hashinf.error = FALSE;
 
 
          /* Put all hash values in HASHCODES.  */
          /* Put all hash values in HASHCODES.  */
          elf_link_hash_traverse (elf_hash_table (info),
          elf_link_hash_traverse (elf_hash_table (info),
                                  elf_collect_hash_codes, &hashinf);
                                  elf_collect_hash_codes, &hashinf);
          if (hashinf.error)
          if (hashinf.error)
 
            {
 
              free (hashcodes);
            return FALSE;
            return FALSE;
 
            }
 
 
          nsyms = hashinf.hashcodes - hashcodes;
          nsyms = hashinf.hashcodes - hashcodes;
          bucketcount
          bucketcount
            = compute_bucket_count (info, hashcodes, nsyms, 0);
            = compute_bucket_count (info, hashcodes, nsyms, 0);
          free (hashcodes);
          free (hashcodes);
Line 6265... Line 6345...
 
 
          s = bfd_get_section_by_name (dynobj, ".hash");
          s = bfd_get_section_by_name (dynobj, ".hash");
          BFD_ASSERT (s != NULL);
          BFD_ASSERT (s != NULL);
          hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
          hash_entry_size = elf_section_data (s)->this_hdr.sh_entsize;
          s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
          s->size = ((2 + bucketcount + dynsymcount) * hash_entry_size);
          s->contents = bfd_zalloc (output_bfd, s->size);
          s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
          if (s->contents == NULL)
          if (s->contents == NULL)
            return FALSE;
            return FALSE;
 
 
          bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
          bfd_put (8 * hash_entry_size, output_bfd, bucketcount, s->contents);
          bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
          bfd_put (8 * hash_entry_size, output_bfd, dynsymcount,
Line 6288... Line 6368...
 
 
          /* Compute the hash values for all exported symbols.  At the same
          /* Compute the hash values for all exported symbols.  At the same
             time store the values in an array so that we could use them for
             time store the values in an array so that we could use them for
             optimizations.  */
             optimizations.  */
          amt = dynsymcount * 2 * sizeof (unsigned long int);
          amt = dynsymcount * 2 * sizeof (unsigned long int);
          cinfo.hashcodes = bfd_malloc (amt);
          cinfo.hashcodes = (long unsigned int *) bfd_malloc (amt);
          if (cinfo.hashcodes == NULL)
          if (cinfo.hashcodes == NULL)
            return FALSE;
            return FALSE;
 
 
          cinfo.hashval = cinfo.hashcodes + dynsymcount;
          cinfo.hashval = cinfo.hashcodes + dynsymcount;
          cinfo.min_dynindx = -1;
          cinfo.min_dynindx = -1;
Line 6301... Line 6381...
 
 
          /* Put all hash values in HASHCODES.  */
          /* Put all hash values in HASHCODES.  */
          elf_link_hash_traverse (elf_hash_table (info),
          elf_link_hash_traverse (elf_hash_table (info),
                                  elf_collect_gnu_hash_codes, &cinfo);
                                  elf_collect_gnu_hash_codes, &cinfo);
          if (cinfo.error)
          if (cinfo.error)
 
            {
 
              free (cinfo.hashcodes);
            return FALSE;
            return FALSE;
 
            }
 
 
          bucketcount
          bucketcount
            = compute_bucket_count (info, cinfo.hashcodes, cinfo.nsyms, 1);
            = compute_bucket_count (info, cinfo.hashcodes, cinfo.nsyms, 1);
 
 
          if (bucketcount == 0)
          if (bucketcount == 0)
Line 6321... Line 6404...
            {
            {
              /* Empty .gnu.hash section is special.  */
              /* Empty .gnu.hash section is special.  */
              BFD_ASSERT (cinfo.min_dynindx == -1);
              BFD_ASSERT (cinfo.min_dynindx == -1);
              free (cinfo.hashcodes);
              free (cinfo.hashcodes);
              s->size = 5 * 4 + bed->s->arch_size / 8;
              s->size = 5 * 4 + bed->s->arch_size / 8;
              contents = bfd_zalloc (output_bfd, s->size);
              contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
              if (contents == NULL)
              if (contents == NULL)
                return FALSE;
                return FALSE;
              s->contents = contents;
              s->contents = contents;
              /* 1 empty bucket.  */
              /* 1 empty bucket.  */
              bfd_put_32 (output_bfd, 1, contents);
              bfd_put_32 (output_bfd, 1, contents);
Line 6365... Line 6448...
              cinfo.shift2 = maskbitslog2;
              cinfo.shift2 = maskbitslog2;
              cinfo.maskbits = 1 << maskbitslog2;
              cinfo.maskbits = 1 << maskbitslog2;
              maskwords = 1 << (maskbitslog2 - cinfo.shift1);
              maskwords = 1 << (maskbitslog2 - cinfo.shift1);
              amt = bucketcount * sizeof (unsigned long int) * 2;
              amt = bucketcount * sizeof (unsigned long int) * 2;
              amt += maskwords * sizeof (bfd_vma);
              amt += maskwords * sizeof (bfd_vma);
              cinfo.bitmask = bfd_malloc (amt);
              cinfo.bitmask = (bfd_vma *) bfd_malloc (amt);
              if (cinfo.bitmask == NULL)
              if (cinfo.bitmask == NULL)
                {
                {
                  free (cinfo.hashcodes);
                  free (cinfo.hashcodes);
                  return FALSE;
                  return FALSE;
                }
                }
 
 
              cinfo.counts = (void *) (cinfo.bitmask + maskwords);
              cinfo.counts = (long unsigned int *) (cinfo.bitmask + maskwords);
              cinfo.indx = cinfo.counts + bucketcount;
              cinfo.indx = cinfo.counts + bucketcount;
              cinfo.symindx = dynsymcount - cinfo.nsyms;
              cinfo.symindx = dynsymcount - cinfo.nsyms;
              memset (cinfo.bitmask, 0, maskwords * sizeof (bfd_vma));
              memset (cinfo.bitmask, 0, maskwords * sizeof (bfd_vma));
 
 
              /* Determine how often each hash bucket is used.  */
              /* Determine how often each hash bucket is used.  */
Line 6394... Line 6477...
              cinfo.bucketcount = bucketcount;
              cinfo.bucketcount = bucketcount;
              cinfo.local_indx = cinfo.min_dynindx;
              cinfo.local_indx = cinfo.min_dynindx;
 
 
              s->size = (4 + bucketcount + cinfo.nsyms) * 4;
              s->size = (4 + bucketcount + cinfo.nsyms) * 4;
              s->size += cinfo.maskbits / 8;
              s->size += cinfo.maskbits / 8;
              contents = bfd_zalloc (output_bfd, s->size);
              contents = (unsigned char *) bfd_zalloc (output_bfd, s->size);
              if (contents == NULL)
              if (contents == NULL)
                {
                {
                  free (cinfo.bitmask);
                  free (cinfo.bitmask);
                  free (cinfo.hashcodes);
                  free (cinfo.hashcodes);
                  return FALSE;
                  return FALSE;
Line 6518... Line 6601...
{
{
  /* Allocate the structure if it has not already been allocated by a
  /* Allocate the structure if it has not already been allocated by a
     subclass.  */
     subclass.  */
  if (entry == NULL)
  if (entry == NULL)
    {
    {
      entry = bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry));
      entry = (struct bfd_hash_entry *)
 
          bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry));
      if (entry == NULL)
      if (entry == NULL)
        return entry;
        return entry;
    }
    }
 
 
  /* Call the allocation method of the superclass.  */
  /* Call the allocation method of the superclass.  */
Line 6605... Line 6689...
void
void
_bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
_bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
                                struct elf_link_hash_entry *h,
                                bfd_boolean force_local)
                                bfd_boolean force_local)
{
{
 
  /* STT_GNU_IFUNC symbol must go through PLT.  */
 
  if (h->type != STT_GNU_IFUNC)
 
    {
  h->plt = elf_hash_table (info)->init_plt_offset;
  h->plt = elf_hash_table (info)->init_plt_offset;
  h->needs_plt = 0;
  h->needs_plt = 0;
 
    }
  if (force_local)
  if (force_local)
    {
    {
      h->forced_local = 1;
      h->forced_local = 1;
      if (h->dynindx != -1)
      if (h->dynindx != -1)
        {
        {
Line 6655... Line 6743...
_bfd_elf_link_hash_table_create (bfd *abfd)
_bfd_elf_link_hash_table_create (bfd *abfd)
{
{
  struct elf_link_hash_table *ret;
  struct elf_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct elf_link_hash_table);
  bfd_size_type amt = sizeof (struct elf_link_hash_table);
 
 
  ret = bfd_malloc (amt);
  ret = (struct elf_link_hash_table *) bfd_malloc (amt);
  if (ret == NULL)
  if (ret == NULL)
    return NULL;
    return NULL;
 
 
  if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
  if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
                                       sizeof (struct elf_link_hash_entry)))
                                       sizeof (struct elf_link_hash_entry)))
Line 6747... Line 6835...
bfd_elf_get_bfd_needed_list (bfd *abfd,
bfd_elf_get_bfd_needed_list (bfd *abfd,
                             struct bfd_link_needed_list **pneeded)
                             struct bfd_link_needed_list **pneeded)
{
{
  asection *s;
  asection *s;
  bfd_byte *dynbuf = NULL;
  bfd_byte *dynbuf = NULL;
  int elfsec;
  unsigned int elfsec;
  unsigned long shlink;
  unsigned long shlink;
  bfd_byte *extdyn, *extdynend;
  bfd_byte *extdyn, *extdynend;
  size_t extdynsize;
  size_t extdynsize;
  void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
  void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
 
 
Line 6767... Line 6855...
 
 
  if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
  if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
    goto error_return;
    goto error_return;
 
 
  elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
  elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
  if (elfsec == -1)
  if (elfsec == SHN_BAD)
    goto error_return;
    goto error_return;
 
 
  shlink = elf_elfsections (abfd)[elfsec]->sh_link;
  shlink = elf_elfsections (abfd)[elfsec]->sh_link;
 
 
  extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
  extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
Line 6798... Line 6886...
          string = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
          string = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
          if (string == NULL)
          if (string == NULL)
            goto error_return;
            goto error_return;
 
 
          amt = sizeof *l;
          amt = sizeof *l;
          l = bfd_alloc (abfd, amt);
          l = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
          if (l == NULL)
          if (l == NULL)
            goto error_return;
            goto error_return;
 
 
          l->by = abfd;
          l->by = abfd;
          l->name = string;
          l->name = string;
Line 6870... Line 6958...
  Elf_Internal_Sym **ind, **indbufend, **indbuf;
  Elf_Internal_Sym **ind, **indbufend, **indbuf;
  struct elf_symbuf_symbol *ssym;
  struct elf_symbuf_symbol *ssym;
  struct elf_symbuf_head *ssymbuf, *ssymhead;
  struct elf_symbuf_head *ssymbuf, *ssymhead;
  bfd_size_type i, shndx_count, total_size;
  bfd_size_type i, shndx_count, total_size;
 
 
  indbuf = bfd_malloc2 (symcount, sizeof (*indbuf));
  indbuf = (Elf_Internal_Sym **) bfd_malloc2 (symcount, sizeof (*indbuf));
  if (indbuf == NULL)
  if (indbuf == NULL)
    return NULL;
    return NULL;
 
 
  for (ind = indbuf, i = 0; i < symcount; i++)
  for (ind = indbuf, i = 0; i < symcount; i++)
    if (isymbuf[i].st_shndx != SHN_UNDEF)
    if (isymbuf[i].st_shndx != SHN_UNDEF)
Line 6890... Line 6978...
      if (ind[0]->st_shndx != ind[1]->st_shndx)
      if (ind[0]->st_shndx != ind[1]->st_shndx)
        shndx_count++;
        shndx_count++;
 
 
  total_size = ((shndx_count + 1) * sizeof (*ssymbuf)
  total_size = ((shndx_count + 1) * sizeof (*ssymbuf)
                + (indbufend - indbuf) * sizeof (*ssym));
                + (indbufend - indbuf) * sizeof (*ssym));
  ssymbuf = bfd_malloc (total_size);
  ssymbuf = (struct elf_symbuf_head *) bfd_malloc (total_size);
  if (ssymbuf == NULL)
  if (ssymbuf == NULL)
    {
    {
      free (indbuf);
      free (indbuf);
      return NULL;
      return NULL;
    }
    }
Line 6939... Line 7027...
  Elf_Internal_Sym *isymbuf1, *isymbuf2;
  Elf_Internal_Sym *isymbuf1, *isymbuf2;
  struct elf_symbuf_head *ssymbuf1, *ssymbuf2;
  struct elf_symbuf_head *ssymbuf1, *ssymbuf2;
  Elf_Internal_Sym *isym, *isymend;
  Elf_Internal_Sym *isym, *isymend;
  struct elf_symbol *symtable1 = NULL, *symtable2 = NULL;
  struct elf_symbol *symtable1 = NULL, *symtable2 = NULL;
  bfd_size_type count1, count2, i;
  bfd_size_type count1, count2, i;
  int shndx1, shndx2;
  unsigned int shndx1, shndx2;
  bfd_boolean result;
  bfd_boolean result;
 
 
  bfd1 = sec1->owner;
  bfd1 = sec1->owner;
  bfd2 = sec2->owner;
  bfd2 = sec2->owner;
 
 
Line 6955... Line 7043...
  if (elf_section_type (sec1) != elf_section_type (sec2))
  if (elf_section_type (sec1) != elf_section_type (sec2))
    return FALSE;
    return FALSE;
 
 
  shndx1 = _bfd_elf_section_from_bfd_section (bfd1, sec1);
  shndx1 = _bfd_elf_section_from_bfd_section (bfd1, sec1);
  shndx2 = _bfd_elf_section_from_bfd_section (bfd2, sec2);
  shndx2 = _bfd_elf_section_from_bfd_section (bfd2, sec2);
  if (shndx1 == -1 || shndx2 == -1)
  if (shndx1 == SHN_BAD || shndx2 == SHN_BAD)
    return FALSE;
    return FALSE;
 
 
  bed1 = get_elf_backend_data (bfd1);
  bed1 = get_elf_backend_data (bfd1);
  bed2 = get_elf_backend_data (bfd2);
  bed2 = get_elf_backend_data (bfd2);
  hdr1 = &elf_tdata (bfd1)->symtab_hdr;
  hdr1 = &elf_tdata (bfd1)->symtab_hdr;
Line 6971... Line 7059...
    return FALSE;
    return FALSE;
 
 
  result = FALSE;
  result = FALSE;
  isymbuf1 = NULL;
  isymbuf1 = NULL;
  isymbuf2 = NULL;
  isymbuf2 = NULL;
  ssymbuf1 = elf_tdata (bfd1)->symbuf;
  ssymbuf1 = (struct elf_symbuf_head *) elf_tdata (bfd1)->symbuf;
  ssymbuf2 = elf_tdata (bfd2)->symbuf;
  ssymbuf2 = (struct elf_symbuf_head *) elf_tdata (bfd2)->symbuf;
 
 
  if (ssymbuf1 == NULL)
  if (ssymbuf1 == NULL)
    {
    {
      isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
      isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
                                       NULL, NULL, NULL);
                                       NULL, NULL, NULL);
Line 7012... Line 7100...
      ssymbuf1++;
      ssymbuf1++;
      count1 = 0;
      count1 = 0;
      while (lo < hi)
      while (lo < hi)
        {
        {
          mid = (lo + hi) / 2;
          mid = (lo + hi) / 2;
          if ((unsigned int) shndx1 < ssymbuf1[mid].st_shndx)
          if (shndx1 < ssymbuf1[mid].st_shndx)
            hi = mid;
            hi = mid;
          else if ((unsigned int) shndx1 > ssymbuf1[mid].st_shndx)
          else if (shndx1 > ssymbuf1[mid].st_shndx)
            lo = mid + 1;
            lo = mid + 1;
          else
          else
            {
            {
              count1 = ssymbuf1[mid].count;
              count1 = ssymbuf1[mid].count;
              ssymbuf1 += mid;
              ssymbuf1 += mid;
Line 7031... Line 7119...
      ssymbuf2++;
      ssymbuf2++;
      count2 = 0;
      count2 = 0;
      while (lo < hi)
      while (lo < hi)
        {
        {
          mid = (lo + hi) / 2;
          mid = (lo + hi) / 2;
          if ((unsigned int) shndx2 < ssymbuf2[mid].st_shndx)
          if (shndx2 < ssymbuf2[mid].st_shndx)
            hi = mid;
            hi = mid;
          else if ((unsigned int) shndx2 > ssymbuf2[mid].st_shndx)
          else if (shndx2 > ssymbuf2[mid].st_shndx)
            lo = mid + 1;
            lo = mid + 1;
          else
          else
            {
            {
              count2 = ssymbuf2[mid].count;
              count2 = ssymbuf2[mid].count;
              ssymbuf2 += mid;
              ssymbuf2 += mid;
Line 7046... Line 7134...
        }
        }
 
 
      if (count1 == 0 || count2 == 0 || count1 != count2)
      if (count1 == 0 || count2 == 0 || count1 != count2)
        goto done;
        goto done;
 
 
      symtable1 = bfd_malloc (count1 * sizeof (struct elf_symbol));
      symtable1 = (struct elf_symbol *)
      symtable2 = bfd_malloc (count2 * sizeof (struct elf_symbol));
          bfd_malloc (count1 * sizeof (struct elf_symbol));
 
      symtable2 = (struct elf_symbol *)
 
          bfd_malloc (count2 * sizeof (struct elf_symbol));
      if (symtable1 == NULL || symtable2 == NULL)
      if (symtable1 == NULL || symtable2 == NULL)
        goto done;
        goto done;
 
 
      symp = symtable1;
      symp = symtable1;
      for (ssym = ssymbuf1->ssym, ssymend = ssym + count1;
      for (ssym = ssymbuf1->ssym, ssymend = ssym + count1;
Line 7088... Line 7178...
 
 
      result = TRUE;
      result = TRUE;
      goto done;
      goto done;
    }
    }
 
 
  symtable1 = bfd_malloc (symcount1 * sizeof (struct elf_symbol));
  symtable1 = (struct elf_symbol *)
  symtable2 = bfd_malloc (symcount2 * sizeof (struct elf_symbol));
      bfd_malloc (symcount1 * sizeof (struct elf_symbol));
 
  symtable2 = (struct elf_symbol *)
 
      bfd_malloc (symcount2 * sizeof (struct elf_symbol));
  if (symtable1 == NULL || symtable2 == NULL)
  if (symtable1 == NULL || symtable2 == NULL)
    goto done;
    goto done;
 
 
  /* Count definitions in the section.  */
  /* Count definitions in the section.  */
  count1 = 0;
  count1 = 0;
  for (isym = isymbuf1, isymend = isym + symcount1; isym < isymend; isym++)
  for (isym = isymbuf1, isymend = isym + symcount1; isym < isymend; isym++)
    if (isym->st_shndx == (unsigned int) shndx1)
    if (isym->st_shndx == shndx1)
      symtable1[count1++].u.isym = isym;
      symtable1[count1++].u.isym = isym;
 
 
  count2 = 0;
  count2 = 0;
  for (isym = isymbuf2, isymend = isym + symcount2; isym < isymend; isym++)
  for (isym = isymbuf2, isymend = isym + symcount2; isym < isymend; isym++)
    if (isym->st_shndx == (unsigned int) shndx2)
    if (isym->st_shndx == shndx2)
      symtable2[count2++].u.isym = isym;
      symtable2[count2++].u.isym = isym;
 
 
  if (count1 == 0 || count2 == 0 || count1 != count2)
  if (count1 == 0 || count2 == 0 || count1 != count2)
    goto done;
    goto done;
 
 
Line 7677... Line 7769...
  if (lsb0_p)
  if (lsb0_p)
    shift = (start + 1) - len;
    shift = (start + 1) - len;
  else
  else
    shift = (8 * wordsz) - (start + len);
    shift = (8 * wordsz) - (start + len);
 
 
 
  /* FIXME: octets_per_byte.  */
  x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset);
  x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset);
 
 
#ifdef DEBUG
#ifdef DEBUG
  printf ("Doing complex reloc: "
  printf ("Doing complex reloc: "
          "lsb0? %ld, signed? %ld, trunc? %ld, wordsz %ld, "
          "lsb0? %ld, signed? %ld, trunc? %ld, wordsz %ld, "
Line 7708... Line 7801...
          " shifted/masked reloc: %8.8lx\n"
          " shifted/masked reloc: %8.8lx\n"
          "               result: %8.8lx\n",
          "               result: %8.8lx\n",
          relocation, (mask << shift),
          relocation, (mask << shift),
          ((relocation & mask) << shift), x);
          ((relocation & mask) << shift), x);
#endif
#endif
 
  /* FIXME: octets_per_byte.  */
  put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
  put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
  return r;
  return r;
}
}
 
 
/* When performing a relocatable link, the input relocations are
/* When performing a relocatable link, the input relocations are
Line 7791... Line 7885...
};
};
 
 
static int
static int
elf_link_sort_cmp1 (const void *A, const void *B)
elf_link_sort_cmp1 (const void *A, const void *B)
{
{
  const struct elf_link_sort_rela *a = A;
  const struct elf_link_sort_rela *a = (const struct elf_link_sort_rela *) A;
  const struct elf_link_sort_rela *b = B;
  const struct elf_link_sort_rela *b = (const struct elf_link_sort_rela *) B;
  int relativea, relativeb;
  int relativea, relativeb;
 
 
  relativea = a->type == reloc_class_relative;
  relativea = a->type == reloc_class_relative;
  relativeb = b->type == reloc_class_relative;
  relativeb = b->type == reloc_class_relative;
 
 
Line 7816... Line 7910...
}
}
 
 
static int
static int
elf_link_sort_cmp2 (const void *A, const void *B)
elf_link_sort_cmp2 (const void *A, const void *B)
{
{
  const struct elf_link_sort_rela *a = A;
  const struct elf_link_sort_rela *a = (const struct elf_link_sort_rela *) A;
  const struct elf_link_sort_rela *b = B;
  const struct elf_link_sort_rela *b = (const struct elf_link_sort_rela *) B;
  int copya, copyb;
  int copya, copyb;
 
 
  if (a->u.offset < b->u.offset)
  if (a->u.offset < b->u.offset)
    return -1;
    return -1;
  if (a->u.offset > b->u.offset)
  if (a->u.offset > b->u.offset)
Line 8015... Line 8109...
 
 
  sort_elt = (sizeof (struct elf_link_sort_rela)
  sort_elt = (sizeof (struct elf_link_sort_rela)
              + (i2e - 1) * sizeof (Elf_Internal_Rela));
              + (i2e - 1) * sizeof (Elf_Internal_Rela));
 
 
  count = dynamic_relocs->size / ext_size;
  count = dynamic_relocs->size / ext_size;
  sort = bfd_zmalloc (sort_elt * count);
  if (count == 0)
 
    return 0;
 
  sort = (bfd_byte *) bfd_zmalloc (sort_elt * count);
 
 
  if (sort == NULL)
  if (sort == NULL)
    {
    {
      (*info->callbacks->warning)
      (*info->callbacks->warning)
        (info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
        (info, _("Not enough memory to sort relocations"), 0, abfd, 0, 0);
Line 8045... Line 8141...
            free (sort);
            free (sort);
            return 0;
            return 0;
          }
          }
        erel = o->contents;
        erel = o->contents;
        erelend = o->contents + o->size;
        erelend = o->contents + o->size;
 
        /* FIXME: octets_per_byte.  */
        p = sort + o->output_offset / ext_size * sort_elt;
        p = sort + o->output_offset / ext_size * sort_elt;
 
 
        while (erel < erelend)
        while (erel < erelend)
          {
          {
            struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
            struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
Line 8089... Line 8186...
        bfd_byte *erel, *erelend;
        bfd_byte *erel, *erelend;
        asection *o = lo->u.indirect.section;
        asection *o = lo->u.indirect.section;
 
 
        erel = o->contents;
        erel = o->contents;
        erelend = o->contents + o->size;
        erelend = o->contents + o->size;
 
        /* FIXME: octets_per_byte.  */
        p = sort + o->output_offset / ext_size * sort_elt;
        p = sort + o->output_offset / ext_size * sort_elt;
        while (erel < erelend)
        while (erel < erelend)
          {
          {
            struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
            struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p;
            (*swap_out) (abfd, s->rela, erel);
            (*swap_out) (abfd, s->rela, erel);
Line 8132... Line 8230...
  return TRUE;
  return TRUE;
}
}
 
 
/* Add a symbol to the output symbol table.  */
/* Add a symbol to the output symbol table.  */
 
 
static bfd_boolean
static int
elf_link_output_sym (struct elf_final_link_info *finfo,
elf_link_output_sym (struct elf_final_link_info *finfo,
                     const char *name,
                     const char *name,
                     Elf_Internal_Sym *elfsym,
                     Elf_Internal_Sym *elfsym,
                     asection *input_sec,
                     asection *input_sec,
                     struct elf_link_hash_entry *h)
                     struct elf_link_hash_entry *h)
{
{
  bfd_byte *dest;
  bfd_byte *dest;
  Elf_External_Sym_Shndx *destshndx;
  Elf_External_Sym_Shndx *destshndx;
  bfd_boolean (*output_symbol_hook)
  int (*output_symbol_hook)
    (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
    (struct bfd_link_info *, const char *, Elf_Internal_Sym *, asection *,
     struct elf_link_hash_entry *);
     struct elf_link_hash_entry *);
  const struct elf_backend_data *bed;
  const struct elf_backend_data *bed;
 
 
  bed = get_elf_backend_data (finfo->output_bfd);
  bed = get_elf_backend_data (finfo->output_bfd);
  output_symbol_hook = bed->elf_backend_link_output_symbol_hook;
  output_symbol_hook = bed->elf_backend_link_output_symbol_hook;
  if (output_symbol_hook != NULL)
  if (output_symbol_hook != NULL)
    {
    {
      if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
      int ret = (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h);
        return FALSE;
      if (ret != 1)
 
        return ret;
    }
    }
 
 
  if (name == NULL || *name == '\0')
  if (name == NULL || *name == '\0')
    elfsym->st_name = 0;
    elfsym->st_name = 0;
  else if (input_sec->flags & SEC_EXCLUDE)
  else if (input_sec->flags & SEC_EXCLUDE)
Line 8163... Line 8262...
  else
  else
    {
    {
      elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
      elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
                                                            name, TRUE, FALSE);
                                                            name, TRUE, FALSE);
      if (elfsym->st_name == (unsigned long) -1)
      if (elfsym->st_name == (unsigned long) -1)
        return FALSE;
        return 0;
    }
    }
 
 
  if (finfo->symbuf_count >= finfo->symbuf_size)
  if (finfo->symbuf_count >= finfo->symbuf_size)
    {
    {
      if (! elf_link_flush_output_syms (finfo, bed))
      if (! elf_link_flush_output_syms (finfo, bed))
        return FALSE;
        return 0;
    }
    }
 
 
  dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym;
  dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym;
  destshndx = finfo->symshndxbuf;
  destshndx = finfo->symshndxbuf;
  if (destshndx != NULL)
  if (destshndx != NULL)
Line 8181... Line 8280...
      if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size)
      if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size)
        {
        {
          bfd_size_type amt;
          bfd_size_type amt;
 
 
          amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
          amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
          destshndx = bfd_realloc (destshndx, amt * 2);
          destshndx = (Elf_External_Sym_Shndx *) bfd_realloc (destshndx,
 
                                                              amt * 2);
          if (destshndx == NULL)
          if (destshndx == NULL)
            return FALSE;
            return 0;
          finfo->symshndxbuf = destshndx;
          finfo->symshndxbuf = destshndx;
          memset ((char *) destshndx + amt, 0, amt);
          memset ((char *) destshndx + amt, 0, amt);
          finfo->shndxbuf_size *= 2;
          finfo->shndxbuf_size *= 2;
        }
        }
      destshndx += bfd_get_symcount (finfo->output_bfd);
      destshndx += bfd_get_symcount (finfo->output_bfd);
Line 8195... Line 8295...
 
 
  bed->s->swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx);
  bed->s->swap_symbol_out (finfo->output_bfd, elfsym, dest, destshndx);
  finfo->symbuf_count += 1;
  finfo->symbuf_count += 1;
  bfd_get_symcount (finfo->output_bfd) += 1;
  bfd_get_symcount (finfo->output_bfd) += 1;
 
 
  return TRUE;
  return 1;
}
}
 
 
/* Return TRUE if the dynamic symbol SYM in ABFD is supported.  */
/* Return TRUE if the dynamic symbol SYM in ABFD is supported.  */
 
 
static bfd_boolean
static bfd_boolean
check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
check_dynsym (bfd *abfd, Elf_Internal_Sym *sym)
{
{
  if (sym->st_shndx > SHN_HIRESERVE)
  if (sym->st_shndx >= (SHN_LORESERVE & 0xffff)
 
      && sym->st_shndx < SHN_LORESERVE)
    {
    {
      /* The gABI doesn't support dynamic symbols in output sections
      /* The gABI doesn't support dynamic symbols in output sections
         beyond 64k.  */
         beyond 64k.  */
      (*_bfd_error_handler)
      (*_bfd_error_handler)
        (_("%B: Too many sections: %d (>= %d)"),
        (_("%B: Too many sections: %d (>= %d)"),
         abfd, bfd_count_sections (abfd), SHN_LORESERVE);
         abfd, bfd_count_sections (abfd), SHN_LORESERVE & 0xffff);
      bfd_set_error (bfd_error_nonrepresentable_section);
      bfd_set_error (bfd_error_nonrepresentable_section);
      return FALSE;
      return FALSE;
    }
    }
  return TRUE;
  return TRUE;
}
}
Line 8306... Line 8407...
      if (isymbuf == NULL)
      if (isymbuf == NULL)
        return FALSE;
        return FALSE;
 
 
      /* Read in any version definitions.  */
      /* Read in any version definitions.  */
      versymhdr = &elf_tdata (input)->dynversym_hdr;
      versymhdr = &elf_tdata (input)->dynversym_hdr;
      extversym = bfd_malloc (versymhdr->sh_size);
      extversym = (Elf_External_Versym *) bfd_malloc (versymhdr->sh_size);
      if (extversym == NULL)
      if (extversym == NULL)
        goto error_ret;
        goto error_ret;
 
 
      if (bfd_seek (input, versymhdr->sh_offset, SEEK_SET) != 0
      if (bfd_seek (input, versymhdr->sh_offset, SEEK_SET) != 0
          || (bfd_bread (extversym, versymhdr->sh_size, input)
          || (bfd_bread (extversym, versymhdr->sh_size, input)
Line 8374... Line 8475...
   global symbols.  */
   global symbols.  */
 
 
static bfd_boolean
static bfd_boolean
elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
{
{
  struct elf_outext_info *eoinfo = data;
  struct elf_outext_info *eoinfo = (struct elf_outext_info *) data;
  struct elf_final_link_info *finfo = eoinfo->finfo;
  struct elf_final_link_info *finfo = eoinfo->finfo;
  bfd_boolean strip;
  bfd_boolean strip;
  Elf_Internal_Sym sym;
  Elf_Internal_Sym sym;
  asection *input_sec;
  asection *input_sec;
  const struct elf_backend_data *bed;
  const struct elf_backend_data *bed;
 
  long indx;
 
  int ret;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    {
    {
      h = (struct elf_link_hash_entry *) h->root.u.i.link;
      h = (struct elf_link_hash_entry *) h->root.u.i.link;
      if (h->root.type == bfd_link_hash_new)
      if (h->root.type == bfd_link_hash_new)
Line 8493... Line 8596...
  sym.st_value = 0;
  sym.st_value = 0;
  sym.st_size = h->size;
  sym.st_size = h->size;
  sym.st_other = h->other;
  sym.st_other = h->other;
  if (h->forced_local)
  if (h->forced_local)
    sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
    sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
 
  else if (h->unique_global)
 
    sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
  else if (h->root.type == bfd_link_hash_undefweak
  else if (h->root.type == bfd_link_hash_undefweak
           || h->root.type == bfd_link_hash_defweak)
           || h->root.type == bfd_link_hash_defweak)
    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
  else
  else
    sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
    sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
Line 8581... Line 8686...
    }
    }
 
 
  /* Give the processor backend a chance to tweak the symbol value,
  /* Give the processor backend a chance to tweak the symbol value,
     and also to finish up anything that needs to be done for this
     and also to finish up anything that needs to be done for this
     symbol.  FIXME: Not calling elf_backend_finish_dynamic_symbol for
     symbol.  FIXME: Not calling elf_backend_finish_dynamic_symbol for
     forced local syms when non-shared is due to a historical quirk.  */
     forced local syms when non-shared is due to a historical quirk.
  if ((h->dynindx != -1
     STT_GNU_IFUNC symbol must go through PLT.  */
 
  if ((h->type == STT_GNU_IFUNC
 
       && h->def_regular
 
       && !finfo->info->relocatable)
 
      || ((h->dynindx != -1
       || h->forced_local)
       || h->forced_local)
      && ((finfo->info->shared
      && ((finfo->info->shared
           && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
           && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
               || h->root.type != bfd_link_hash_undefweak))
               || h->root.type != bfd_link_hash_undefweak))
          || !h->forced_local)
          || !h->forced_local)
      && elf_hash_table (finfo->info)->dynamic_sections_created)
          && elf_hash_table (finfo->info)->dynamic_sections_created))
    {
    {
      if (! ((*bed->elf_backend_finish_dynamic_symbol)
      if (! ((*bed->elf_backend_finish_dynamic_symbol)
             (finfo->output_bfd, finfo->info, h, &sym)))
             (finfo->output_bfd, finfo->info, h, &sym)))
        {
        {
          eoinfo->failed = TRUE;
          eoinfo->failed = TRUE;
Line 8610... Line 8719...
      && h->ref_regular
      && h->ref_regular
      && (ELF_ST_BIND (sym.st_info) == STB_GLOBAL
      && (ELF_ST_BIND (sym.st_info) == STB_GLOBAL
          || ELF_ST_BIND (sym.st_info) == STB_WEAK))
          || ELF_ST_BIND (sym.st_info) == STB_WEAK))
    {
    {
      int bindtype;
      int bindtype;
 
      unsigned int type = ELF_ST_TYPE (sym.st_info);
 
 
 
      /* Turn an undefined IFUNC symbol into a normal FUNC symbol. */
 
      if (type == STT_GNU_IFUNC)
 
        type = STT_FUNC;
 
 
      if (h->ref_regular_nonweak)
      if (h->ref_regular_nonweak)
        bindtype = STB_GLOBAL;
        bindtype = STB_GLOBAL;
      else
      else
        bindtype = STB_WEAK;
        bindtype = STB_WEAK;
      sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
      sym.st_info = ELF_ST_INFO (bindtype, type);
    }
    }
 
 
 
  /* If this is a symbol defined in a dynamic library, don't use the
 
     symbol size from the dynamic library.  Relinking an executable
 
     against a new library may introduce gratuitous changes in the
 
     executable's symbols if we keep the size.  */
 
  if (sym.st_shndx == SHN_UNDEF
 
      && !h->def_regular
 
      && h->def_dynamic)
 
    sym.st_size = 0;
 
 
  /* If a non-weak symbol with non-default visibility is not defined
  /* If a non-weak symbol with non-default visibility is not defined
     locally, it is a fatal error.  */
     locally, it is a fatal error.  */
  if (! finfo->info->relocatable
  if (! finfo->info->relocatable
      && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT
      && ELF_ST_VISIBILITY (sym.st_other) != STV_DEFAULT
      && ELF_ST_BIND (sym.st_info) != STB_WEAK
      && ELF_ST_BIND (sym.st_info) != STB_WEAK
Line 8713... Line 8836...
  /* If we're stripping it, then it was just a dynamic symbol, and
  /* If we're stripping it, then it was just a dynamic symbol, and
     there's nothing else to do.  */
     there's nothing else to do.  */
  if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
  if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
    return TRUE;
    return TRUE;
 
 
  h->indx = bfd_get_symcount (finfo->output_bfd);
  indx = bfd_get_symcount (finfo->output_bfd);
 
  ret = elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h);
  if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h))
  if (ret == 0)
    {
    {
      eoinfo->failed = TRUE;
      eoinfo->failed = TRUE;
      return FALSE;
      return FALSE;
    }
    }
 
  else if (ret == 1)
 
    h->indx = indx;
 
  else if (h->indx == -2)
 
    abort();
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Return TRUE if special handling is done for relocs in SEC against
/* Return TRUE if special handling is done for relocs in SEC against
Line 8887... Line 9014...
       isym++, pindex++, ppsection++)
       isym++, pindex++, ppsection++)
    {
    {
      asection *isec;
      asection *isec;
      const char *name;
      const char *name;
      Elf_Internal_Sym osym;
      Elf_Internal_Sym osym;
 
      long indx;
 
      int ret;
 
 
      *pindex = -1;
      *pindex = -1;
 
 
      if (elf_bad_symtab (input_bfd))
      if (elf_bad_symtab (input_bfd))
        {
        {
Line 8901... Line 9030...
            }
            }
        }
        }
 
 
      if (isym->st_shndx == SHN_UNDEF)
      if (isym->st_shndx == SHN_UNDEF)
        isec = bfd_und_section_ptr;
        isec = bfd_und_section_ptr;
      else if (isym->st_shndx < SHN_LORESERVE
 
               || isym->st_shndx > SHN_HIRESERVE)
 
        {
 
          isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
          if (isec
 
              && isec->sec_info_type == ELF_INFO_TYPE_MERGE
 
              && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
 
            isym->st_value =
 
              _bfd_merged_section_offset (output_bfd, &isec,
 
                                          elf_section_data (isec)->sec_info,
 
                                          isym->st_value);
 
        }
 
      else if (isym->st_shndx == SHN_ABS)
      else if (isym->st_shndx == SHN_ABS)
        isec = bfd_abs_section_ptr;
        isec = bfd_abs_section_ptr;
      else if (isym->st_shndx == SHN_COMMON)
      else if (isym->st_shndx == SHN_COMMON)
        isec = bfd_com_section_ptr;
        isec = bfd_com_section_ptr;
      else
      else
        {
        {
 
          isec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
 
          if (isec == NULL)
 
            {
          /* Don't attempt to output symbols with st_shnx in the
          /* Don't attempt to output symbols with st_shnx in the
             reserved range other than SHN_ABS and SHN_COMMON.  */
             reserved range other than SHN_ABS and SHN_COMMON.  */
          *ppsection = NULL;
          *ppsection = NULL;
          continue;
          continue;
        }
        }
 
          else if (isec->sec_info_type == ELF_INFO_TYPE_MERGE
 
                   && ELF_ST_TYPE (isym->st_info) != STT_SECTION)
 
            isym->st_value =
 
              _bfd_merged_section_offset (output_bfd, &isec,
 
                                          elf_section_data (isec)->sec_info,
 
                                          isym->st_value);
 
        }
 
 
      *ppsection = isec;
      *ppsection = isec;
 
 
      /* Don't output the first, undefined, symbol.  */
      /* Don't output the first, undefined, symbol.  */
      if (ppsection == finfo->sections)
      if (ppsection == finfo->sections)
Line 8955... Line 9082...
        continue;
        continue;
 
 
      /* If this symbol is defined in a section which we are
      /* If this symbol is defined in a section which we are
         discarding, we don't need to keep it.  */
         discarding, we don't need to keep it.  */
      if (isym->st_shndx != SHN_UNDEF
      if (isym->st_shndx != SHN_UNDEF
          && (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
          && isym->st_shndx < SHN_LORESERVE
          && (isec == NULL
          && bfd_section_removed_from_list (output_bfd,
              || bfd_section_removed_from_list (output_bfd,
                                            isec->output_section))
                                                isec->output_section)))
 
        continue;
        continue;
 
 
      /* Get the name of the symbol.  */
      /* Get the name of the symbol.  */
      name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
      name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
                                              isym->st_name);
                                              isym->st_name);
Line 8977... Line 9103...
                && (isec->flags & SEC_MERGE) && ! finfo->info->relocatable)
                && (isec->flags & SEC_MERGE) && ! finfo->info->relocatable)
               || finfo->info->discard == discard_l)
               || finfo->info->discard == discard_l)
              && bfd_is_local_label_name (input_bfd, name)))
              && bfd_is_local_label_name (input_bfd, name)))
        continue;
        continue;
 
 
      /* If we get here, we are going to output this symbol.  */
 
 
 
      osym = *isym;
      osym = *isym;
 
 
      /* Adjust the section index for the output file.  */
      /* Adjust the section index for the output file.  */
      osym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
      osym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
                                                         isec->output_section);
                                                         isec->output_section);
      if (osym.st_shndx == SHN_BAD)
      if (osym.st_shndx == SHN_BAD)
        return FALSE;
        return FALSE;
 
 
      *pindex = bfd_get_symcount (output_bfd);
 
 
 
      /* ELF symbols in relocatable files are section relative, but
      /* ELF symbols in relocatable files are section relative, but
         in executable files they are virtual addresses.  Note that
         in executable files they are virtual addresses.  Note that
         this code assumes that all ELF sections have an associated
         this code assumes that all ELF sections have an associated
         BFD section with a reasonable value for output_offset; below
         BFD section with a reasonable value for output_offset; below
         we assume that they also have a reasonable value for
         we assume that they also have a reasonable value for
Line 9008... Line 9130...
              BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
              BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
              osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
              osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
            }
            }
        }
        }
 
 
      if (! elf_link_output_sym (finfo, name, &osym, isec, NULL))
      indx = bfd_get_symcount (output_bfd);
 
      ret = elf_link_output_sym (finfo, name, &osym, isec, NULL);
 
      if (ret == 0)
        return FALSE;
        return FALSE;
 
      else if (ret == 1)
 
        *pindex = indx;
    }
    }
 
 
  /* Relocate the contents of each section.  */
  /* Relocate the contents of each section.  */
  sym_hashes = elf_sym_hashes (input_bfd);
  sym_hashes = elf_sym_hashes (input_bfd);
  for (o = input_bfd->sections; o != NULL; o = o->next)
  for (o = input_bfd->sections; o != NULL; o = o->next)
Line 9024... Line 9150...
        {
        {
          /* This section was omitted from the link.  */
          /* This section was omitted from the link.  */
          continue;
          continue;
        }
        }
 
 
 
      if (finfo->info->relocatable
 
          && (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP)
 
        {
 
          /* Deal with the group signature symbol.  */
 
          struct bfd_elf_section_data *sec_data = elf_section_data (o);
 
          unsigned long symndx = sec_data->this_hdr.sh_info;
 
          asection *osec = o->output_section;
 
 
 
          if (symndx >= locsymcount
 
              || (elf_bad_symtab (input_bfd)
 
                  && finfo->sections[symndx] == NULL))
 
            {
 
              struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff];
 
              while (h->root.type == bfd_link_hash_indirect
 
                     || h->root.type == bfd_link_hash_warning)
 
                h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
              /* Arrange for symbol to be output.  */
 
              h->indx = -2;
 
              elf_section_data (osec)->this_hdr.sh_info = -2;
 
            }
 
          else if (ELF_ST_TYPE (isymbuf[symndx].st_info) == STT_SECTION)
 
            {
 
              /* We'll use the output section target_index.  */
 
              asection *sec = finfo->sections[symndx]->output_section;
 
              elf_section_data (osec)->this_hdr.sh_info = sec->target_index;
 
            }
 
          else
 
            {
 
              if (finfo->indices[symndx] == -1)
 
                {
 
                  /* Otherwise output the local symbol now.  */
 
                  Elf_Internal_Sym sym = isymbuf[symndx];
 
                  asection *sec = finfo->sections[symndx]->output_section;
 
                  const char *name;
 
                  long indx;
 
                  int ret;
 
 
 
                  name = bfd_elf_string_from_elf_section (input_bfd,
 
                                                          symtab_hdr->sh_link,
 
                                                          sym.st_name);
 
                  if (name == NULL)
 
                    return FALSE;
 
 
 
                  sym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
 
                                                                    sec);
 
                  if (sym.st_shndx == SHN_BAD)
 
                    return FALSE;
 
 
 
                  sym.st_value += o->output_offset;
 
 
 
                  indx = bfd_get_symcount (output_bfd);
 
                  ret = elf_link_output_sym (finfo, name, &sym, o, NULL);
 
                  if (ret == 0)
 
                    return FALSE;
 
                  else if (ret == 1)
 
                    finfo->indices[symndx] = indx;
 
                  else
 
                    abort ();
 
                }
 
              elf_section_data (osec)->this_hdr.sh_info
 
                = finfo->indices[symndx];
 
            }
 
        }
 
 
      if ((o->flags & SEC_HAS_CONTENTS) == 0
      if ((o->flags & SEC_HAS_CONTENTS) == 0
          || (o->size == 0 && (o->flags & SEC_RELOC) == 0))
          || (o->size == 0 && (o->flags & SEC_RELOC) == 0))
        continue;
        continue;
 
 
      if ((o->flags & SEC_LINKER_CREATED) != 0)
      if ((o->flags & SEC_LINKER_CREATED) != 0)
Line 9146... Line 9336...
                  ps = &finfo->sections[r_symndx];
                  ps = &finfo->sections[r_symndx];
                  sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr,
                  sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr,
                                               sym, *ps);
                                               sym, *ps);
                }
                }
 
 
              if (s_type == STT_RELC || s_type == STT_SRELC)
              if ((s_type == STT_RELC || s_type == STT_SRELC)
 
                  && !finfo->info->relocatable)
                {
                {
                  bfd_vma val;
                  bfd_vma val;
                  bfd_vma dot = (rel->r_offset
                  bfd_vma dot = (rel->r_offset
                                 + o->output_offset + o->output_section->vma);
                                 + o->output_offset + o->output_section->vma);
#ifdef DEBUG
#ifdef DEBUG
Line 9407... Line 9598...
                      if (finfo->indices[r_symndx] == -1)
                      if (finfo->indices[r_symndx] == -1)
                        {
                        {
                          unsigned long shlink;
                          unsigned long shlink;
                          const char *name;
                          const char *name;
                          asection *osec;
                          asection *osec;
 
                          long indx;
 
 
                          if (finfo->info->strip == strip_all)
                          if (finfo->info->strip == strip_all)
                            {
                            {
                              /* You can't do ld -r -s.  */
                              /* You can't do ld -r -s.  */
                              bfd_set_error (bfd_error_invalid_operation);
                              bfd_set_error (bfd_error_invalid_operation);
Line 9446... Line 9638...
                                  sym.st_value -= (elf_hash_table (finfo->info)
                                  sym.st_value -= (elf_hash_table (finfo->info)
                                                   ->tls_sec->vma);
                                                   ->tls_sec->vma);
                                }
                                }
                            }
                            }
 
 
                          finfo->indices[r_symndx]
                          indx = bfd_get_symcount (output_bfd);
                            = bfd_get_symcount (output_bfd);
                          ret = elf_link_output_sym (finfo, name, &sym, sec,
 
                                                     NULL);
                          if (! elf_link_output_sym (finfo, name, &sym, sec,
                          if (ret == 0)
                                                     NULL))
 
                            return FALSE;
                            return FALSE;
 
                          else if (ret == 1)
 
                            finfo->indices[r_symndx] = indx;
 
                          else
 
                            abort ();
                        }
                        }
 
 
                      r_symndx = finfo->indices[r_symndx];
                      r_symndx = finfo->indices[r_symndx];
                    }
                    }
 
 
Line 9514... Line 9709...
              return FALSE;
              return FALSE;
          }
          }
          break;
          break;
        default:
        default:
          {
          {
 
            /* FIXME: octets_per_byte.  */
            if (! (o->flags & SEC_EXCLUDE)
            if (! (o->flags & SEC_EXCLUDE)
                && ! (o->output_section->flags & SEC_NEVER_LOAD)
                && ! (o->output_section->flags & SEC_NEVER_LOAD)
                && ! bfd_set_section_contents (output_bfd, o->output_section,
                && ! bfd_set_section_contents (output_bfd, o->output_section,
                                               contents,
                                               contents,
                                               (file_ptr) o->output_offset,
                                               (file_ptr) o->output_offset,
Line 9621... Line 9817...
      bfd_reloc_status_type rstat;
      bfd_reloc_status_type rstat;
      bfd_byte *buf;
      bfd_byte *buf;
      bfd_boolean ok;
      bfd_boolean ok;
      const char *sym_name;
      const char *sym_name;
 
 
      size = bfd_get_reloc_size (howto);
      size = (bfd_size_type) bfd_get_reloc_size (howto);
      buf = bfd_zmalloc (size);
      buf = (bfd_byte *) bfd_zmalloc (size);
      if (buf == NULL)
      if (buf == NULL)
        return FALSE;
        return FALSE;
      rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
      rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
      switch (rstat)
      switch (rstat)
        {
        {
Line 9782... Line 9978...
          sub = s->owner;
          sub = s->owner;
          if (bfd_get_flavour (sub) == bfd_target_elf_flavour
          if (bfd_get_flavour (sub) == bfd_target_elf_flavour
              && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass
              && elf_elfheader (sub)->e_ident[EI_CLASS] == bed->s->elfclass
              && (elfsec = _bfd_elf_section_from_bfd_section (sub, s))
              && (elfsec = _bfd_elf_section_from_bfd_section (sub, s))
              && elfsec < elf_numsections (sub)
              && elfsec < elf_numsections (sub)
              && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER)
              && elf_elfsections (sub)[elfsec]->sh_flags & SHF_LINK_ORDER
 
              && elf_elfsections (sub)[elfsec]->sh_link < elf_numsections (sub))
            {
            {
              seen_linkorder++;
              seen_linkorder++;
              linkorder_sec = s;
              linkorder_sec = s;
            }
            }
          else
          else
Line 9836... Line 10033...
    {
    {
      s = sections[n]->u.indirect.section;
      s = sections[n]->u.indirect.section;
      offset &= ~(bfd_vma) 0 << s->alignment_power;
      offset &= ~(bfd_vma) 0 << s->alignment_power;
      s->output_offset = offset;
      s->output_offset = offset;
      sections[n]->offset = offset;
      sections[n]->offset = offset;
 
      /* FIXME: octets_per_byte.  */
      offset += sections[n]->size;
      offset += sections[n]->size;
    }
    }
 
 
 
  free (sections);
  return TRUE;
  return TRUE;
}
}
 
 
 
 
/* Do the final step of an ELF link.  */
/* Do the final step of an ELF link.  */
Line 9998... Line 10197...
                merged = TRUE;
                merged = TRUE;
 
 
              if (info->relocatable || info->emitrelocations)
              if (info->relocatable || info->emitrelocations)
                reloc_count = sec->reloc_count;
                reloc_count = sec->reloc_count;
              else if (bed->elf_backend_count_relocs)
              else if (bed->elf_backend_count_relocs)
                {
                reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
                  Elf_Internal_Rela * relocs;
 
 
 
                  relocs = _bfd_elf_link_read_relocs (sec->owner, sec,
 
                                                      NULL, NULL,
 
                                                      info->keep_memory);
 
 
 
                  if (relocs != NULL)
 
                    {
 
                      reloc_count
 
                        = (*bed->elf_backend_count_relocs) (sec, relocs);
 
 
 
                      if (elf_section_data (sec)->relocs != relocs)
 
                        free (relocs);
 
                    }
 
                }
 
 
 
              if (sec->rawsize > max_contents_size)
              if (sec->rawsize > max_contents_size)
                max_contents_size = sec->rawsize;
                max_contents_size = sec->rawsize;
              if (sec->size > max_contents_size)
              if (sec->size > max_contents_size)
                max_contents_size = sec->size;
                max_contents_size = sec->size;
Line 10071... Line 10255...
            {
            {
              bfd_boolean same_size;
              bfd_boolean same_size;
              bfd_size_type entsize1;
              bfd_size_type entsize1;
 
 
              entsize1 = esdi->rel_hdr.sh_entsize;
              entsize1 = esdi->rel_hdr.sh_entsize;
 
              /* PR 9827: If the header size has not been set yet then
 
                 assume that it will match the output section's reloc type.  */
 
              if (entsize1 == 0)
 
                entsize1 = o->use_rela_p ? bed->s->sizeof_rela : bed->s->sizeof_rel;
 
              else
              BFD_ASSERT (entsize1 == bed->s->sizeof_rel
              BFD_ASSERT (entsize1 == bed->s->sizeof_rel
                          || entsize1 == bed->s->sizeof_rela);
                          || entsize1 == bed->s->sizeof_rela);
              same_size = !o->use_rela_p == (entsize1 == bed->s->sizeof_rel);
              same_size = !o->use_rela_p == (entsize1 == bed->s->sizeof_rel);
 
 
              if (!same_size)
              if (!same_size)
Line 10170... Line 10359...
  /* sh_flags, sh_addr and sh_size all start off zero.  */
  /* sh_flags, sh_addr and sh_size all start off zero.  */
  symtab_hdr->sh_entsize = bed->s->sizeof_sym;
  symtab_hdr->sh_entsize = bed->s->sizeof_sym;
  /* sh_link is set in assign_section_numbers.  */
  /* sh_link is set in assign_section_numbers.  */
  /* sh_info is set below.  */
  /* sh_info is set below.  */
  /* sh_offset is set just below.  */
  /* sh_offset is set just below.  */
  symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
  symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
 
 
  off = elf_tdata (abfd)->next_file_pos;
  off = elf_tdata (abfd)->next_file_pos;
  off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
  off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, TRUE);
 
 
  /* Note that at this point elf_tdata (abfd)->next_file_pos is
  /* Note that at this point elf_tdata (abfd)->next_file_pos is
Line 10187... Line 10376...
    finfo.symbuf_size = 20;
    finfo.symbuf_size = 20;
  else
  else
    finfo.symbuf_size = max_sym_count;
    finfo.symbuf_size = max_sym_count;
  amt = finfo.symbuf_size;
  amt = finfo.symbuf_size;
  amt *= bed->s->sizeof_sym;
  amt *= bed->s->sizeof_sym;
  finfo.symbuf = bfd_malloc (amt);
  finfo.symbuf = (bfd_byte *) bfd_malloc (amt);
  if (finfo.symbuf == NULL)
  if (finfo.symbuf == NULL)
    goto error_return;
    goto error_return;
  if (elf_numsections (abfd) > SHN_LORESERVE)
  if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
    {
    {
      /* Wild guess at number of output symbols.  realloc'd as needed.  */
      /* Wild guess at number of output symbols.  realloc'd as needed.  */
      amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
      amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
      finfo.shndxbuf_size = amt;
      finfo.shndxbuf_size = amt;
      amt *= sizeof (Elf_External_Sym_Shndx);
      amt *= sizeof (Elf_External_Sym_Shndx);
      finfo.symshndxbuf = bfd_zmalloc (amt);
      finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt);
      if (finfo.symshndxbuf == NULL)
      if (finfo.symshndxbuf == NULL)
        goto error_return;
        goto error_return;
    }
    }
 
 
  /* Start writing out the symbol table.  The first symbol is always a
  /* Start writing out the symbol table.  The first symbol is always a
Line 10211... Line 10400...
      elfsym.st_value = 0;
      elfsym.st_value = 0;
      elfsym.st_size = 0;
      elfsym.st_size = 0;
      elfsym.st_info = 0;
      elfsym.st_info = 0;
      elfsym.st_other = 0;
      elfsym.st_other = 0;
      elfsym.st_shndx = SHN_UNDEF;
      elfsym.st_shndx = SHN_UNDEF;
      if (! elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
      if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
                                 NULL))
                               NULL) != 1)
        goto error_return;
        goto error_return;
    }
    }
 
 
  /* Output a symbol for each section.  We output these even if we are
  /* Output a symbol for each section.  We output these even if we are
     discarding local symbols, since they are used for relocs.  These
     discarding local symbols, since they are used for relocs.  These
Line 10237... Line 10426...
            {
            {
              o->target_index = bfd_get_symcount (abfd);
              o->target_index = bfd_get_symcount (abfd);
              elfsym.st_shndx = i;
              elfsym.st_shndx = i;
              if (!info->relocatable)
              if (!info->relocatable)
                elfsym.st_value = o->vma;
                elfsym.st_value = o->vma;
              if (!elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL))
              if (elf_link_output_sym (&finfo, NULL, &elfsym, o, NULL) != 1)
                goto error_return;
                goto error_return;
            }
            }
          if (i == SHN_LORESERVE - 1)
 
            i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
 
        }
        }
    }
    }
 
 
  /* Allocate some memory to hold information read in from the input
  /* Allocate some memory to hold information read in from the input
     files.  */
     files.  */
  if (max_contents_size != 0)
  if (max_contents_size != 0)
    {
    {
      finfo.contents = bfd_malloc (max_contents_size);
      finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
      if (finfo.contents == NULL)
      if (finfo.contents == NULL)
        goto error_return;
        goto error_return;
    }
    }
 
 
  if (max_external_reloc_size != 0)
  if (max_external_reloc_size != 0)
Line 10265... Line 10452...
 
 
  if (max_internal_reloc_count != 0)
  if (max_internal_reloc_count != 0)
    {
    {
      amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
      amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
      amt *= sizeof (Elf_Internal_Rela);
      amt *= sizeof (Elf_Internal_Rela);
      finfo.internal_relocs = bfd_malloc (amt);
      finfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
      if (finfo.internal_relocs == NULL)
      if (finfo.internal_relocs == NULL)
        goto error_return;
        goto error_return;
    }
    }
 
 
  if (max_sym_count != 0)
  if (max_sym_count != 0)
    {
    {
      amt = max_sym_count * bed->s->sizeof_sym;
      amt = max_sym_count * bed->s->sizeof_sym;
      finfo.external_syms = bfd_malloc (amt);
      finfo.external_syms = (bfd_byte *) bfd_malloc (amt);
      if (finfo.external_syms == NULL)
      if (finfo.external_syms == NULL)
        goto error_return;
        goto error_return;
 
 
      amt = max_sym_count * sizeof (Elf_Internal_Sym);
      amt = max_sym_count * sizeof (Elf_Internal_Sym);
      finfo.internal_syms = bfd_malloc (amt);
      finfo.internal_syms = (Elf_Internal_Sym *) bfd_malloc (amt);
      if (finfo.internal_syms == NULL)
      if (finfo.internal_syms == NULL)
        goto error_return;
        goto error_return;
 
 
      amt = max_sym_count * sizeof (long);
      amt = max_sym_count * sizeof (long);
      finfo.indices = bfd_malloc (amt);
      finfo.indices = (long int *) bfd_malloc (amt);
      if (finfo.indices == NULL)
      if (finfo.indices == NULL)
        goto error_return;
        goto error_return;
 
 
      amt = max_sym_count * sizeof (asection *);
      amt = max_sym_count * sizeof (asection *);
      finfo.sections = bfd_malloc (amt);
      finfo.sections = (asection **) bfd_malloc (amt);
      if (finfo.sections == NULL)
      if (finfo.sections == NULL)
        goto error_return;
        goto error_return;
    }
    }
 
 
  if (max_sym_shndx_count != 0)
  if (max_sym_shndx_count != 0)
    {
    {
      amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx);
      amt = max_sym_shndx_count * sizeof (Elf_External_Sym_Shndx);
      finfo.locsym_shndx = bfd_malloc (amt);
      finfo.locsym_shndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
      if (finfo.locsym_shndx == NULL)
      if (finfo.locsym_shndx == NULL)
        goto error_return;
        goto error_return;
    }
    }
 
 
  if (elf_hash_table (info)->tls_sec)
  if (elf_hash_table (info)->tls_sec)
Line 10415... Line 10602...
 
 
  /* If backend needs to output some local symbols not present in the hash
  /* If backend needs to output some local symbols not present in the hash
     table, do it now.  */
     table, do it now.  */
  if (bed->elf_backend_output_arch_local_syms)
  if (bed->elf_backend_output_arch_local_syms)
    {
    {
      typedef bfd_boolean (*out_sym_func)
      typedef int (*out_sym_func)
        (void *, const char *, Elf_Internal_Sym *, asection *,
        (void *, const char *, Elf_Internal_Sym *, asection *,
         struct elf_link_hash_entry *);
         struct elf_link_hash_entry *);
 
 
      if (! ((*bed->elf_backend_output_arch_local_syms)
      if (! ((*bed->elf_backend_output_arch_local_syms)
             (abfd, info, &finfo, (out_sym_func) elf_link_output_sym)))
             (abfd, info, &finfo, (out_sym_func) elf_link_output_sym)))
Line 10488... Line 10675...
              /* Copy the internal symbol as is.
              /* Copy the internal symbol as is.
                 Note that we saved a word of storage and overwrote
                 Note that we saved a word of storage and overwrote
                 the original st_name with the dynstr_index.  */
                 the original st_name with the dynstr_index.  */
              sym = e->isym;
              sym = e->isym;
 
 
              if (e->isym.st_shndx != SHN_UNDEF
 
                  && (e->isym.st_shndx < SHN_LORESERVE
 
                      || e->isym.st_shndx > SHN_HIRESERVE))
 
                {
 
                  s = bfd_section_from_elf_index (e->input_bfd,
                  s = bfd_section_from_elf_index (e->input_bfd,
                                                  e->isym.st_shndx);
                                                  e->isym.st_shndx);
 
              if (s != NULL)
 
                {
                  sym.st_shndx =
                  sym.st_shndx =
                    elf_section_data (s->output_section)->this_idx;
                    elf_section_data (s->output_section)->this_idx;
                  if (! check_dynsym (abfd, &sym))
                  if (! check_dynsym (abfd, &sym))
                    return FALSE;
                    return FALSE;
                  sym.st_value = (s->output_section->vma
                  sym.st_value = (s->output_section->vma
Line 10529... Line 10713...
 
 
  /* If backend needs to output some symbols not present in the hash
  /* If backend needs to output some symbols not present in the hash
     table, do it now.  */
     table, do it now.  */
  if (bed->elf_backend_output_arch_syms)
  if (bed->elf_backend_output_arch_syms)
    {
    {
      typedef bfd_boolean (*out_sym_func)
      typedef int (*out_sym_func)
        (void *, const char *, Elf_Internal_Sym *, asection *,
        (void *, const char *, Elf_Internal_Sym *, asection *,
         struct elf_link_hash_entry *);
         struct elf_link_hash_entry *);
 
 
      if (! ((*bed->elf_backend_output_arch_syms)
      if (! ((*bed->elf_backend_output_arch_syms)
             (abfd, info, &finfo, (out_sym_func) elf_link_output_sym)))
             (abfd, info, &finfo, (out_sym_func) elf_link_output_sym)))
Line 10664... Line 10848...
                                          FALSE, FALSE, TRUE);
                                          FALSE, FALSE, TRUE);
                if (h != NULL
                if (h != NULL
                    && (h->root.type == bfd_link_hash_defined
                    && (h->root.type == bfd_link_hash_defined
                        || h->root.type == bfd_link_hash_defweak))
                        || h->root.type == bfd_link_hash_defweak))
                  {
                  {
                    dyn.d_un.d_val = h->root.u.def.value;
                    dyn.d_un.d_ptr = h->root.u.def.value;
                    o = h->root.u.def.section;
                    o = h->root.u.def.section;
                    if (o->output_section != NULL)
                    if (o->output_section != NULL)
                      dyn.d_un.d_val += (o->output_section->vma
                      dyn.d_un.d_ptr += (o->output_section->vma
                                         + o->output_offset);
                                         + o->output_offset);
                    else
                    else
                      {
                      {
                        /* The symbol is imported from another shared
                        /* The symbol is imported from another shared
                           library and does not apply to this one.  */
                           library and does not apply to this one.  */
                        dyn.d_un.d_val = 0;
                        dyn.d_un.d_ptr = 0;
                      }
                      }
                    break;
                    break;
                  }
                  }
              }
              }
              continue;
              continue;
Line 10752... Line 10936...
              if (dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ)
              if (dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ)
                type = SHT_REL;
                type = SHT_REL;
              else
              else
                type = SHT_RELA;
                type = SHT_RELA;
              dyn.d_un.d_val = 0;
              dyn.d_un.d_val = 0;
 
              dyn.d_un.d_ptr = 0;
              for (i = 1; i < elf_numsections (abfd); i++)
              for (i = 1; i < elf_numsections (abfd); i++)
                {
                {
                  Elf_Internal_Shdr *hdr;
                  Elf_Internal_Shdr *hdr;
 
 
                  hdr = elf_elfsections (abfd)[i];
                  hdr = elf_elfsections (abfd)[i];
Line 10764... Line 10949...
                    {
                    {
                      if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
                      if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
                        dyn.d_un.d_val += hdr->sh_size;
                        dyn.d_un.d_val += hdr->sh_size;
                      else
                      else
                        {
                        {
                          if (dyn.d_un.d_val == 0
                          if (dyn.d_un.d_ptr == 0
                              || hdr->sh_addr < dyn.d_un.d_val)
                              || hdr->sh_addr < dyn.d_un.d_ptr)
                            dyn.d_un.d_val = hdr->sh_addr;
                            dyn.d_un.d_ptr = hdr->sh_addr;
                        }
                        }
                    }
                    }
                }
                }
              break;
              break;
            }
            }
Line 10828... Line 11013...
            continue;
            continue;
          if ((elf_section_data (o->output_section)->this_hdr.sh_type
          if ((elf_section_data (o->output_section)->this_hdr.sh_type
               != SHT_STRTAB)
               != SHT_STRTAB)
              || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
              || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
            {
            {
 
              /* FIXME: octets_per_byte.  */
              if (! bfd_set_section_contents (abfd, o->output_section,
              if (! bfd_set_section_contents (abfd, o->output_section,
                                              o->contents,
                                              o->contents,
                                              (file_ptr) o->output_offset,
                                              (file_ptr) o->output_offset,
                                              o->size))
                                              o->size))
                goto error_return;
                goto error_return;
Line 10902... Line 11088...
 
 
  elf_tdata (abfd)->linker = TRUE;
  elf_tdata (abfd)->linker = TRUE;
 
 
  if (attr_section)
  if (attr_section)
    {
    {
      bfd_byte *contents = bfd_malloc (attr_size);
      bfd_byte *contents = (bfd_byte *) bfd_malloc (attr_size);
      if (contents == NULL)
      if (contents == NULL)
        return FALSE;   /* Bail out and fail.  */
        return FALSE;   /* Bail out and fail.  */
      bfd_elf_set_obj_attr_contents (abfd, contents, attr_size);
      bfd_elf_set_obj_attr_contents (abfd, contents, attr_size);
      bfd_set_section_contents (abfd, attr_section, contents, 0, attr_size);
      bfd_set_section_contents (abfd, attr_section, contents, 0, attr_size);
      free (contents);
      free (contents);
Line 11244... Line 11430...
  if ((h->root.type == bfd_link_hash_defined
  if ((h->root.type == bfd_link_hash_defined
       || h->root.type == bfd_link_hash_defweak)
       || h->root.type == bfd_link_hash_defweak)
      && !h->root.u.def.section->gc_mark
      && !h->root.u.def.section->gc_mark
      && !(h->root.u.def.section->owner->flags & DYNAMIC))
      && !(h->root.u.def.section->owner->flags & DYNAMIC))
    {
    {
      struct elf_gc_sweep_symbol_info *inf = data;
      struct elf_gc_sweep_symbol_info *inf =
 
          (struct elf_gc_sweep_symbol_info *) data;
      (*inf->hide_symbol) (inf->info, h, TRUE);
      (*inf->hide_symbol) (inf->info, h, TRUE);
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
Line 11274... Line 11461...
      if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
      if (bfd_get_flavour (sub) != bfd_target_elf_flavour)
        continue;
        continue;
 
 
      for (o = sub->sections; o != NULL; o = o->next)
      for (o = sub->sections; o != NULL; o = o->next)
        {
        {
          /* Keep debug and special sections.  */
          /* When any section in a section group is kept, we keep all
          if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
             sections in the section group.  If the first member of
 
             the section group is excluded, we will also exclude the
 
             group section.  */
 
          if (o->flags & SEC_GROUP)
 
            {
 
              asection *first = elf_next_in_group (o);
 
              o->gc_mark = first->gc_mark;
 
            }
 
          else if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
              || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
              || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
 
            {
 
              /* Keep debug and special sections.  */
            o->gc_mark = 1;
            o->gc_mark = 1;
 
            }
 
 
          if (o->gc_mark)
          if (o->gc_mark)
            continue;
            continue;
 
 
          /* Skip sweeping sections already excluded.  */
          /* Skip sweeping sections already excluded.  */
Line 11614... Line 11812...
  return FALSE;
  return FALSE;
 
 
 win:
 win:
  if (!child->vtable)
  if (!child->vtable)
    {
    {
      child->vtable = bfd_zalloc (abfd, sizeof (*child->vtable));
      child->vtable = (struct elf_link_virtual_table_entry *)
 
          bfd_zalloc (abfd, sizeof (*child->vtable));
      if (!child->vtable)
      if (!child->vtable)
        return FALSE;
        return FALSE;
    }
    }
  if (!h)
  if (!h)
    {
    {
Line 11646... Line 11845...
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  unsigned int log_file_align = bed->s->log_file_align;
  unsigned int log_file_align = bed->s->log_file_align;
 
 
  if (!h->vtable)
  if (!h->vtable)
    {
    {
      h->vtable = bfd_zalloc (abfd, sizeof (*h->vtable));
      h->vtable = (struct elf_link_virtual_table_entry *)
 
          bfd_zalloc (abfd, sizeof (*h->vtable));
      if (!h->vtable)
      if (!h->vtable)
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (addend >= h->vtable->size)
  if (addend >= h->vtable->size)
Line 11679... Line 11879...
         consolidation pass.  */
         consolidation pass.  */
      bytes = ((size >> log_file_align) + 1) * sizeof (bfd_boolean);
      bytes = ((size >> log_file_align) + 1) * sizeof (bfd_boolean);
 
 
      if (ptr)
      if (ptr)
        {
        {
          ptr = bfd_realloc (ptr - 1, bytes);
          ptr = (bfd_boolean *) bfd_realloc (ptr - 1, bytes);
 
 
          if (ptr != NULL)
          if (ptr != NULL)
            {
            {
              size_t oldbytes;
              size_t oldbytes;
 
 
Line 11691... Line 11891...
                          * sizeof (bfd_boolean));
                          * sizeof (bfd_boolean));
              memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
              memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
            }
            }
        }
        }
      else
      else
        ptr = bfd_zmalloc (bytes);
        ptr = (bfd_boolean *) bfd_zmalloc (bytes);
 
 
      if (ptr == NULL)
      if (ptr == NULL)
        return FALSE;
        return FALSE;
 
 
      /* And arrange for that done flag to be at index -1.  */
      /* And arrange for that done flag to be at index -1.  */
Line 11708... Line 11908...
  return TRUE;
  return TRUE;
}
}
 
 
struct alloc_got_off_arg {
struct alloc_got_off_arg {
  bfd_vma gotoff;
  bfd_vma gotoff;
  unsigned int got_elt_size;
  struct bfd_link_info *info;
};
};
 
 
/* We need a special top-level link routine to convert got reference counts
/* We need a special top-level link routine to convert got reference counts
   to real got offsets.  */
   to real got offsets.  */
 
 
static bfd_boolean
static bfd_boolean
elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg)
elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg)
{
{
  struct alloc_got_off_arg *gofarg = arg;
  struct alloc_got_off_arg *gofarg = (struct alloc_got_off_arg *) arg;
 
  bfd *obfd = gofarg->info->output_bfd;
 
  const struct elf_backend_data *bed = get_elf_backend_data (obfd);
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 
  if (h->got.refcount > 0)
  if (h->got.refcount > 0)
    {
    {
      h->got.offset = gofarg->gotoff;
      h->got.offset = gofarg->gotoff;
      gofarg->gotoff += gofarg->got_elt_size;
      gofarg->gotoff += bed->got_elt_size (obfd, gofarg->info, h, NULL, 0);
    }
    }
  else
  else
    h->got.offset = (bfd_vma) -1;
    h->got.offset = (bfd_vma) -1;
 
 
  return TRUE;
  return TRUE;
Line 11743... Line 11945...
                                        struct bfd_link_info *info)
                                        struct bfd_link_info *info)
{
{
  bfd *i;
  bfd *i;
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  bfd_vma gotoff;
  bfd_vma gotoff;
  unsigned int got_elt_size = bed->s->arch_size / 8;
 
  struct alloc_got_off_arg gofarg;
  struct alloc_got_off_arg gofarg;
 
 
 
  BFD_ASSERT (abfd == info->output_bfd);
 
 
  if (! is_elf_hash_table (info->hash))
  if (! is_elf_hash_table (info->hash))
    return FALSE;
    return FALSE;
 
 
  /* The GOT offset is relative to the .got section, but the GOT header is
  /* The GOT offset is relative to the .got section, but the GOT header is
     put into the .got.plt section, if the backend uses it.  */
     put into the .got.plt section, if the backend uses it.  */
Line 11781... Line 11984...
      for (j = 0; j < locsymcount; ++j)
      for (j = 0; j < locsymcount; ++j)
        {
        {
          if (local_got[j] > 0)
          if (local_got[j] > 0)
            {
            {
              local_got[j] = gotoff;
              local_got[j] = gotoff;
              gotoff += got_elt_size;
              gotoff += bed->got_elt_size (abfd, info, NULL, i, j);
            }
            }
          else
          else
            local_got[j] = (bfd_vma) -1;
            local_got[j] = (bfd_vma) -1;
        }
        }
    }
    }
 
 
  /* Then the global .got entries.  .plt refcounts are handled by
  /* Then the global .got entries.  .plt refcounts are handled by
     adjust_dynamic_symbol  */
     adjust_dynamic_symbol  */
  gofarg.gotoff = gotoff;
  gofarg.gotoff = gotoff;
  gofarg.got_elt_size = got_elt_size;
  gofarg.info = info;
  elf_link_hash_traverse (elf_hash_table (info),
  elf_link_hash_traverse (elf_hash_table (info),
                          elf_gc_allocate_got_offsets,
                          elf_gc_allocate_got_offsets,
                          &gofarg);
                          &gofarg);
  return TRUE;
  return TRUE;
}
}
Line 11814... Line 12017...
}
}
 
 
bfd_boolean
bfd_boolean
bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
bfd_elf_reloc_symbol_deleted_p (bfd_vma offset, void *cookie)
{
{
  struct elf_reloc_cookie *rcookie = cookie;
  struct elf_reloc_cookie *rcookie = (struct elf_reloc_cookie *) cookie;
 
 
  if (rcookie->bad_symtab)
  if (rcookie->bad_symtab)
    rcookie->rel = rcookie->rels;
    rcookie->rel = rcookie->rels;
 
 
  for (; rcookie->rel < rcookie->relend; rcookie->rel++)
  for (; rcookie->rel < rcookie->relend; rcookie->rel++)
Line 11861... Line 12064...
          asection *isec;
          asection *isec;
          Elf_Internal_Sym *isym;
          Elf_Internal_Sym *isym;
 
 
          /* Need to: get the symbol; get the section.  */
          /* Need to: get the symbol; get the section.  */
          isym = &rcookie->locsyms[r_symndx];
          isym = &rcookie->locsyms[r_symndx];
          if (isym->st_shndx < SHN_LORESERVE || isym->st_shndx > SHN_HIRESERVE)
 
            {
 
              isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx);
              isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx);
              if (isec != NULL && elf_discarded_section (isec))
              if (isec != NULL && elf_discarded_section (isec))
                return TRUE;
                return TRUE;
            }
            }
        }
 
      return FALSE;
      return FALSE;
    }
    }
  return FALSE;
  return FALSE;
}
}
 
 
Line 11966... Line 12166...
    ret = TRUE;
    ret = TRUE;
 
 
  return ret;
  return ret;
}
}
 
 
 
/* For a SHT_GROUP section, return the group signature.  For other
 
   sections, return the normal section name.  */
 
 
 
static const char *
 
section_signature (asection *sec)
 
{
 
  if ((sec->flags & SEC_GROUP) != 0
 
      && elf_next_in_group (sec) != NULL
 
      && elf_group_name (elf_next_in_group (sec)) != NULL)
 
    return elf_group_name (elf_next_in_group (sec));
 
  return sec->name;
 
}
 
 
void
void
_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section *sec,
_bfd_elf_section_already_linked (bfd *abfd, asection *sec,
                                 struct bfd_link_info *info)
                                 struct bfd_link_info *info)
{
{
  flagword flags;
  flagword flags;
  const char *name, *p;
  const char *name, *p;
  struct bfd_section_already_linked *l;
  struct bfd_section_already_linked *l;
Line 12007... Line 12220...
 
 
     Also, not merging link once sections in a relocatable link
     Also, not merging link once sections in a relocatable link
     causes trouble for MIPS ELF, which relies on link once semantics
     causes trouble for MIPS ELF, which relies on link once semantics
     to handle the .reginfo section correctly.  */
     to handle the .reginfo section correctly.  */
 
 
  name = bfd_get_section_name (abfd, sec);
  name = section_signature (sec);
 
 
  if (CONST_STRNEQ (name, ".gnu.linkonce.")
  if (CONST_STRNEQ (name, ".gnu.linkonce.")
      && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
      && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
    p++;
    p++;
  else
  else
Line 12022... Line 12235...
  for (l = already_linked_list->entry; l != NULL; l = l->next)
  for (l = already_linked_list->entry; l != NULL; l = l->next)
    {
    {
      /* We may have 2 different types of sections on the list: group
      /* We may have 2 different types of sections on the list: group
         sections and linkonce sections.  Match like sections.  */
         sections and linkonce sections.  Match like sections.  */
      if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
      if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
          && strcmp (name, l->sec->name) == 0
          && strcmp (name, section_signature (l->sec)) == 0
          && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
          && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
        {
        {
          /* The section has already been linked.  See if we should
          /* The section has already been linked.  See if we should
             issue a warning.  */
             issue a warning.  */
          switch (flags & SEC_LINK_DUPLICATES)
          switch (flags & SEC_LINK_DUPLICATES)
Line 12145... Line 12358...
              sec->kept_section = first;
              sec->kept_section = first;
              break;
              break;
            }
            }
        }
        }
 
 
 
  /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
 
     referencing its discarded `.gnu.linkonce.t.F' counterpart - g++-3.4
 
     specific as g++-4.x is using COMDAT groups (without the `.gnu.linkonce'
 
     prefix) instead.  `.gnu.linkonce.r.*' were the `.rodata' part of its
 
     matching `.gnu.linkonce.t.*'.  If `.gnu.linkonce.r.F' is not discarded
 
     but its `.gnu.linkonce.t.F' is discarded means we chose one-only
 
     `.gnu.linkonce.t.F' section from a different bfd not requiring any
 
     `.gnu.linkonce.r.F'.  Thus `.gnu.linkonce.r.F' should be discarded.
 
     The reverse order cannot happen as there is never a bfd with only the
 
     `.gnu.linkonce.r.F' section.  The order of sections in a bfd does not
 
     matter as here were are looking only for cross-bfd sections.  */
 
 
 
  if ((flags & SEC_GROUP) == 0 && CONST_STRNEQ (name, ".gnu.linkonce.r."))
 
    for (l = already_linked_list->entry; l != NULL; l = l->next)
 
      if ((l->sec->flags & SEC_GROUP) == 0
 
          && CONST_STRNEQ (l->sec->name, ".gnu.linkonce.t."))
 
        {
 
          if (abfd != l->sec->owner)
 
            sec->output_section = bfd_abs_section_ptr;
 
          break;
 
        }
 
 
  /* This is the first section with this name.  Record it.  */
  /* This is the first section with this name.  Record it.  */
  if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
  if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
    info->callbacks->einfo (_("%F%P: already_linked_table: %E"));
    info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
}
}
 
 
bfd_boolean
bfd_boolean
_bfd_elf_common_definition (Elf_Internal_Sym *sym)
_bfd_elf_common_definition (Elf_Internal_Sym *sym)
{
{
Line 12168... Line 12403...
_bfd_elf_common_section (asection *sec ATTRIBUTE_UNUSED)
_bfd_elf_common_section (asection *sec ATTRIBUTE_UNUSED)
{
{
  return bfd_com_section_ptr;
  return bfd_com_section_ptr;
}
}
 
 
 No newline at end of file
 No newline at end of file
 
bfd_vma
 
_bfd_elf_default_got_elt_size (bfd *abfd,
 
                               struct bfd_link_info *info ATTRIBUTE_UNUSED,
 
                               struct elf_link_hash_entry *h ATTRIBUTE_UNUSED,
 
                               bfd *ibfd ATTRIBUTE_UNUSED,
 
                               unsigned long symndx ATTRIBUTE_UNUSED)
 
{
 
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
  return bed->s->arch_size / 8;
 
}
 
 
 
/* Routines to support the creation of dynamic relocs.  */
 
 
 
/* Return true if NAME is a name of a relocation
 
   section associated with section S.  */
 
 
 
static bfd_boolean
 
is_reloc_section (bfd_boolean rela, const char * name, asection * s)
 
{
 
  if (rela)
 
    return CONST_STRNEQ (name, ".rela")
 
      && strcmp (bfd_get_section_name (NULL, s), name + 5) == 0;
 
 
 
  return CONST_STRNEQ (name, ".rel")
 
    && strcmp (bfd_get_section_name (NULL, s), name + 4) == 0;
 
}
 
 
 
/* Returns the name of the dynamic reloc section associated with SEC.  */
 
 
 
static const char *
 
get_dynamic_reloc_section_name (bfd *       abfd,
 
                                asection *  sec,
 
                                bfd_boolean is_rela)
 
{
 
  const char * name;
 
  unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
 
  unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name;
 
 
 
  name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
 
  if (name == NULL)
 
    return NULL;
 
 
 
  if (! is_reloc_section (is_rela, name, sec))
 
    {
 
      static bfd_boolean complained = FALSE;
 
 
 
      if (! complained)
 
        {
 
          (*_bfd_error_handler)
 
            (_("%B: bad relocation section name `%s\'"),  abfd, name);
 
          complained = TRUE;
 
        }
 
      name = NULL;
 
    }
 
 
 
  return name;
 
}
 
 
 
/* Returns the dynamic reloc section associated with SEC.
 
   If necessary compute the name of the dynamic reloc section based
 
   on SEC's name (looked up in ABFD's string table) and the setting
 
   of IS_RELA.  */
 
 
 
asection *
 
_bfd_elf_get_dynamic_reloc_section (bfd *       abfd,
 
                                    asection *  sec,
 
                                    bfd_boolean is_rela)
 
{
 
  asection * reloc_sec = elf_section_data (sec)->sreloc;
 
 
 
  if (reloc_sec == NULL)
 
    {
 
      const char * name = get_dynamic_reloc_section_name (abfd, sec, is_rela);
 
 
 
      if (name != NULL)
 
        {
 
          reloc_sec = bfd_get_section_by_name (abfd, name);
 
 
 
          if (reloc_sec != NULL)
 
            elf_section_data (sec)->sreloc = reloc_sec;
 
        }
 
    }
 
 
 
  return reloc_sec;
 
}
 
 
 
/* Returns the dynamic reloc section associated with SEC.  If the
 
   section does not exist it is created and attached to the DYNOBJ
 
   bfd and stored in the SRELOC field of SEC's elf_section_data
 
   structure.
 
 
 
   ALIGNMENT is the alignment for the newly created section and
 
   IS_RELA defines whether the name should be .rela.<SEC's name>
 
   or .rel.<SEC's name>.  The section name is looked up in the
 
   string table associated with ABFD.  */
 
 
 
asection *
 
_bfd_elf_make_dynamic_reloc_section (asection *         sec,
 
                                     bfd *              dynobj,
 
                                     unsigned int       alignment,
 
                                     bfd *              abfd,
 
                                     bfd_boolean        is_rela)
 
{
 
  asection * reloc_sec = elf_section_data (sec)->sreloc;
 
 
 
  if (reloc_sec == NULL)
 
    {
 
      const char * name = get_dynamic_reloc_section_name (abfd, sec, is_rela);
 
 
 
      if (name == NULL)
 
        return NULL;
 
 
 
      reloc_sec = bfd_get_section_by_name (dynobj, name);
 
 
 
      if (reloc_sec == NULL)
 
        {
 
          flagword flags;
 
 
 
          flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
 
          if ((sec->flags & SEC_ALLOC) != 0)
 
            flags |= SEC_ALLOC | SEC_LOAD;
 
 
 
          reloc_sec = bfd_make_section_with_flags (dynobj, name, flags);
 
          if (reloc_sec != NULL)
 
            {
 
              if (! bfd_set_section_alignment (dynobj, reloc_sec, alignment))
 
                reloc_sec = NULL;
 
            }
 
        }
 
 
 
      elf_section_data (sec)->sreloc = reloc_sec;
 
    }
 
 
 
  return reloc_sec;
 
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.