2009-09-01 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / bfd / elflink.c
index d0e4534894acdc9742c2f6d3eef0c969b4770a71..d6534f768dea26b3781e16763a691262f0026824 100644 (file)
@@ -101,58 +101,57 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   asection *s;
   struct elf_link_hash_entry *h;
   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.  */
   s = bfd_get_section_by_name (abfd, ".got");
   if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0)
     return TRUE;
 
-  switch (bed->s->arch_size)
-    {
-    case 32:
-      ptralign = 2;
-      break;
-
-    case 64:
-      ptralign = 3;
-      break;
-
-    default:
-      bfd_set_error (bfd_error_bad_value);
-      return FALSE;
-    }
-
   flags = bed->dynamic_sec_flags;
 
+  s = bfd_make_section_with_flags (abfd,
+                                  (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;
+  htab->srelgot = s;
+
   s = bfd_make_section_with_flags (abfd, ".got", flags);
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, ptralign))
+      || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
+  htab->sgot = s;
 
   if (bed->want_got_plt)
     {
       s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
       if (s == NULL
-         || !bfd_set_section_alignment (abfd, s, ptralign))
+         || !bfd_set_section_alignment (abfd, s,
+                                        bed->s->log_file_align))
        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)
     {
       /* 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
         because we don't want to define the symbol if we are not creating
         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;
       if (h == NULL)
        return FALSE;
     }
 
-  /* The first bit of the global offset table is the header.  */
-  s->size += bed->got_header_size;
-
   return TRUE;
 }
 \f
@@ -303,6 +302,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_entry *h;
   asection *s;
   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
      .rel[a].bss sections.  */
@@ -323,6 +323,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
     return FALSE;
+  htab->splt = s;
 
   /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
      .plt section.  */
@@ -342,6 +343,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
     return FALSE;
+  htab->srelplt = s;
 
   if (! _bfd_elf_create_got_section (abfd, info))
     return FALSE;
@@ -1246,6 +1248,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
   oldweak = (h->root.type == bfd_link_hash_defweak
             || 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
      old symbol comes from a dynamic library, we treat the new one as
      strong.  Similarly, an old weak symbol definition from a regular
@@ -1798,80 +1803,6 @@ nondefault:
   return TRUE;
 }
 \f
-static struct bfd_elf_version_tree *
-find_version_for_sym (struct bfd_elf_version_tree *verdefs,
-                     const char *sym_name,
-                     bfd_boolean *hide)
-{
-  struct bfd_elf_version_tree *t;
-  struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
-
-  local_ver = NULL;
-  global_ver = NULL;
-  exist_ver = NULL;
-  for (t = verdefs; t != NULL; t = t->next)
-    {
-      if (t->globals.list != NULL)
-       {
-         struct bfd_elf_version_expr *d = NULL;
-
-         while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
-           {
-             global_ver = t;
-             if (d->symver)
-               exist_ver = t;
-             d->script = 1;
-             /* If the match is a wildcard pattern, keep looking for
-                a more explicit, perhaps even local, match.  */
-             if (d->literal)
-               break;
-           }
-
-         if (d != NULL)
-           break;
-       }
-
-      if (t->locals.list != NULL)
-       {
-         struct bfd_elf_version_expr *d = NULL;
-
-         while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
-           {
-             local_ver = t;
-             /* If the match is a wildcard pattern, keep looking for
-                a more explicit, perhaps even global, match.  */
-             if (d->literal)
-               {
-                 /* An exact match overrides a global wildcard.  */
-                 global_ver = NULL;
-                 break;
-               }
-           }
-
-         if (d != NULL)
-           break;
-       }
-    }
-
-  if (global_ver != NULL)
-    {
-      /* If we already have a versioned symbol that matches the
-        node for this symbol, then we don't want to create a
-        duplicate from the unversioned symbol.  Instead hide the
-        unversioned symbol.  */
-      *hide = exist_ver == global_ver;
-      return global_ver;
-    }
-
-  if (local_ver != NULL)
-    {
-      *hide = TRUE;
-      return local_ver;
-    }
-
-  return NULL;
-}
-
 /* This routine is used to export all defined symbols into the dynamic
    symbol table.  It is called via elf_link_hash_traverse.  */
 
@@ -1898,7 +1829,7 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
       bfd_boolean hide;
 
       if (eif->verdefs == NULL
-         || (find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
+         || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
              && !hide))
        {
          if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
@@ -2160,7 +2091,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
     {
       bfd_boolean hide;
 
-      h->verinfo.vertree = find_version_for_sym (sinfo->verdefs,
+      h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs,
                                                 h->root.root.string, &hide);
       if (h->verinfo.vertree != NULL && hide)
        (*bed->elf_backend_hide_symbol) (info, h, TRUE);
@@ -2202,7 +2133,7 @@ elf_link_read_relocs_from_section (bfd *abfd,
     return FALSE;
 
   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);
 
@@ -2228,11 +2159,24 @@ elf_link_read_relocs_from_section (bfd *abfd,
       r_symndx = ELF32_R_SYM (irela->r_info);
       if (bed->s->arch_size == 64)
        r_symndx >>= 24;
-      if ((size_t) r_symndx >= nsyms)
+      if (nsyms > 0)
+       {
+         if ((size_t) r_symndx >= nsyms)
+           {
+             (*_bfd_error_handler)
+               (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
+                  " for offset 0x%lx in section `%A'"),
+                abfd, sec,
+                (unsigned long) r_symndx, (unsigned long) nsyms, irela->r_offset);
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           }
+       }
+      else if (r_symndx != 0)
        {
          (*_bfd_error_handler)
-           (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
-              " for offset 0x%lx in section `%A'"),
+           (_("%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);
@@ -2661,6 +2605,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
      about symbols which are defined by one dynamic object and
      referenced by another one?  */
   if (!h->needs_plt
+      && h->type != STT_GNU_IFUNC
       && (h->def_regular
          || !h->def_dynamic
          || (!h->ref_regular
@@ -3412,6 +3357,7 @@ _bfd_elf_relocs_compatible (const bfd_target *input,
 static bfd_boolean
 elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 {
+  Elf_Internal_Ehdr *ehdr;
   Elf_Internal_Shdr *hdr;
   bfd_size_type symcount;
   bfd_size_type extsymcount;
@@ -3467,6 +3413,17 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
+  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
      .gnu.warning.SYMBOL are treated as warning symbols for the given
      symbol.  This differs from .gnu.warning sections, which generate
@@ -3596,7 +3553,11 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          unsigned long shlink;
 
          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);
          if (elfsec == SHN_BAD)
@@ -3680,11 +3641,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
                  amt = strlen (fnm) + 1;
                  anm = bfd_alloc (abfd, amt);
                  if (anm == NULL)
-                   {
-                   error_free_dyn:
-                     free (dynbuf);
-                     goto error_return;
-                   }
+                   goto error_free_dyn;
                  memcpy (anm, fnm, amt);
                  n->name = anm;
                  n->by = abfd;
@@ -3918,24 +3875,31 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       common = bed->common_definition (isym);
 
       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
             global symbols follow all local symbols, and that sh_info
             point to the first global symbol.  Unfortunately, Irix 5
             screws this up.  */
          continue;
-       }
-      else if (bind == STB_GLOBAL)
-       {
+
+       case STB_GLOBAL:
          if (isym->st_shndx != SHN_UNDEF && !common)
            flags = BSF_GLOBAL;
-       }
-      else if (bind == STB_WEAK)
-       flags = BSF_WEAK;
-      else
-       {
+         break;
+
+       case STB_WEAK:
+         flags = BSF_WEAK;
+         break;
+
+       case STB_GNU_UNIQUE:
+         flags = BSF_GNU_UNIQUE;
+         break;
+
+       default:
          /* Leave it up to the processor backend.  */
+         break;
        }
 
       if (isym->st_shndx == SHN_UNDEF)
@@ -4187,7 +4151,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       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;
+
       *sym_hash = h;
+      h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
 
       new_weakdef = FALSE;
       if (dynamic
@@ -4326,15 +4292,24 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          if (ELF_ST_TYPE (isym->st_info) != STT_NOTYPE
              && (definition || h->type == STT_NOTYPE))
            {
-             if (h->type != STT_NOTYPE
-                 && h->type != ELF_ST_TYPE (isym->st_info)
-                 && ! type_change_ok)
-               (*_bfd_error_handler)
-                 (_("Warning: type of symbol `%s' changed"
-                    " from %d to %d in %B"),
-                  abfd, name, h->type, ELF_ST_TYPE (isym->st_info));
+             unsigned int type = ELF_ST_TYPE (isym->st_info);
+
+             /* 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)
+                     (_("Warning: type of symbol `%s' changed"
+                        " from %d to %d in %B"),
+                      abfd, name, h->type, type);
 
-             h->type = ELF_ST_TYPE (isym->st_info);
+                 h->type = type;
+               }
            }
 
          /* Merge st_other field.  */
@@ -6711,8 +6686,12 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
                                bfd_boolean force_local)
 {
-  h->plt = elf_hash_table (info)->init_plt_offset;
-  h->needs_plt = 0;
+  /* STT_GNU_IFUNC symbol must go through PLT.  */
+  if (h->type != STT_GNU_IFUNC)
+    {
+      h->plt = elf_hash_table (info)->init_plt_offset;
+      h->needs_plt = 0;
+    }
   if (force_local)
     {
       h->forced_local = 1;
@@ -7783,6 +7762,7 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
   else
     shift = (8 * wordsz) - (start + len);
 
+  /* FIXME: octets_per_byte.  */
   x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset);
 
 #ifdef DEBUG
@@ -7814,6 +7794,7 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
          relocation, (mask << shift),
          ((relocation & mask) << shift), x);
 #endif
+  /* FIXME: octets_per_byte.  */
   put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
   return r;
 }
@@ -8121,6 +8102,8 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
              + (i2e - 1) * sizeof (Elf_Internal_Rela));
 
   count = dynamic_relocs->size / ext_size;
+  if (count == 0)
+    return 0;
   sort = bfd_zmalloc (sort_elt * count);
 
   if (sort == NULL)
@@ -8151,6 +8134,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
          }
        erel = o->contents;
        erelend = o->contents + o->size;
+       /* FIXME: octets_per_byte.  */
        p = sort + o->output_offset / ext_size * sort_elt;
 
        while (erel < erelend)
@@ -8195,6 +8179,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
 
        erel = o->contents;
        erelend = o->contents + o->size;
+       /* FIXME: octets_per_byte.  */
        p = sort + o->output_offset / ext_size * sort_elt;
        while (erel < erelend)
          {
@@ -8238,7 +8223,7 @@ elf_link_flush_output_syms (struct elf_final_link_info *finfo,
 
 /* Add a symbol to the output symbol table.  */
 
-static bfd_boolean
+static int
 elf_link_output_sym (struct elf_final_link_info *finfo,
                     const char *name,
                     Elf_Internal_Sym *elfsym,
@@ -8247,7 +8232,7 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
 {
   bfd_byte *dest;
   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 elf_link_hash_entry *);
   const struct elf_backend_data *bed;
@@ -8256,8 +8241,9 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
   output_symbol_hook = bed->elf_backend_link_output_symbol_hook;
   if (output_symbol_hook != NULL)
     {
-      if (! (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h))
-       return FALSE;
+      int ret = (*output_symbol_hook) (finfo->info, name, elfsym, input_sec, h);
+      if (ret != 1)
+       return ret;
     }
 
   if (name == NULL || *name == '\0')
@@ -8269,13 +8255,13 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
       elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
                                                            name, TRUE, FALSE);
       if (elfsym->st_name == (unsigned long) -1)
-       return FALSE;
+       return 0;
     }
 
   if (finfo->symbuf_count >= finfo->symbuf_size)
     {
       if (! elf_link_flush_output_syms (finfo, bed))
-       return FALSE;
+       return 0;
     }
 
   dest = finfo->symbuf + finfo->symbuf_count * bed->s->sizeof_sym;
@@ -8289,7 +8275,7 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
          amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
          destshndx = bfd_realloc (destshndx, amt * 2);
          if (destshndx == NULL)
-           return FALSE;
+           return 0;
          finfo->symshndxbuf = destshndx;
          memset ((char *) destshndx + amt, 0, amt);
          finfo->shndxbuf_size *= 2;
@@ -8301,7 +8287,7 @@ elf_link_output_sym (struct elf_final_link_info *finfo,
   finfo->symbuf_count += 1;
   bfd_get_symcount (finfo->output_bfd) += 1;
 
-  return TRUE;
+  return 1;
 }
 
 /* Return TRUE if the dynamic symbol SYM in ABFD is supported.  */
@@ -8487,6 +8473,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   Elf_Internal_Sym sym;
   asection *input_sec;
   const struct elf_backend_data *bed;
+  long indx;
+  int ret;
 
   if (h->root.type == bfd_link_hash_warning)
     {
@@ -8600,6 +8588,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   sym.st_other = h->other;
   if (h->forced_local)
     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
           || h->root.type == bfd_link_hash_defweak)
     sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
@@ -8688,14 +8678,18 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   /* Give the processor backend a chance to tweak the symbol value,
      and also to finish up anything that needs to be done for this
      symbol.  FIXME: Not calling elf_backend_finish_dynamic_symbol for
-     forced local syms when non-shared is due to a historical quirk.  */
-  if ((h->dynindx != -1
-       || h->forced_local)
-      && ((finfo->info->shared
-          && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-              || h->root.type != bfd_link_hash_undefweak))
-         || !h->forced_local)
-      && elf_hash_table (finfo->info)->dynamic_sections_created)
+     forced local syms when non-shared is due to a historical quirk.
+     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)
+         && ((finfo->info->shared
+              && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                  || h->root.type != bfd_link_hash_undefweak))
+             || !h->forced_local)
+         && elf_hash_table (finfo->info)->dynamic_sections_created))
     {
       if (! ((*bed->elf_backend_finish_dynamic_symbol)
             (finfo->output_bfd, finfo->info, h, &sym)))
@@ -8717,12 +8711,17 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
          || ELF_ST_BIND (sym.st_info) == STB_WEAK))
     {
       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)
        bindtype = STB_GLOBAL;
       else
        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
@@ -8829,13 +8828,17 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   if (strip || (input_sec->flags & SEC_EXCLUDE) != 0)
     return TRUE;
 
-  h->indx = bfd_get_symcount (finfo->output_bfd);
-
-  if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h))
+  indx = bfd_get_symcount (finfo->output_bfd);
+  ret = elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec, h);
+  if (ret == 0)
     {
       eoinfo->failed = TRUE;
       return FALSE;
     }
+  else if (ret == 1)
+    h->indx = indx;
+  else if (h->indx == -2)
+    abort();
 
   return TRUE;
 }
@@ -9003,6 +9006,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
       asection *isec;
       const char *name;
       Elf_Internal_Sym osym;
+      long indx;
+      int ret;
 
       *pindex = -1;
 
@@ -9090,8 +9095,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
              && bfd_is_local_label_name (input_bfd, name)))
        continue;
 
-      /* If we get here, we are going to output this symbol.  */
-
       osym = *isym;
 
       /* Adjust the section index for the output file.  */
@@ -9100,8 +9103,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
       if (osym.st_shndx == SHN_BAD)
        return FALSE;
 
-      *pindex = bfd_get_symcount (output_bfd);
-
       /* ELF symbols in relocatable files are section relative, but
         in executable files they are virtual addresses.  Note that
         this code assumes that all ELF sections have an associated
@@ -9121,8 +9122,12 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
            }
        }
 
-      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;
+      else if (ret == 1)
+       *pindex = indx;
     }
 
   /* Relocate the contents of each section.  */
@@ -9171,6 +9176,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                  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,
@@ -9185,9 +9192,14 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
 
                  sym.st_value += o->output_offset;
 
-                 finfo->indices[symndx] = bfd_get_symcount (output_bfd);
-                 if (! elf_link_output_sym (finfo, name, &sym, o, NULL))
+                 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];
@@ -9316,7 +9328,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                                               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 dot = (rel->r_offset
@@ -9577,6 +9590,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                          unsigned long shlink;
                          const char *name;
                          asection *osec;
+                         long indx;
 
                          if (finfo->info->strip == strip_all)
                            {
@@ -9616,12 +9630,15 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                                }
                            }
 
-                         finfo->indices[r_symndx]
-                           = bfd_get_symcount (output_bfd);
-
-                         if (! elf_link_output_sym (finfo, name, &sym, sec,
-                                                    NULL))
+                         indx = bfd_get_symcount (output_bfd);
+                         ret = elf_link_output_sym (finfo, name, &sym, sec,
+                                                    NULL);
+                         if (ret == 0)
                            return FALSE;
+                         else if (ret == 1)
+                           finfo->indices[r_symndx] = indx;
+                         else
+                           abort ();
                        }
 
                      r_symndx = finfo->indices[r_symndx];
@@ -9684,6 +9701,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          break;
        default:
          {
+           /* FIXME: octets_per_byte.  */
            if (! (o->flags & SEC_EXCLUDE)
                && ! (o->output_section->flags & SEC_NEVER_LOAD)
                && ! bfd_set_section_contents (output_bfd, o->output_section,
@@ -10007,6 +10025,7 @@ elf_fixup_link_order (bfd *abfd, asection *o)
       offset &= ~(bfd_vma) 0 << s->alignment_power;
       s->output_offset = offset;
       sections[n]->offset = offset;
+      /* FIXME: octets_per_byte.  */
       offset += sections[n]->size;
     }
 
@@ -10373,8 +10392,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       elfsym.st_info = 0;
       elfsym.st_other = 0;
       elfsym.st_shndx = SHN_UNDEF;
-      if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
-                                NULL))
+      if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
+                              NULL) != 1)
        goto error_return;
     }
 
@@ -10399,7 +10418,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              elfsym.st_shndx = i;
              if (!info->relocatable)
                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;
            }
        }
@@ -10575,7 +10594,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
      table, do it now.  */
   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 *,
         struct elf_link_hash_entry *);
 
@@ -10686,7 +10705,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
      table, do it now.  */
   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 *,
         struct elf_link_hash_entry *);
 
@@ -10986,6 +11005,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
               != SHT_STRTAB)
              || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
            {
+             /* FIXME: octets_per_byte.  */
              if (! bfd_set_section_contents (abfd, o->output_section,
                                              o->contents,
                                              (file_ptr) o->output_offset,
@@ -12351,7 +12371,7 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec,
 
   /* This is the first section with this name.  Record it.  */
   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
This page took 0.037886 seconds and 4 git commands to generate.