* elf32-sh.c (sh_elf_create_dynamic_sections): Return if dynamic
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
index 22c341684394fc29e8ca4a70bd28c7c5c203093e..2098f6fa9fa341eef68afb900f6005f8189bc4e1 100644 (file)
@@ -357,6 +357,10 @@ elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
       reloc->address += input_section->output_offset;
       return bfd_reloc_ok;
     }
+
+  if (input_section->flags & SEC_DEBUGGING)
+    return bfd_reloc_continue;
+
   *error_message = "Unsupported call to elfNN_ia64_reloc";
   return bfd_reloc_notsupported;
 }
@@ -656,31 +660,12 @@ static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] =
 #define DYNAMIC_INTERPRETER(abfd) \
   (elfNN_ia64_aix_vec (abfd->xvec) ? AIX_DYNAMIC_INTERPRETER : ELF_DYNAMIC_INTERPRETER)
 
-/* Select out of range branch fixup type.  Note that Itanium does
-   not support brl, and so it gets emulated by the kernel.  */
-#undef USE_BRL
-
-#ifdef USE_BRL
 static const bfd_byte oor_brl[16] =
 {
   0x05, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MLX]        nop.m 0            */
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /*               brl.sptk.few tgt;; */
   0x00, 0x00, 0x00, 0xc0
 };
-#else
-static const bfd_byte oor_ip[48] =
-{
-  0x04, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MLX]        nop.m 0            */
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,  /*               movl r15=0         */
-  0x01, 0x00, 0x00, 0x60,
-  0x03, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MII]        nop.m 0            */
-  0x00, 0x01, 0x00, 0x60, 0x00, 0x00,  /*               mov r16=ip;;       */
-  0xf2, 0x80, 0x00, 0x80,              /*               add r16=r15,r16;;  */
-  0x11, 0x00, 0x00, 0x00, 0x01, 0x00,  /*  [MIB]        nop.m 0            */
-  0x60, 0x80, 0x04, 0x80, 0x03, 0x00,  /*               mov b6=r16         */
-  0x60, 0x00, 0x80, 0x00               /*               br b6;;            */
-};
-#endif
 \f
 /* These functions do relaxation for IA-64 ELF.  */
 
@@ -715,9 +700,16 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
      one pass.  */
   *again = FALSE;
 
-  /* Nothing to do if there are no relocations.  */
+  /* Don't even try to relax for non-ELF outputs.  */
+  if (link_info->hash->creator->flavour != bfd_target_elf_flavour)
+    return FALSE;
+
+  /* Nothing to do if there are no relocations or there is no need for
+     the relax finalize pass.  */
   if ((sec->flags & SEC_RELOC) == 0
-      || sec->reloc_count == 0)
+      || sec->reloc_count == 0
+      || (link_info->relax_finalizing
+         && sec->need_finalize_relax == 0))
     return TRUE;
 
   /* If this is the first time we have been called for this section,
@@ -728,7 +720,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 
   /* Load the relocations for this section.  */
-  internal_relocs = (_bfd_elfNN_link_read_relocs
+  internal_relocs = (_bfd_elf_link_read_relocs
                     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
                      link_info->keep_memory));
   if (internal_relocs == NULL)
@@ -767,11 +759,18 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
        case R_IA64_PCREL21BI:
        case R_IA64_PCREL21M:
        case R_IA64_PCREL21F:
+         if (link_info->relax_finalizing)
+           continue;
          is_branch = TRUE;
          break;
 
        case R_IA64_LTOFF22X:
        case R_IA64_LDXMOV:
+         if (!link_info->relax_finalizing)
+           {
+             sec->need_finalize_relax = 1;
+             continue;
+           }
          is_branch = FALSE;
          break;
 
@@ -797,7 +796,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
                goto error_return;
            }
 
-         isym = isymbuf + ELF64_R_SYM (irel->r_info);
+         isym = isymbuf + ELFNN_R_SYM (irel->r_info);
          if (isym->st_shndx == SHN_UNDEF)
            continue;   /* We can't do anthing with undefined symbols.  */
          else if (isym->st_shndx == SHN_ABS)
@@ -838,6 +837,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
 
              tsec = ia64_info->plt_sec;
              toff = dyn_i->plt2_offset;
+             BFD_ASSERT (irel->r_addend == 0);
            }
 
          /* Can't do anything else with dynamic symbols.  */
@@ -856,10 +856,15 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
            }
        }
 
-      symaddr = (tsec->output_section->vma
-                + tsec->output_offset
-                + toff
-                + irel->r_addend);
+      if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
+       toff = _bfd_merged_section_offset (abfd, &tsec,
+                                          elf_section_data (tsec)->sec_info,
+                                          toff + irel->r_addend,
+                                          (bfd_vma) 0);
+      else
+       toff += irel->r_addend;
+
+      symaddr = tsec->output_section->vma + tsec->output_offset + toff;
 
       roff = irel->r_offset;
 
@@ -897,11 +902,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
                size = sizeof (plt_full_entry);
              else
                {
-#ifdef USE_BRL
                  size = sizeof (oor_brl);
-#else
-                 size = sizeof (oor_ip);
-#endif
                }
 
              /* Resize the current section to make room for the new branch. */
@@ -923,18 +924,10 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
                }
              else
                {
-#ifdef USE_BRL
                  memcpy (contents + trampoff, oor_brl, size);
                  irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
                                               R_IA64_PCREL60B);
                  irel->r_offset = trampoff + 2;
-#else
-                 memcpy (contents + trampoff, oor_ip, size);
-                 irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
-                                              R_IA64_PCREL64I);
-                 irel->r_addend -= 16;
-                 irel->r_offset = trampoff + 2;
-#endif
                }
 
              /* Record the fixup so we don't do it again this section.  */
@@ -978,8 +971,8 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
            }
 
          /* If the data is out of range, do nothing.  */
-         if ((bfd_signed_vma) (symaddr - gp) >= 0x400000
-             ||(bfd_signed_vma) (symaddr - gp) < -0x400000)
+         if ((bfd_signed_vma) (symaddr - gp) >= 0x200000
+             ||(bfd_signed_vma) (symaddr - gp) < -0x200000)
            continue;
 
          if (r_type == R_IA64_LTOFF22X)
@@ -1053,6 +1046,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
       struct elfNN_ia64_allocate_data data;
       data.info = link_info;
       data.ofs = 0;
+      ia64_info->self_dtpmod_offset = (bfd_vma) -1;
 
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
       elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
@@ -1063,6 +1057,9 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
       /* ??? Resize .rela.got too.  */
     }
 
+  if (link_info->relax_finalizing)
+    sec->need_finalize_relax = 0;
+
   *again = changed_contents || changed_relocs;
   return TRUE;
 
@@ -1092,7 +1089,7 @@ elfNN_ia64_relax_ldxmov (abfd, contents, off)
     case 0: shift =  5; break;
     case 1: shift = 14; off += 3; break;
     case 2: shift = 23; off += 6; break;
-    case 3:
+    default:
       abort ();
     }
 
@@ -1344,7 +1341,7 @@ elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd_vma *valp;
 {
   if (sym->st_shndx == SHN_COMMON
-      && !info->relocateable
+      && !info->relocatable
       && sym->st_size <= elf_gp_size (abfd))
     {
       /* Common symbols less than or equal to -G nn bytes are
@@ -1469,7 +1466,7 @@ elfNN_ia64_aix_link_add_symbols (abfd, info)
   if (! elf_hash_table (info)->dynamic_sections_created
       && abfd->xvec == info->hash->creator)
     {
-      if (! bfd_elfNN_link_create_dynamic_sections (abfd, info))
+      if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
        return FALSE;
     }
 
@@ -1795,7 +1792,10 @@ elfNN_ia64_hash_hide_symbol (info, xh, force_local)
   _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
 
   for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next)
-    dyn_i->want_plt2 = 0;
+    {
+      dyn_i->want_plt2 = 0;
+      dyn_i->want_plt = 0;
+    }
 }
 
 /* Create the derived linker hash table.  The IA-64 ELF port uses this
@@ -1808,19 +1808,24 @@ elfNN_ia64_hash_table_create (abfd)
 {
   struct elfNN_ia64_link_hash_table *ret;
 
-  ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret));
+  ret = bfd_zmalloc ((bfd_size_type) sizeof (*ret));
   if (!ret)
     return 0;
+
   if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
                                      elfNN_ia64_new_elf_hash_entry))
     {
-      bfd_release (abfd, ret);
+      free (ret);
       return 0;
     }
 
   if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd,
                                         elfNN_ia64_new_loc_hash_entry))
-    return 0;
+    {
+      free (ret);
+      return 0;
+    }
+
   return &ret->root.root;
 }
 
@@ -1996,7 +2001,11 @@ get_dyn_sym_info (ia64_info, h, abfd, rel, create)
       struct elfNN_ia64_local_hash_entry *loc_h;
 
       loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
-      BFD_ASSERT (loc_h);
+      if (!loc_h)
+       {
+         BFD_ASSERT (!create);
+         return NULL;
+       }
 
       pp = &loc_h->info;
     }
@@ -2219,7 +2228,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
   const Elf_Internal_Rela *rel;
   asection *got, *fptr, *srel;
 
-  if (info->relocateable)
+  if (info->relocatable)
     return TRUE;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -2629,7 +2638,10 @@ allocate_fptr (dyn_i, data)
               || h->root.type == bfd_link_hash_warning)
          h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-      if (x->info->shared
+      if ((x->info->shared
+          && (!h
+              || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+              || h->root.type != bfd_link_hash_undefweak))
          /* AIX needs an FPTR in this case. */
          || (elfNN_ia64_aix_vec (x->info->hash->creator)
              && (!h
@@ -2754,15 +2766,18 @@ allocate_dynrel_entries (dyn_i, data)
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
   struct elfNN_ia64_link_hash_table *ia64_info;
   struct elfNN_ia64_dyn_reloc_entry *rent;
-  bfd_boolean dynamic_symbol, shared;
+  bfd_boolean dynamic_symbol, shared, resolved_zero;
 
   ia64_info = elfNN_ia64_hash_table (x->info);
   dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
     || (elfNN_ia64_aix_vec (x->info->hash->creator)
        /* Don't allocate an entry for __GLOB_DATA_PTR */
        && (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
-         "__GLOB_DATA_PTR") != 0));
+                                "__GLOB_DATA_PTR") != 0));
   shared = x->info->shared;
+  resolved_zero = (dyn_i->h
+                  && ELF_ST_VISIBILITY (dyn_i->h->other)
+                  && dyn_i->h->root.type == bfd_link_hash_undefweak);
 
   /* Take care of the normal data relocations.  */
 
@@ -2807,8 +2822,12 @@ allocate_dynrel_entries (dyn_i, data)
 
   /* Take care of the GOT and PLT relocations.  */
 
-  if (((dynamic_symbol || shared) && (dyn_i->want_got || dyn_i->want_gotx))
-      || (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1))
+  if ((!resolved_zero
+       && (dynamic_symbol || shared)
+       && (dyn_i->want_got || dyn_i->want_gotx))
+      || (dyn_i->want_ltoff_fptr
+         && dyn_i->h
+         && dyn_i->h->dynindx != -1))
     ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
   if ((dynamic_symbol || shared) && dyn_i->want_tprel)
     ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
@@ -2817,7 +2836,7 @@ allocate_dynrel_entries (dyn_i, data)
   if (dynamic_symbol && dyn_i->want_dtprel)
     ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
 
-  if (dyn_i->want_pltoff)
+  if (!resolved_zero && dyn_i->want_pltoff)
     {
       bfd_size_type t = 0;
 
@@ -2884,7 +2903,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
 
   /* Set the contents of the .interp section to the interpreter.  */
   if (ia64_info->root.dynamic_sections_created
-      && !info->shared)
+      && info->executable)
     {
       sec = bfd_get_section_by_name (dynobj, ".interp");
       BFD_ASSERT (sec != NULL);
@@ -3059,7 +3078,7 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
         later (in finish_dynamic_sections) but we must add the entries now
         so that we get the correct size for the .dynamic section.  */
 
-      if (!info->shared)
+      if (info->executable)
        {
          /* The DT_DEBUG entry is filled in by the dynamic linker and used
             by the debugger.  */
@@ -3425,7 +3444,11 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
       bfd_put_64 (abfd, value, got_sec->contents + got_offset);
 
       /* Install a dynamic relocation if needed.  */
-      if ((info->shared && dyn_r_type != R_IA64_DTPREL64LSB)
+      if ((info->shared
+          && (!dyn_i->h
+              || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+              || dyn_i->h->root.type != bfd_link_hash_undefweak)
+          && dyn_r_type != R_IA64_DTPREL64LSB)
           || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
          || elfNN_ia64_aix_vec (abfd->xvec)
          || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
@@ -3546,7 +3569,11 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
       bfd_put_64 (abfd, gp, pltoff_sec->contents + dyn_i->pltoff_offset + 8);
 
       /* Install dynamic relocations if needed.  */
-      if (!is_plt && info->shared)
+      if (!is_plt
+         && info->shared
+         && (!dyn_i->h
+             || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+             || dyn_i->h->root.type != bfd_link_hash_undefweak))
        {
          unsigned int dyn_r_type;
 
@@ -3752,7 +3779,7 @@ elfNN_ia64_final_link (abfd, info)
   ia64_info = elfNN_ia64_hash_table (info);
 
   /* Make sure we've got ourselves a nice fat __gp value.  */
-  if (!info->relocateable)
+  if (!info->relocatable)
     {
       bfd_vma gp_val = _bfd_get_gp_value (abfd);
       struct elf_link_hash_entry *gp;
@@ -3778,7 +3805,7 @@ elfNN_ia64_final_link (abfd, info)
      of the .IA_64.unwind section.  Force this section to be relocated
      into memory rather than written immediately to the output file.  */
   unwind_output_sec = NULL;
-  if (!info->relocateable)
+  if (!info->relocatable)
     {
       asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
       if (s)
@@ -3836,7 +3863,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
   ia64_info = elfNN_ia64_hash_table (info);
 
   /* Infect various flags from the input section to the output section.  */
-  if (info->relocateable)
+  if (info->relocatable)
     {
       bfd_vma flags;
 
@@ -3866,6 +3893,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
       asection *sym_sec;
       bfd_byte *hit_addr;
       bfd_boolean dynamic_symbol_p;
+      bfd_boolean local_symbol_p;
       bfd_boolean undef_weak_ref;
 
       r_type = ELFNN_R_TYPE (rel->r_info);
@@ -3970,7 +3998,6 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                      (!info->shared || info->no_undefined
                       || ELF_ST_VISIBILITY (h->other)))))
                return FALSE;
-             ret_val = FALSE;
              continue;
            }
        }
@@ -3978,6 +4005,11 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
       hit_addr = contents + rel->r_offset;
       value += rel->r_addend;
       dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info);
+      /* Is this symbol locally defined? A protected symbol is locallly
+        defined. But its function descriptor may not. Use it with
+        caution.  */
+      local_symbol_p = (! dynamic_symbol_p
+                       || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT);
 
       switch (r_type)
        {
@@ -4010,7 +4042,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
              /* If we don't need dynamic symbol lookup, find a
                 matching RELATIVE relocation.  */
              dyn_r_type = r_type;
-             if (dynamic_symbol_p)
+             if (! local_symbol_p)
                {
                  dynindx = h->dynindx;
                  addend = rel->r_addend;
@@ -4293,7 +4325,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                {
                  int i;
                  for (i = m->count - 1; i >= 0; i--)
-                   if (m->sections[i] == sym_sec->output_section)
+                   if (m->sections[i] == input_section->output_section)
                      break;
                  if (i >= 0)
                    break;
@@ -4339,7 +4371,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 
              /* If we don't need dynamic symbol lookup, install two
                 RELATIVE relocations.  */
-             if (! dynamic_symbol_p)
+             if (local_symbol_p)
                {
                  unsigned int dyn_r_type;
 
This page took 0.029135 seconds and 4 git commands to generate.