* elf32-arm.c (elf32_arm_output_symbol_hook): Install new entry into the
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index dc75331b06f2b8ddd933275103eef8ae2e15c17d..99a0def3b9daaf8a252e4f18dd01f67e574998b9 100644 (file)
@@ -456,7 +456,6 @@ static struct mips_got_info *mips_elf_got_for_ibfd
 static bfd *reldyn_sorting_bfd;
 
 /* Nonzero if ABFD is using the N32 ABI.  */
-
 #define ABI_N32_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
 
@@ -2638,6 +2637,9 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
        return FALSE;
     }
 
+  /* Make sure we have a GOT to put this entry into.  */
+  BFD_ASSERT (g != NULL);
+
   entry.abfd = abfd;
   entry.symndx = -1;
   entry.d.h = (struct mips_elf_link_hash_entry *) h;
@@ -2762,7 +2764,7 @@ mips_elf_bfd2got_entry_eq (const void *entry1, const void *entry2)
   return e1->bfd == e2->bfd;
 }
 
-/* In a multi-got link, determine the GOT to be used for IBDF.  G must
+/* In a multi-got link, determine the GOT to be used for IBFD.  G must
    be the master GOT data.  */
 
 static struct mips_got_info *
@@ -3792,6 +3794,17 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
          BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
          symbol = 0;
        }
+      else if (ELF_MIPS_IS_OPTIONAL (h->root.other))
+       {
+         /* This is an optional symbol - an Irix specific extension to the
+            ELF spec.  Ignore it for now.
+            XXX - FIXME - there is more to the spec for OPTIONAL symbols
+            than simply ignoring them, but we do not handle this for now.
+            For information see the "64-bit ELF Object File Specification"
+            which is available from here:
+            http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf  */
+         symbol = 0;
+       }
       else
        {
          if (! ((*info->callbacks->undefined_symbol)
@@ -3918,7 +3931,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
          if (h->tls_type == GOT_NORMAL
              && (! elf_hash_table(info)->dynamic_sections_created
                  || (info->shared
-                     && (info->symbolic || h->root.dynindx == -1)
+                     && (info->symbolic || h->root.forced_local)
                      && h->root.def_regular)))
            {
              /* This is a static link or a -Bsymbolic link.  The
@@ -3970,7 +3983,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
 
   if (gnu_local_gp_p)
     symbol = gp;
-  
+
   /* Figure out what kind of relocation is being performed.  */
   switch (r_type)
     {
@@ -4024,12 +4037,6 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       value &= howto->dst_mask;
       break;
 
-    case R_MIPS_GNU_REL16_S2:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
-      overflowed_p = mips_elf_overflow_p (value, 18);
-      value = (value >> 2) & howto->dst_mask;
-      break;
-
     case R_MIPS16_26:
       /* The calculation for R_MIPS16_26 is just the same as for an
         R_MIPS_26.  It's only the storage of the relocated field into
@@ -4193,8 +4200,10 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       break;
 
     case R_MIPS_PC16:
-      value = _bfd_mips_elf_sign_extend (addend, 16) + symbol - p;
-      overflowed_p = mips_elf_overflow_p (value, 16);
+    case R_MIPS_GNU_REL16_S2:
+      value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
+      overflowed_p = mips_elf_overflow_p (value, 18);
+      value = (value >> 2) & howto->dst_mask;
       break;
 
     case R_MIPS_GOT_HI16:
@@ -4483,10 +4492,8 @@ mips_elf_create_dynamic_relocation (bfd *output_bfd,
   /* We must now calculate the dynamic symbol table index to use
      in the relocation.  */
   if (h != NULL
-      && (! info->symbolic || !h->root.def_regular)
-      /* h->root.dynindx may be -1 if this symbol was marked to
-        become local.  */
-      && h->root.dynindx != -1)
+      && (!h->root.def_regular
+         || (info->shared && !info->symbolic && !h->root.forced_local)))
     {
       indx = h->root.dynindx;
       if (SGI_COMPAT (output_bfd))
@@ -5414,6 +5421,20 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
       return TRUE;
     }
 
+  /* Shared objects may have a dynamic symbol '_gp_disp' defined as
+     a SECTION *ABS*.  This causes ld to think it can resolve _gp_disp
+     by setting a DT_NEEDED for the shared object.  Since _gp_disp is
+     a magic symbol resolved by the linker, we ignore this bogus definition
+     of _gp_disp.  New ABI objects do not suffer from this problem so this
+     is not done for them. */
+  if (!NEWABI_P(abfd)
+      && (sym->st_shndx == SHN_ABS)
+      && (strcmp (*namep, "_gp_disp") == 0))
+    {
+      *namep = NULL;
+      return TRUE;
+    }
+
   switch (sym->st_shndx)
     {
     case SHN_COMMON:
@@ -5979,6 +6000,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            case R_MIPS_GOT_PAGE:
            case R_MIPS_GOT_OFST:
            case R_MIPS_GOT_DISP:
+           case R_MIPS_TLS_GOTTPREL:
            case R_MIPS_TLS_GD:
            case R_MIPS_TLS_LDM:
              if (dynobj == NULL)
@@ -6668,7 +6690,6 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       const char *name;
-      bfd_boolean strip;
 
       /* It's OK to base decisions on the section name, because none
         of the dynobj section names depend upon the input files.  */
@@ -6677,24 +6698,9 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
       if ((s->flags & SEC_LINKER_CREATED) == 0)
        continue;
 
-      strip = FALSE;
-
       if (strncmp (name, ".rel", 4) == 0)
        {
-         if (s->size == 0)
-           {
-             /* We only strip the section if the output section name
-                 has the same name.  Otherwise, there might be several
-                 input sections for this output section.  FIXME: This
-                 code is probably not needed these days anyhow, since
-                 the linker now does not create empty output sections.  */
-             if (s->output_section != NULL
-                 && strcmp (name,
-                            bfd_get_section_name (s->output_section->owner,
-                                                  s->output_section)) == 0)
-               strip = TRUE;
-           }
-         else
+         if (s->size != 0)
            {
              const char *outname;
              asection *target;
@@ -6818,15 +6824,18 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
          continue;
        }
 
-      if (strip)
+      if (s->size == 0)
        {
          s->flags |= SEC_EXCLUDE;
          continue;
        }
 
+      if ((s->flags & SEC_HAS_CONTENTS) == 0)
+       continue;
+
       /* Allocate memory for the section contents.  */
       s->contents = bfd_zalloc (dynobj, s->size);
-      if (s->contents == NULL && s->size != 0)
+      if (s->contents == NULL)
        {
          bfd_set_error (bfd_error_no_memory);
          return FALSE;
@@ -6941,7 +6950,7 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   for (rel = relocs; rel < relend; ++rel)
     {
       const char *name;
-      bfd_vma value;
+      bfd_vma value = 0;
       reloc_howto_type *howto;
       bfd_boolean require_jalx;
       /* TRUE if the relocation is a RELA relocation, rather than a
@@ -7378,7 +7387,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
                                   MIPS_ELF_STUB_SECTION_NAME (dynobj));
       BFD_ASSERT (s != NULL);
 
-      /* FIXME: Can h->dynindex be more than 64K?  */
+      /* FIXME: Can h->dynindx be more than 64K?  */
       if (h->dynindx & 0xffff0000)
        return FALSE;
 
@@ -7637,7 +7646,11 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_MIPS_TIME_STAMP:
-             time ((time_t *) &dyn.d_un.d_val);
+             {
+               time_t t;
+               time (&t);
+               dyn.d_un.d_val = t;
+             }
              break;
 
            case DT_MIPS_ICHECKSUM:
@@ -8382,13 +8395,13 @@ _bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
    _bfd_elf_link_hash_copy_indirect copy the flags for us.  */
 
 void
-_bfd_mips_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
+_bfd_mips_elf_copy_indirect_symbol (struct bfd_link_info *info,
                                    struct elf_link_hash_entry *dir,
                                    struct elf_link_hash_entry *ind)
 {
   struct mips_elf_link_hash_entry *dirmips, *indmips;
 
-  _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 
   if (ind->root.type != bfd_link_hash_indirect)
     return;
@@ -8403,8 +8416,6 @@ _bfd_mips_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
 
   if (dirmips->tls_type == 0)
     dirmips->tls_type = indmips->tls_type;
-  else
-    BFD_ASSERT (indmips->tls_type == 0);
 }
 
 void
@@ -8423,11 +8434,10 @@ _bfd_mips_elf_hide_symbol (struct bfd_link_info *info,
   h->forced_local = force_local;
 
   dynobj = elf_hash_table (info)->dynobj;
-  if (dynobj != NULL && force_local && h->root.type != STT_TLS)
+  if (dynobj != NULL && force_local && h->root.type != STT_TLS
+      && (got = mips_elf_got_section (dynobj, FALSE)) != NULL
+      && (g = mips_elf_section_data (got)->u.got_info) != NULL)
     {
-      got = mips_elf_got_section (dynobj, FALSE);
-      g = mips_elf_section_data (got)->u.got_info;
-
       if (g->next)
        {
          struct mips_got_entry e;
@@ -8846,7 +8856,7 @@ _bfd_elf_mips_get_relocated_section_contents
                                               input_section, relocatable,
                                               data, gp);
          else
-           r = bfd_perform_relocation (input_bfd, *parent, data, 
+           r = bfd_perform_relocation (input_bfd, *parent, data,
                                        input_section,
                                        relocatable ? abfd : NULL,
                                        &error_message);
@@ -8867,8 +8877,7 @@ _bfd_elf_mips_get_relocated_section_contents
                case bfd_reloc_undefined:
                  if (!((*link_info->callbacks->undefined_symbol)
                        (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
-                        input_bfd, input_section, (*parent)->address,
-                        TRUE)))
+                        input_bfd, input_section, (*parent)->address, TRUE)))
                    goto error_return;
                  break;
                case bfd_reloc_dangerous:
@@ -9000,7 +9009,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                && !(*bed->elf_backend_omit_section_dynsym) (abfd, info, p))
              ++ dynsecsymcount;
        }
-      
+
       if (! mips_elf_sort_hash_table (info, dynsecsymcount + 1))
        return FALSE;
 
@@ -9660,11 +9669,26 @@ mips_mach_extends_p (unsigned long base, unsigned long extension)
 {
   size_t i;
 
-  for (i = 0; extension != base && i < ARRAY_SIZE (mips_mach_extensions); i++)
+  if (extension == base)
+    return TRUE;
+
+  if (base == bfd_mach_mipsisa32
+      && mips_mach_extends_p (bfd_mach_mipsisa64, extension))
+    return TRUE;
+
+  if (base == bfd_mach_mipsisa32r2
+      && mips_mach_extends_p (bfd_mach_mipsisa64r2, extension))
+    return TRUE;
+
+  for (i = 0; i < ARRAY_SIZE (mips_mach_extensions); i++)
     if (extension == mips_mach_extensions[i].extension)
-      extension = mips_mach_extensions[i].base;
+      {
+       extension = mips_mach_extensions[i].base;
+       if (extension == base)
+         return TRUE;
+      }
 
-  return extension == base;
+  return FALSE;
 }
 
 
@@ -9969,7 +9993,7 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
   return TRUE;
 }
 
-struct bfd_elf_special_section const _bfd_mips_elf_special_sections[] =
+const struct bfd_elf_special_section _bfd_mips_elf_special_sections[] =
 {
   { ".lit4",   5,  0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
   { ".lit8",   5,  0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE + SHF_MIPS_GPREL },
@@ -9980,20 +10004,23 @@ struct bfd_elf_special_section const _bfd_mips_elf_special_sections[] =
   { NULL,      0,  0, 0,              0 }
 };
 
-const struct bfd_elf_special_section *
-_bfd_mips_elf_get_sec_type_attr (bfd *abfd, asection *sec)
-{
-  const struct bfd_elf_special_section const *ssect;
-
-  /* See if this is one of the special sections.  */
-  if (sec->name == NULL)
-    return NULL;
-
-  ssect = _bfd_elf_get_special_section (sec->name,
-                                       _bfd_mips_elf_special_sections,
-                                       sec->use_rela_p);
-  if (ssect != NULL)
-    return ssect;
+/* Ensure that the STO_OPTIONAL flag is copied into h->other,
+   even if this is not a defintion of the symbol.  */
+void
+_bfd_mips_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
+                                     const Elf_Internal_Sym *isym,
+                                     bfd_boolean definition,
+                                     bfd_boolean dynamic ATTRIBUTE_UNUSED)
+{
+  if (! definition
+      && ELF_MIPS_IS_OPTIONAL (isym->st_other))
+    h->other |= STO_OPTIONAL;
+}
 
-  return _bfd_elf_get_sec_type_attr (abfd, sec);
+/* Decide whether an undefined symbol is special and can be ignored.
+   This is the case for OPTIONAL symbols on IRIX.  */
+bfd_boolean
+_bfd_mips_elf_ignore_undef_symbol (struct elf_link_hash_entry *h)
+{
+  return ELF_MIPS_IS_OPTIONAL (h->other) ? TRUE : FALSE;
 }
This page took 0.028298 seconds and 4 git commands to generate.