Add support to GDB for the Renesas rl78 architecture.
[external/binutils.git] / bfd / elf64-alpha.c
index 2b15a81..94ea685 100644 (file)
@@ -1448,7 +1448,8 @@ elf64_alpha_find_nearest_line (bfd *abfd, asection *section, asymbol **symbols,
 {
   asection *msec;
 
-  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
+                                     section, symbols, offset,
                                     filename_ptr, functionname_ptr,
                                     line_ptr, 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info))
@@ -1553,9 +1554,6 @@ elf64_alpha_output_extsym (struct alpha_elf_link_hash_entry *h, PTR data)
   bfd_boolean strip;
   asection *sec, *output_section;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   if (h->root.indx == -2)
     strip = FALSE;
   else if ((h->root.def_dynamic
@@ -1885,10 +1883,13 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
          break;
 
        case R_ALPHA_TPREL64:
-         if (info->shared || maybe_dynamic)
+         if (info->shared && !info->pie)
+           {
+             info->flags |= DF_STATIC_TLS;
+             need = NEED_DYNREL;
+           }
+         else if (maybe_dynamic)
            need = NEED_DYNREL;
-         if (info->shared)
-           info->flags |= DF_STATIC_TLS;
          break;
        }
 
@@ -2151,23 +2152,29 @@ elf64_alpha_merge_symbol_attribute (struct elf_link_hash_entry *h,
    indirect to the new ones.  Consolidate the got and reloc information
    in these situations.  */
 
-static bfd_boolean
-elf64_alpha_merge_ind_symbols (struct alpha_elf_link_hash_entry *hi,
-                              PTR dummy ATTRIBUTE_UNUSED)
+static void
+elf64_alpha_copy_indirect_symbol (struct bfd_link_info *info,
+                                 struct elf_link_hash_entry *dir,
+                                 struct elf_link_hash_entry *ind)
 {
-  struct alpha_elf_link_hash_entry *hs;
+  struct alpha_elf_link_hash_entry *hi
+    = (struct alpha_elf_link_hash_entry *) ind;
+  struct alpha_elf_link_hash_entry *hs
+    = (struct alpha_elf_link_hash_entry *) dir;
 
-  if (hi->root.root.type != bfd_link_hash_indirect)
-    return TRUE;
-  hs = hi;
-  do {
-    hs = (struct alpha_elf_link_hash_entry *)hs->root.root.u.i.link;
-  } while (hs->root.root.type == bfd_link_hash_indirect);
+  /* Do the merging in the superclass.  */
+  _bfd_elf_link_hash_copy_indirect(info, dir, ind);
 
   /* Merge the flags.  Whee.  */
-
   hs->flags |= hi->flags;
 
+  /* ??? It's unclear to me what's really supposed to happen when
+     "merging" defweak and defined symbols, given that we don't
+     actually throw away the defweak.  This more-or-less copies
+     the logic related to got and plt entries in the superclass.  */
+  if (ind->root.type != bfd_link_hash_indirect)
+    return;
+
   /* Merge the .got entries.  Cannibalize the old symbol's list in
      doing so, since we don't need it anymore.  */
 
@@ -2220,8 +2227,6 @@ elf64_alpha_merge_ind_symbols (struct alpha_elf_link_hash_entry *hi,
        }
     }
   hi->reloc_entries = NULL;
-
-  return TRUE;
 }
 
 /* Is it possible to merge two object file's .got tables?  */
@@ -2390,9 +2395,6 @@ elf64_alpha_calc_got_offsets_for_symbol (struct alpha_elf_link_hash_entry *h,
 {
   struct alpha_elf_got_entry *gotent;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   for (gotent = h->got_entries; gotent; gotent = gotent->next)
     if (gotent->use_count > 0)
       {
@@ -2631,10 +2633,6 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (htab == NULL)
     return FALSE;
 
-  /* First, take care of the indirect symbols created by versioning.  */
-  alpha_elf_link_hash_traverse (htab, elf64_alpha_merge_ind_symbols,
-                               NULL);
-
   if (!elf64_alpha_size_got_sections (info))
     return FALSE;
 
@@ -2657,7 +2655,7 @@ elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 /* The number of dynamic relocations required by a static relocation.  */
 
 static int
-alpha_dynamic_entries_for_reloc (int r_type, int dynamic, int shared)
+alpha_dynamic_entries_for_reloc (int r_type, int dynamic, int shared, int pie)
 {
   switch (r_type)
     {
@@ -2667,16 +2665,18 @@ alpha_dynamic_entries_for_reloc (int r_type, int dynamic, int shared)
     case R_ALPHA_TLSLDM:
       return shared;
     case R_ALPHA_LITERAL:
-    case R_ALPHA_GOTTPREL:
       return dynamic || shared;
+    case R_ALPHA_GOTTPREL:
+      return dynamic || (shared && !pie);
     case R_ALPHA_GOTDTPREL:
       return dynamic;
 
     /* May appear in data sections.  */
     case R_ALPHA_REFLONG:
     case R_ALPHA_REFQUAD:
-    case R_ALPHA_TPREL64:
       return dynamic || shared;
+    case R_ALPHA_TPREL64:
+      return dynamic || (shared && !pie);
 
     /* Everything else is illegal.  We'll issue an error during
        relocate_section.  */
@@ -2695,9 +2695,6 @@ elf64_alpha_calc_dynrel_sizes (struct alpha_elf_link_hash_entry *h,
   struct alpha_elf_reloc_entry *relent;
   unsigned long entries;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   /* If the symbol was defined as a common symbol in a regular object
      file, and there was no definition in any dynamic object, then the
      linker will have allocated space for the symbol in a common
@@ -2727,7 +2724,7 @@ elf64_alpha_calc_dynrel_sizes (struct alpha_elf_link_hash_entry *h,
   for (relent = h->reloc_entries; relent; relent = relent->next)
     {
       entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
-                                                info->shared);
+                                                info->shared, info->pie);
       if (entries)
        {
          relent->srel->size +=
@@ -2751,9 +2748,6 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
   struct alpha_elf_got_entry *gotent;
   unsigned long entries;
 
-  if (h->root.root.type == bfd_link_hash_warning)
-    h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
-
   /* If we're using a plt for this symbol, then all of its relocations
      for its got entries go into .rela.plt.  */
   if (h->root.needs_plt)
@@ -2773,8 +2767,8 @@ elf64_alpha_size_rela_got_1 (struct alpha_elf_link_hash_entry *h,
   entries = 0;
   for (gotent = h->got_entries; gotent ; gotent = gotent->next)
     if (gotent->use_count > 0)
-      entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type,
-                                                 dynamic, info->shared);
+      entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type, dynamic,
+                                                 info->shared, info->pie);
 
   if (entries > 0)
     {
@@ -2824,7 +2818,7 @@ elf64_alpha_size_rela_got_section (struct bfd_link_info *info)
                 gotent ; gotent = gotent->next)
              if (gotent->use_count > 0)
                entries += (alpha_dynamic_entries_for_reloc
-                           (gotent->reloc_type, 0, info->shared));
+                           (gotent->reloc_type, 0, info->shared, info->pie));
        }
     }
 
@@ -2927,7 +2921,8 @@ elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
             linker does that before adjust_dynamic_symbol is called, and
             it is that function which decides whether anything needs to
             go into these sections.  */
-         s->flags |= SEC_EXCLUDE;
+         if (!CONST_STRNEQ (name, ".got"))
+           s->flags |= SEC_EXCLUDE;
        }
       else if ((s->flags & SEC_HAS_CONTENTS) != 0)
        {
@@ -3055,7 +3050,8 @@ elf64_alpha_relax_got_load (struct alpha_relax_info *info, bfd_vma symval,
     return TRUE;
 
   /* Can't use local-exec relocations in shared libraries.  */
-  if (r_type == R_ALPHA_GOTTPREL && info->link_info->shared)
+  if (r_type == R_ALPHA_GOTTPREL
+      && (info->link_info->shared && !info->link_info->pie))
     return TRUE;
 
   if (r_type == R_ALPHA_LITERAL)
@@ -3513,6 +3509,13 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
   pos[3] = info->contents + gpdisp->r_offset;
   pos[4] = pos[3] + gpdisp->r_addend;
 
+  /* Beware of the compiler hoisting part of the sequence out a loop
+     and adjusting the destination register for the TLSGD insn.  If this
+     happens, there will be a move into $16 before the JSR insn, so only
+     transformations of the first insn pair should use this register.  */
+  tlsgd_reg = bfd_get_32 (info->abfd, pos[0]);
+  tlsgd_reg = (tlsgd_reg >> 21) & 31;
+
   /* Generally, the positions are not allowed to be out of order, lest the
      modified insn sequence have different register lifetimes.  We can make
      an exception when pos 1 is adjacent to pos 0.  */
@@ -3580,13 +3583,6 @@ elf64_alpha_relax_tls_get_addr (struct alpha_relax_info *info, bfd_vma symval,
   use_gottprel = FALSE;
   new_symndx = is_gd ? ELF64_R_SYM (irel->r_info) : STN_UNDEF;
 
-  /* Beware of the compiler hoisting part of the sequence out a loop
-     and adjusting the destination register for the TLSGD insn.  If this
-     happens, there will be a move into $16 before the JSR insn, so only
-     transformations of the first insn pair should use this register.  */
-  tlsgd_reg = bfd_get_32 (info->abfd, pos[0]);
-  tlsgd_reg = (tlsgd_reg >> 21) & 31;
-
   switch (!dynamic && !info->link_info->shared)
     {
     case 1:
@@ -4217,6 +4213,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       bfd_vma value;
       bfd_vma addend;
       bfd_boolean dynamic_symbol_p;
+      bfd_boolean unresolved_reloc = FALSE;
       bfd_boolean undef_weak_ref = FALSE;
       unsigned long r_type;
 
@@ -4298,7 +4295,6 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       else
        {
          bfd_boolean warned;
-         bfd_boolean unresolved_reloc;
          struct elf_link_hash_entry *hh;
          struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
 
@@ -4520,7 +4516,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            else if (r_type == R_ALPHA_TPREL64)
              {
                BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
-               if (!info->shared)
+               if (!info->shared || info->pie)
                  {
                    value -= tp_base;
                    goto default_reloc;
@@ -4531,7 +4527,12 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
            else if (info->shared
                     && r_symndx != STN_UNDEF
                     && (input_section->flags & SEC_ALLOC)
-                    && !undef_weak_ref)
+                    && !undef_weak_ref
+                    && !(unresolved_reloc
+                         && (_bfd_elf_section_offset (output_bfd, info,
+                                                      input_section,
+                                                      rel->r_offset)
+                             == (bfd_vma) -1)))
              {
                if (r_type == R_ALPHA_REFLONG)
                  {
@@ -4577,7 +4578,11 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          /* ??? .eh_frame references to discarded sections will be smashed
             to relocations against SHN_UNDEF.  The .eh_frame format allows
             NULL to be encoded as 0 in any format, so this works here.  */
-         if (r_symndx == STN_UNDEF)
+         if (r_symndx == STN_UNDEF
+             || (unresolved_reloc
+                 && _bfd_elf_section_offset (output_bfd, info,
+                                             input_section,
+                                             rel->r_offset) == (bfd_vma) -1))
            howto = (elf64_alpha_howto_table
                     + (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG));
          goto default_reloc;
@@ -4641,7 +4646,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
        case R_ALPHA_TPRELHI:
        case R_ALPHA_TPRELLO:
        case R_ALPHA_TPREL16:
-         if (info->shared)
+         if (info->shared && !info->pie)
            {
              (*_bfd_error_handler)
                (_("%B: TLS local exec code cannot be linked into shared objects"),
@@ -5454,6 +5459,8 @@ static const struct elf_size_info alpha_elf_size_info =
   elf64_alpha_adjust_dynamic_symbol
 #define elf_backend_merge_symbol_attribute \
   elf64_alpha_merge_symbol_attribute
+#define elf_backend_copy_indirect_symbol \
+  elf64_alpha_copy_indirect_symbol
 #define elf_backend_always_size_sections \
   elf64_alpha_always_size_sections
 #define elf_backend_size_dynamic_sections \