2000-11-14 Kazu Hirata <kazu@hxi.com>
[deliverable/binutils-gdb.git] / bfd / elf64-alpha.c
index a21d1b9f32c03568cd213a756c63030b7b4f4f0f..73620eb9b586dd97cbfaa9e77ab00a5986bf9584 100644 (file)
@@ -125,6 +125,10 @@ static boolean elf64_alpha_finish_dynamic_sections
   PARAMS((bfd *, struct bfd_link_info *));
 static boolean elf64_alpha_final_link
   PARAMS((bfd *, struct bfd_link_info *));
+static boolean elf64_alpha_merge_ind_symbols
+  PARAMS((struct alpha_elf_link_hash_entry *, PTR));
+static Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs
+  PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int));
 
 \f
 struct alpha_elf_link_hash_entry
@@ -1123,12 +1127,13 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
 
   /* A little preparation for the loop... */
   disp = symval - info->gp;
-  fits16 = (disp >= -(bfd_signed_vma)0x8000 && disp < 0x8000);
-  fits32 = (disp >= -(bfd_signed_vma)0x80000000 && disp < 0x7fff8000);
 
   for (urel = irel+1, i = 0; i < count; ++i, ++urel)
     {
       unsigned int insn;
+      int insn_disp;
+      bfd_signed_vma xdisp;
+
       insn = bfd_get_32 (info->abfd, info->contents + urel->r_offset);
 
       switch (urel->r_addend)
@@ -1141,14 +1146,23 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
 
        case 1: /* MEM FORMAT */
          /* We can always optimize 16-bit displacements.  */
+
+         /* Extract the displacement from the instruction, sign-extending
+            it if necessary, then test whether it is within 16 or 32 bits
+            displacement from GP.  */
+         insn_disp = insn & 0x0000ffff;
+         if (insn_disp & 0x00008000)
+           insn_disp |= 0xffff0000;  /* Negative: sign-extend.  */
+
+         xdisp = disp + insn_disp;
+         fits16 = (xdisp >= - (bfd_signed_vma) 0x00008000 && xdisp < 0x00008000);
+         fits32 = (xdisp >= - (bfd_signed_vma) 0x80000000 && xdisp < 0x7fff8000);
+
          if (fits16)
            {
-             /* FIXME: sanity check the insn for mem format with
-                zero addend.  */
-
-             /* Take the op code and dest from this insn, take the base 
-                register from the literal insn.  Leave the offset alone.  */
-             insn = (insn & 0xffe00000) | (lit_insn & 0x001f0000);
+             /* Take the op code and dest from this insn, take the base
+                register from the literal insn.  Leave the offset alone. */
+             insn = (insn & 0xffe0ffff) | (lit_insn & 0x001f0000);
              urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
                                           R_ALPHA_GPRELLOW);
              urel->r_addend = irel->r_addend;
@@ -1161,8 +1175,7 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
          /* If all mem+byte, we can optimize 32-bit mem displacements.  */
          else if (fits32 && !(flags & ~6))
            {
-             /* FIXME: sanity check that lit insn Ra is mem insn Rb, and
-                that mem_insn disp is zero.  */
+             /* FIXME: sanity check that lit insn Ra is mem insn Rb.  */
 
              irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
                                           R_ALPHA_GPRELHIGH);
@@ -2577,9 +2590,10 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
              else
                rent->count++;
            }
-         else if (info->shared)
+         else if (info->shared && (sec->flags & SEC_ALLOC))
            {
-             /* If this is a shared library, we need a RELATIVE reloc.  */
+             /* If this is a shared library, and the section is to be
+                loaded into memory, we need a RELATIVE reloc.  */
              sreloc->_raw_size += sizeof (Elf64_External_Rela);
            }
          break;
@@ -3307,6 +3321,7 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
        {
          if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
            return false;
+         info->flags |= DF_TEXTREL;
        }
     }
 
@@ -3470,13 +3485,17 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.root.type == bfd_link_hash_undefweak)
            relocation = 0;
-         else if (info->shared && !info->symbolic && !info->no_undefined)
+         else if (info->shared && !info->symbolic
+                  && !info->no_undefined
+                  && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
            relocation = 0;
          else
            {
              if (!((*info->callbacks->undefined_symbol)
                    (info, h->root.root.root.string, input_bfd,
-                    input_section, rel->r_offset)))
+                    input_section, rel->r_offset,
+                    (!info->shared || info->no_undefined
+                     || ELF_ST_VISIBILITY (h->root.other)))))
                return false;
              relocation = 0;
            }
@@ -3618,7 +3637,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                outrel.r_addend = addend;
                addend = 0, relocation = 0;
              }
-           else if (info->shared)
+           else if (info->shared && (input_section->flags & SEC_ALLOC))
              {
                outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
                outrel.r_addend = 0;
@@ -4634,6 +4653,36 @@ elf64_alpha_ecoff_debug_swap =
   elf64_alpha_read_ecoff_info
 };
 \f
+/* Use a non-standard hash bucket size of 8.  */
+
+const struct elf_size_info alpha_elf_size_info =
+{
+  sizeof (Elf64_External_Ehdr),
+  sizeof (Elf64_External_Phdr),
+  sizeof (Elf64_External_Shdr),
+  sizeof (Elf64_External_Rel),
+  sizeof (Elf64_External_Rela),
+  sizeof (Elf64_External_Sym),
+  sizeof (Elf64_External_Dyn),
+  sizeof (Elf_External_Note),
+  8,
+  1,
+  64, 8,
+  ELFCLASS64, EV_CURRENT,
+  bfd_elf64_write_out_phdrs,
+  bfd_elf64_write_shdrs_and_ehdr,
+  bfd_elf64_write_relocs,
+  bfd_elf64_swap_symbol_out,
+  bfd_elf64_slurp_reloc_table,
+  bfd_elf64_slurp_symbol_table,
+  bfd_elf64_swap_dyn_in,
+  bfd_elf64_swap_dyn_out,
+  NULL,
+  NULL,
+  NULL,
+  NULL
+};
+
 #define TARGET_LITTLE_SYM      bfd_elf64_alpha_vec
 #define TARGET_LITTLE_NAME     "elf64-alpha"
 #define ELF_ARCH               bfd_arch_alpha
@@ -4689,6 +4738,9 @@ elf64_alpha_ecoff_debug_swap =
 #define elf_backend_ecoff_debug_swap \
   &elf64_alpha_ecoff_debug_swap
 
+#define elf_backend_size_info \
+  alpha_elf_size_info
+
 /*
  * A few constants that determine how the .plt section is set up.
  */
This page took 0.030809 seconds and 4 git commands to generate.