* elf.c (prep_headers): Get the machine code from the elf
[deliverable/binutils-gdb.git] / bfd / elf64-alpha.c
index 085d09beff845804c8284a313d48b0c00e565fcc..2836fd50b5852aacf3adb3f72873ef3fbef95119 100644 (file)
@@ -74,6 +74,8 @@ static boolean elf64_alpha_object_p
   PARAMS((bfd *));
 static boolean elf64_alpha_section_from_shdr
   PARAMS((bfd *, Elf64_Internal_Shdr *, char *));
+static boolean elf64_alpha_section_flags
+  PARAMS((flagword *, Elf64_Internal_Shdr *));
 static boolean elf64_alpha_fake_sections
   PARAMS((bfd *, Elf64_Internal_Shdr *, asection *));
 static boolean elf64_alpha_create_got_section
@@ -399,6 +401,9 @@ elf64_alpha_object_p (abfd)
    from smaller values.  Start with zero, widen, *then* decrement.  */
 #define MINUS_ONE      (((bfd_vma)0) - 1)
 
+#define SKIP_HOWTO(N) \
+  HOWTO(N, 0, 0, 0, 0, 0, 0, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
+
 static reloc_howto_type elf64_alpha_howto_table[] =
 {
   HOWTO (R_ALPHA_NONE,         /* type */
@@ -465,7 +470,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
   /* Used for an instruction that refers to memory off the GP register.  */
   HOWTO (R_ALPHA_LITERAL,      /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -486,7 +491,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
      This does not actually do any relocation.  */
   HOWTO (R_ALPHA_LITUSE,       /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -546,7 +551,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
   /* A hint for a jump to a register.  */
   HOWTO (R_ALPHA_HINT,         /* type */
         2,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
         14,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
@@ -603,99 +608,22 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         MINUS_ONE,             /* dst_mask */
         true),                 /* pcrel_offset */
 
-  /* Push a value on the reloc evaluation stack.  */
-  /* Not implemented -- it's dumb.  */
-  HOWTO (R_ALPHA_OP_PUSH,      /* type */
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "OP_PUSH",             /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
-
-  /* Store the value from the stack at the given address.  Store it in
-     a bitfield of size r_size starting at bit position r_offset.  */
-  /* Not implemented -- it's dumb.  */
-  HOWTO (R_ALPHA_OP_STORE,     /* type */
-        0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
-        64,                    /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "OP_STORE",            /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        MINUS_ONE,             /* dst_mask */
-        false),                /* pcrel_offset */
-
-  /* Subtract the reloc address from the value on the top of the
-     relocation stack.  */
-  /* Not implemented -- it's dumb.  */
-  HOWTO (R_ALPHA_OP_PSUB,      /* type */
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "OP_PSUB",             /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
-
-  /* Shift the value on the top of the relocation stack right by the
-     given value.  */
-  /* Not implemented -- it's dumb.  */
-  HOWTO (R_ALPHA_OP_PRSHIFT,   /* type */
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "OP_PRSHIFT",          /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
-
-  /* Change the value of GP used by +r_addend until the next GPVALUE or the
-     end of the input bfd.  */
-  /* Not implemented -- it's dumb.  */
-  HOWTO (R_ALPHA_GPVALUE,
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "GPVALUE",             /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
+  /* Skip 12 - 16; deprecated ECOFF relocs.  */
+  SKIP_HOWTO (12),
+  SKIP_HOWTO (13),
+  SKIP_HOWTO (14),
+  SKIP_HOWTO (15),
+  SKIP_HOWTO (16),
 
   /* The high 16 bits of the displacement from GP to the target.  */
   HOWTO (R_ALPHA_GPRELHIGH,
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
+        0,                     /* special_function */
         "GPRELHIGH",           /* name */
         false,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -705,12 +633,12 @@ static reloc_howto_type elf64_alpha_howto_table[] =
   /* The low 16 bits of the displacement from GP to the target.  */
   HOWTO (R_ALPHA_GPRELLOW,
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
+        0,                     /* special_function */
         "GPRELLOW",            /* name */
         false,                 /* partial_inplace */
         0xffff,                /* src_mask */
@@ -718,89 +646,25 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         false),                /* pcrel_offset */
 
   /* A 16-bit displacement from the GP to the target.  */
-  /* XXX: Not implemented.  */
-  HOWTO (R_ALPHA_IMMED_GP_16,
+  HOWTO (R_ALPHA_GPREL16,
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         0,                     /* special_function */
-        "IMMED_GP_16",         /* name */
+        "GPREL16",             /* name */
         false,                 /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* The high bits of a 32-bit displacement from the GP to the target; the
-     low bits are supplied in the subsequent R_ALPHA_IMMED_LO32 relocs.  */
-  /* XXX: Not implemented.  */
-  HOWTO (R_ALPHA_IMMED_GP_HI32,
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "IMMED_GP_HI32",               /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
-
-  /* The high bits of a 32-bit displacement to the starting address of the
-     current section (the relocation target is ignored); the low bits are
-     supplied in the subsequent R_ALPHA_IMMED_LO32 relocs.  */
-  /* XXX: Not implemented.  */
-  HOWTO (R_ALPHA_IMMED_SCN_HI32,
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "IMMED_SCN_HI32",              /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
-
-  /* The high bits of a 32-bit displacement from the previous br, bsr, jsr
-     or jmp insn (as tagged by a BRADDR or HINT reloc) to the target; the
-     low bits are supplied by subsequent R_ALPHA_IMMED_LO32 relocs.  */
-  /* XXX: Not implemented.  */
-  HOWTO (R_ALPHA_IMMED_BR_HI32,
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "IMMED_BR_HI32",               /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
-
-  /* The low 16 bits of a displacement calculated in a previous HI32 reloc.  */
-  /* XXX: Not implemented.  */
-  HOWTO (R_ALPHA_IMMED_LO32,
-        0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
-        0,                     /* bitsize */
-        false,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-        elf64_alpha_reloc_bad, /* special_function */
-        "IMMED_LO32",          /* name */
-        false,                 /* partial_inplace */
-        0,                     /* src_mask */
-        0,                     /* dst_mask */
-        false),                /* pcrel_offset */
+  /* Skip 20 - 23; deprecated ECOFF relocs.  */
+  SKIP_HOWTO (20),
+  SKIP_HOWTO (21),
+  SKIP_HOWTO (22),
+  SKIP_HOWTO (23),
 
   /* Misc ELF relocations.  */
 
@@ -1003,30 +867,22 @@ struct elf_reloc_map
 
 static const struct elf_reloc_map elf64_alpha_reloc_map[] =
 {
-  {BFD_RELOC_NONE,             R_ALPHA_NONE},
-  {BFD_RELOC_32,               R_ALPHA_REFLONG},
-  {BFD_RELOC_64,               R_ALPHA_REFQUAD},
-  {BFD_RELOC_CTOR,             R_ALPHA_REFQUAD},
-  {BFD_RELOC_GPREL32,          R_ALPHA_GPREL32},
-  {BFD_RELOC_ALPHA_ELF_LITERAL,        R_ALPHA_LITERAL},
-  {BFD_RELOC_ALPHA_LITUSE,     R_ALPHA_LITUSE},
-  {BFD_RELOC_ALPHA_GPDISP,     R_ALPHA_GPDISP},
-  {BFD_RELOC_23_PCREL_S2,      R_ALPHA_BRADDR},
-  {BFD_RELOC_ALPHA_HINT,       R_ALPHA_HINT},
-  {BFD_RELOC_16_PCREL,         R_ALPHA_SREL16},
-  {BFD_RELOC_32_PCREL,         R_ALPHA_SREL32},
-  {BFD_RELOC_64_PCREL,         R_ALPHA_SREL64},
-
-/* The BFD_RELOC_ALPHA_USER_* relocations are used by the assembler to process
-   the explicit !<reloc>!sequence relocations, and are mapped into the normal
-   relocations at the end of processing.  */
-  {BFD_RELOC_ALPHA_USER_LITERAL,       R_ALPHA_LITERAL},
-  {BFD_RELOC_ALPHA_USER_LITUSE_BASE,   R_ALPHA_LITUSE},
-  {BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF, R_ALPHA_LITUSE},
-  {BFD_RELOC_ALPHA_USER_LITUSE_JSR,    R_ALPHA_LITUSE},
-  {BFD_RELOC_ALPHA_USER_GPDISP,                R_ALPHA_GPDISP},
-  {BFD_RELOC_ALPHA_USER_GPRELHIGH,     R_ALPHA_GPRELHIGH},
-  {BFD_RELOC_ALPHA_USER_GPRELLOW,      R_ALPHA_GPRELLOW},
+  {BFD_RELOC_NONE,                     R_ALPHA_NONE},
+  {BFD_RELOC_32,                       R_ALPHA_REFLONG},
+  {BFD_RELOC_64,                       R_ALPHA_REFQUAD},
+  {BFD_RELOC_CTOR,                     R_ALPHA_REFQUAD},
+  {BFD_RELOC_GPREL32,                  R_ALPHA_GPREL32},
+  {BFD_RELOC_ALPHA_ELF_LITERAL,                R_ALPHA_LITERAL},
+  {BFD_RELOC_ALPHA_LITUSE,             R_ALPHA_LITUSE},
+  {BFD_RELOC_ALPHA_GPDISP,             R_ALPHA_GPDISP},
+  {BFD_RELOC_23_PCREL_S2,              R_ALPHA_BRADDR},
+  {BFD_RELOC_ALPHA_HINT,               R_ALPHA_HINT},
+  {BFD_RELOC_16_PCREL,                 R_ALPHA_SREL16},
+  {BFD_RELOC_32_PCREL,                 R_ALPHA_SREL32},
+  {BFD_RELOC_64_PCREL,                 R_ALPHA_SREL64},
+  {BFD_RELOC_ALPHA_GPREL_HI16,         R_ALPHA_GPRELHIGH},
+  {BFD_RELOC_ALPHA_GPREL_LO16,         R_ALPHA_GPRELLOW},
+  {BFD_RELOC_GPREL16,                  R_ALPHA_GPREL16},
 };
 
 /* Given a BFD reloc type, return a HOWTO structure.  */
@@ -1205,7 +1061,7 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
                 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);
+                                          R_ALPHA_GPREL16);
              urel->r_addend = irel->r_addend;
              info->changed_relocs = true;
 
@@ -1295,14 +1151,36 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
            else
              all_optimized = false;
 
-           /* ??? If target gp == current gp we can eliminate the gp reload.
-              This does depend on every place a gp could be reloaded will
-              be, which currently happens for all code produced by gcc, but
-              not necessarily by hand-coded assembly, or if sibling calls
-              are enabled in gcc.
-
-              Perhaps conditionalize this on a flag being set in the target
-              object file's header, and have gcc set it?  */
+           /* Even if the target is not in range for a direct branch,
+              if we share a GP, we can eliminate the gp reload.  */
+           if (optdest)
+             {
+               Elf_Internal_Rela *gpdisp
+                 = (elf64_alpha_find_reloc_at_ofs
+                    (irel, irelend, urel->r_offset + 4, R_ALPHA_GPDISP));
+               if (gpdisp)
+                 {
+                   bfd_byte *p_ldah = info->contents + gpdisp->r_offset; 
+                   bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
+                   unsigned int ldah = bfd_get_32 (info->abfd, p_ldah);
+                   unsigned int lda = bfd_get_32 (info->abfd, p_lda);
+
+                   /* Verify that the instruction is "ldah $29,0($26)".
+                      Consider a function that ends in a noreturn call,
+                      and that the next function begins with an ldgp,
+                      and that by accident there is no padding between.
+                      In that case the insn would use $27 as the base.  */
+                   if (ldah == 0x27ba0000 && lda == 0x23bd0000)
+                     {
+                       bfd_put_32 (info->abfd, INSN_UNOP, p_ldah);
+                       bfd_put_32 (info->abfd, INSN_UNOP, p_lda);
+
+                       gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
+                       info->changed_contents = true;
+                       info->changed_relocs = true;
+                     }
+                 }
+             }
          }
          break;
        }
@@ -1442,7 +1320,7 @@ elf64_alpha_relax_without_lituse (info, symval, irel)
   bfd_put_32 (info->abfd, insn, info->contents + irel->r_offset);
   info->changed_contents = true;
 
-  irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPRELLOW);
+  irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPREL16);
   info->changed_relocs = true;
 
   /* Reduce the use count on this got entry by one, possibly
@@ -1746,13 +1624,6 @@ elf64_alpha_section_from_shdr (abfd, hdr, name)
       if (strcmp (name, ".mdebug") != 0)
        return false;
       break;
-#ifdef ERIC_neverdef
-    case SHT_ALPHA_REGINFO:
-      if (strcmp (name, ".reginfo") != 0
-         || hdr->sh_size != sizeof (Elf64_External_RegInfo))
-       return false;
-      break;
-#endif
     default:
       return false;
     }
@@ -1769,22 +1640,18 @@ elf64_alpha_section_from_shdr (abfd, hdr, name)
        return false;
     }
 
-#ifdef ERIC_neverdef
-  /* For a .reginfo section, set the gp value in the tdata information
-     from the contents of this section.  We need the gp value while
-     processing relocs, so we just get it now.  */
-  if (hdr->sh_type == SHT_ALPHA_REGINFO)
-    {
-      Elf64_External_RegInfo ext;
-      Elf64_RegInfo s;
+  return true;
+}
 
-      if (! bfd_get_section_contents (abfd, newsect, (PTR) &ext,
-                                     (file_ptr) 0, sizeof ext))
-       return false;
-      bfd_alpha_elf64_swap_reginfo_in (abfd, &ext, &s);
-      elf_gp (abfd) = s.ri_gp_value;
-    }
-#endif
+/* Convert Alpha specific section flags to bfd internal section flags.  */
+
+static boolean
+elf64_alpha_section_flags (flags, hdr)
+     flagword *flags;
+     Elf64_Internal_Shdr *hdr;
+{
+  if (hdr->sh_flags & SHF_ALPHA_GPREL)
+    *flags |= SEC_SMALL_DATA;
 
   return true;
 }
@@ -1812,31 +1679,8 @@ elf64_alpha_fake_sections (abfd, hdr, sec)
       else
        hdr->sh_entsize = 1;
     }
-#ifdef ERIC_neverdef
-  else if (strcmp (name, ".reginfo") == 0)
-    {
-      hdr->sh_type = SHT_ALPHA_REGINFO;
-      /* In a shared object on Irix 5.3, the .reginfo section has an
-         entsize of 0x18.  FIXME: Does this matter?  */
-      if ((abfd->flags & DYNAMIC) != 0)
-       hdr->sh_entsize = sizeof (Elf64_External_RegInfo);
-      else
-       hdr->sh_entsize = 1;
-
-      /* Force the section size to the correct value, even if the
-        linker thinks it is larger.  The link routine below will only
-        write out this much data for .reginfo.  */
-      hdr->sh_size = sec->_raw_size = sizeof (Elf64_External_RegInfo);
-    }
-  else if (strcmp (name, ".hash") == 0
-          || strcmp (name, ".dynamic") == 0
-          || strcmp (name, ".dynstr") == 0)
-    {
-      hdr->sh_entsize = 0;
-      hdr->sh_info = SIZEOF_ALPHA_DYNSYM_SECNAMES;
-    }
-#endif
-  else if (strcmp (name, ".sdata") == 0
+  else if ((sec->flags & SEC_SMALL_DATA)
+          || strcmp (name, ".sdata") == 0
           || strcmp (name, ".sbss") == 0
           || strcmp (name, ".lit4") == 0
           || strcmp (name, ".lit8") == 0)
@@ -2340,9 +2184,6 @@ elf64_alpha_output_extsym (h, data)
          else
            h->esym.asym.value = 0;
        }
-#if 0 /* FIXME?  */
-      h->esym.ifd = 0;
-#endif
     }
 
   if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
@@ -2539,6 +2380,7 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
          /* FALLTHRU */
 
        case R_ALPHA_GPDISP:
+       case R_ALPHA_GPREL16:
        case R_ALPHA_GPREL32:
        case R_ALPHA_GPRELHIGH:
        case R_ALPHA_GPRELLOW:
@@ -3386,6 +3228,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
   asection *sec, *sgot, *srel, *srelgot;
   bfd *dynobj, *gotobj;
   bfd_vma gp;
+  boolean ret_val = true;
 
   srelgot = srel = NULL;
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -3487,33 +3330,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
            {
              sec = h->root.root.u.def.section;
 
-#if rth_notdef
-             if ((r_type == R_ALPHA_LITERAL
-                  && elf_hash_table(info)->dynamic_sections_created
-                  && (!info->shared
-                      || !info->symbolic
-                      || !(h->root.elf_link_hash_flags
-                           & ELF_LINK_HASH_DEF_REGULAR)))
-                 || (info->shared
-                     && (!info->symbolic
-                         || !(h->root.elf_link_hash_flags
-                              & ELF_LINK_HASH_DEF_REGULAR))
-                     && (input_section->flags & SEC_ALLOC)
-                     && (r_type == R_ALPHA_REFLONG
-                         || r_type == R_ALPHA_REFQUAD
-                         || r_type == R_ALPHA_LITERAL)))
-               {
-                 /* In these cases, we don't need the relocation value.
-                    We check specially because in some obscure cases
-                    sec->output_section will be NULL.  */
-                 relocation = 0;
-               }
-#else
-             /* FIXME: Are not these obscure cases simply bugs?  Let's
-                get something working and come back to this.  */
              if (sec->output_section == NULL)
                relocation = 0;
-#endif /* rth_notdef */
              else
                {
                  relocation = (h->root.root.u.def.value
@@ -3534,7 +3352,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                     input_section, rel->r_offset,
                     (!info->shared || info->no_undefined
                      || ELF_ST_VISIBILITY (h->root.other)))))
-               return false;
+               ret_val = false;
              relocation = 0;
            }
        }
@@ -3560,13 +3378,6 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          }
          break;
 
-       case R_ALPHA_OP_PUSH:
-       case R_ALPHA_OP_STORE:
-       case R_ALPHA_OP_PSUB:
-       case R_ALPHA_OP_PRSHIFT:
-         /* We hate these silly beasts.  */
-         abort ();
-
        case R_ALPHA_LITERAL:
          {
            struct alpha_elf_got_entry *gotent;
@@ -3637,13 +3448,28 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
          /* overflow handled by _bfd_final_link_relocate */
          goto default_reloc;
 
+       case R_ALPHA_GPREL16:
        case R_ALPHA_GPREL32:
        case R_ALPHA_GPRELLOW:
+         if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
+            {
+              (*_bfd_error_handler)
+                (_("%s: gp-relative relocation against dynamic symbol %s"),
+                 bfd_get_filename (input_bfd), h->root.root.root.string);
+              ret_val = false;
+            }
          BFD_ASSERT(gp != 0);
          relocation -= gp;
          goto default_reloc;
 
        case R_ALPHA_GPRELHIGH:
+         if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
+            {
+              (*_bfd_error_handler)
+                (_("%s: gp-relative relocation against dynamic symbol %s"),
+                 bfd_get_filename (input_bfd), h->root.root.root.string);
+              ret_val = false;
+            }
          BFD_ASSERT(gp != 0);
          relocation -= gp;
          relocation += addend;
@@ -3652,8 +3478,17 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                        + ((relocation >> 15) & 1));
          goto default_reloc;
 
-       case R_ALPHA_BRADDR:
        case R_ALPHA_HINT:
+         /* A call to a dynamic symbol is definitely out of range of
+            the 16-bit displacement.  Don't bother writing anything.  */
+         if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
+           {
+             r = bfd_reloc_ok;
+             break;
+           }
+         /* FALLTHRU */
+
+       case R_ALPHA_BRADDR:
          /* The regular PC-relative stuff measures from the start of
             the instruction rather than the end.  */
          addend -= 4;
@@ -3760,7 +3595,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
            if (! ((*info->callbacks->reloc_overflow)
                   (info, name, howto->name, (bfd_vma) 0,
                    input_bfd, input_section, rel->r_offset)))
-             return false;
+             ret_val = false;
          }
          break;
 
@@ -3770,7 +3605,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
        }
     }
 
-  return true;
+  return ret_val;
 }
 
 /* Finish up dynamic symbol handling.  We set the contents of various
@@ -4016,9 +3851,9 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info)
   return true;
 }
 
-/* We need to use a special link routine to handle the .reginfo and
-   the .mdebug sections.  We need to merge all instances of these
-   sections together, not write them all out sequentially.  */
+/* We need to use a special link routine to handle the .mdebug section.
+   We need to merge all instances of these sections together, not write
+   them all out sequentially.  */
 
 static boolean
 elf64_alpha_final_link (abfd, info)
@@ -4027,96 +3862,17 @@ elf64_alpha_final_link (abfd, info)
 {
   asection *o;
   struct bfd_link_order *p;
-  asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
+  asection *mdebug_sec;
   struct ecoff_debug_info debug;
   const struct ecoff_debug_swap *swap
     = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
   HDRR *symhdr = &debug.symbolic_header;
   PTR mdebug_handle = NULL;
 
-#if 0
-             if (++ngots == 2)
-               {
-                 (*info->callbacks->warning)
-                   (info, _("using multiple gp values"), (char *) NULL,
-                    output_bfd, (asection *) NULL, (bfd_vma) 0);
-               }
-#endif
-
-  /* Go through the sections and collect the .reginfo and .mdebug
-     information.  */
-  reginfo_sec = NULL;
+  /* Go through the sections and collect the mdebug information.  */
   mdebug_sec = NULL;
-  gptab_data_sec = NULL;
-  gptab_bss_sec = NULL;
   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
     {
-#ifdef ERIC_neverdef
-      if (strcmp (o->name, ".reginfo") == 0)
-       {
-         memset (&reginfo, 0, sizeof reginfo);
-
-         /* We have found the .reginfo section in the output file.
-            Look through all the link_orders comprising it and merge
-            the information together.  */
-         for (p = o->link_order_head;
-              p != (struct bfd_link_order *) NULL;
-              p = p->next)
-           {
-             asection *input_section;
-             bfd *input_bfd;
-             Elf64_External_RegInfo ext;
-             Elf64_RegInfo sub;
-
-             if (p->type != bfd_indirect_link_order)
-               {
-                 if (p->type == bfd_fill_link_order)
-                   continue;
-                 abort ();
-               }
-
-             input_section = p->u.indirect.section;
-             input_bfd = input_section->owner;
-
-             /* The linker emulation code has probably clobbered the
-                 size to be zero bytes.  */
-             if (input_section->_raw_size == 0)
-               input_section->_raw_size = sizeof (Elf64_External_RegInfo);
-
-             if (! bfd_get_section_contents (input_bfd, input_section,
-                                             (PTR) &ext,
-                                             (file_ptr) 0,
-                                             sizeof ext))
-               return false;
-
-             bfd_alpha_elf64_swap_reginfo_in (input_bfd, &ext, &sub);
-
-             reginfo.ri_gprmask |= sub.ri_gprmask;
-             reginfo.ri_cprmask[0] |= sub.ri_cprmask[0];
-             reginfo.ri_cprmask[1] |= sub.ri_cprmask[1];
-             reginfo.ri_cprmask[2] |= sub.ri_cprmask[2];
-             reginfo.ri_cprmask[3] |= sub.ri_cprmask[3];
-
-             /* ri_gp_value is set by the function
-                alpha_elf_section_processing when the section is
-                finally written out.  */
-
-             /* Hack: reset the SEC_HAS_CONTENTS flag so that
-                elf_link_input_bfd ignores this section.  */
-             input_section->flags &=~ SEC_HAS_CONTENTS;
-           }
-
-         /* Force the section size to the value we want.  */
-         o->_raw_size = sizeof (Elf64_External_RegInfo);
-
-         /* Skip this section later on (I don't think this currently
-            matters, but someday it might).  */
-         o->link_order_head = (struct bfd_link_order *) NULL;
-
-         reginfo_sec = o;
-       }
-#endif
-
       if (strcmp (o->name, ".mdebug") == 0)
        {
          struct extsym_info einfo;
@@ -4303,31 +4059,6 @@ elf64_alpha_final_link (abfd, info)
              input_section->flags &=~ SEC_HAS_CONTENTS;
            }
 
-#ifdef ERIC_neverdef
-         if (info->shared)
-           {
-             /* Create .rtproc section.  */
-             rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
-             if (rtproc_sec == NULL)
-               {
-                 flagword flags = (SEC_HAS_CONTENTS
-                                   | SEC_IN_MEMORY
-                                   | SEC_LINKER_CREATED
-                                   | SEC_READONLY);
-
-                 rtproc_sec = bfd_make_section (abfd, ".rtproc");
-                 if (rtproc_sec == NULL
-                     || ! bfd_set_section_flags (abfd, rtproc_sec, flags)
-                     || ! bfd_set_section_alignment (abfd, rtproc_sec, 12))
-                   return false;
-               }
-
-             if (! alpha_elf_create_procedure_table (mdebug_handle, abfd,
-                                                    info, rtproc_sec, &debug))
-               return false;
-           }
-#endif
-
          /* Build the external symbol information.  */
          einfo.abfd = abfd;
          einfo.info = info;
@@ -4349,229 +4080,6 @@ elf64_alpha_final_link (abfd, info)
 
          mdebug_sec = o;
        }
-
-#ifdef ERIC_neverdef
-      if (strncmp (o->name, ".gptab.", sizeof ".gptab." - 1) == 0)
-       {
-         const char *subname;
-         unsigned int c;
-         Elf64_gptab *tab;
-         Elf64_External_gptab *ext_tab;
-         unsigned int i;
-
-         /* The .gptab.sdata and .gptab.sbss sections hold
-            information describing how the small data area would
-            change depending upon the -G switch.  These sections
-            not used in executables files.  */
-         if (! info->relocateable)
-           {
-             asection **secpp;
-
-             for (p = o->link_order_head;
-                  p != (struct bfd_link_order *) NULL;
-                  p = p->next)
-               {
-                 asection *input_section;
-
-                 if (p->type != bfd_indirect_link_order)
-                   {
-                     if (p->type == bfd_fill_link_order)
-                       continue;
-                     abort ();
-                   }
-
-                 input_section = p->u.indirect.section;
-
-                 /* Hack: reset the SEC_HAS_CONTENTS flag so that
-                    elf_link_input_bfd ignores this section.  */
-                 input_section->flags &=~ SEC_HAS_CONTENTS;
-               }
-
-             /* Skip this section later on (I don't think this
-                currently matters, but someday it might).  */
-             o->link_order_head = (struct bfd_link_order *) NULL;
-
-             /* Really remove the section.  */
-             for (secpp = &abfd->sections;
-                  *secpp != o;
-                  secpp = &(*secpp)->next)
-               ;
-             *secpp = (*secpp)->next;
-             --abfd->section_count;
-
-             continue;
-           }
-
-         /* There is one gptab for initialized data, and one for
-            uninitialized data.  */
-         if (strcmp (o->name, ".gptab.sdata") == 0)
-           gptab_data_sec = o;
-         else if (strcmp (o->name, ".gptab.sbss") == 0)
-           gptab_bss_sec = o;
-         else
-           {
-             (*_bfd_error_handler)
-               (_("%s: illegal section name `%s'"),
-                bfd_get_filename (abfd), o->name);
-             bfd_set_error (bfd_error_nonrepresentable_section);
-             return false;
-           }
-
-         /* The linker script always combines .gptab.data and
-            .gptab.sdata into .gptab.sdata, and likewise for
-            .gptab.bss and .gptab.sbss.  It is possible that there is
-            no .sdata or .sbss section in the output file, in which
-            case we must change the name of the output section.  */
-         subname = o->name + sizeof ".gptab" - 1;
-         if (bfd_get_section_by_name (abfd, subname) == NULL)
-           {
-             if (o == gptab_data_sec)
-               o->name = ".gptab.data";
-             else
-               o->name = ".gptab.bss";
-             subname = o->name + sizeof ".gptab" - 1;
-             BFD_ASSERT (bfd_get_section_by_name (abfd, subname) != NULL);
-           }
-
-         /* Set up the first entry.  */
-         c = 1;
-         tab = (Elf64_gptab *) bfd_malloc (c * sizeof (Elf64_gptab));
-         if (tab == NULL)
-           return false;
-         tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
-         tab[0].gt_header.gt_unused = 0;
-
-         /* Combine the input sections.  */
-         for (p = o->link_order_head;
-              p != (struct bfd_link_order *) NULL;
-              p = p->next)
-           {
-             asection *input_section;
-             bfd *input_bfd;
-             bfd_size_type size;
-             unsigned long last;
-             bfd_size_type gpentry;
-
-             if (p->type != bfd_indirect_link_order)
-               {
-                 if (p->type == bfd_fill_link_order)
-                   continue;
-                 abort ();
-               }
-
-             input_section = p->u.indirect.section;
-             input_bfd = input_section->owner;
-
-             /* Combine the gptab entries for this input section one
-                by one.  We know that the input gptab entries are
-                sorted by ascending -G value.  */
-             size = bfd_section_size (input_bfd, input_section);
-             last = 0;
-             for (gpentry = sizeof (Elf64_External_gptab);
-                  gpentry < size;
-                  gpentry += sizeof (Elf64_External_gptab))
-               {
-                 Elf64_External_gptab ext_gptab;
-                 Elf64_gptab int_gptab;
-                 unsigned long val;
-                 unsigned long add;
-                 boolean exact;
-                 unsigned int look;
-
-                 if (! (bfd_get_section_contents
-                        (input_bfd, input_section, (PTR) &ext_gptab,
-                         gpentry, sizeof (Elf64_External_gptab))))
-                   {
-                     free (tab);
-                     return false;
-                   }
-
-                 bfd_alpha_elf64_swap_gptab_in (input_bfd, &ext_gptab,
-                                               &int_gptab);
-                 val = int_gptab.gt_entry.gt_g_value;
-                 add = int_gptab.gt_entry.gt_bytes - last;
-
-                 exact = false;
-                 for (look = 1; look < c; look++)
-                   {
-                     if (tab[look].gt_entry.gt_g_value >= val)
-                       tab[look].gt_entry.gt_bytes += add;
-
-                     if (tab[look].gt_entry.gt_g_value == val)
-                       exact = true;
-                   }
-
-                 if (! exact)
-                   {
-                     Elf64_gptab *new_tab;
-                     unsigned int max;
-
-                     /* We need a new table entry.  */
-                     new_tab = ((Elf64_gptab *)
-                                bfd_realloc ((PTR) tab,
-                                             (c + 1) * sizeof (Elf64_gptab)));
-                     if (new_tab == NULL)
-                       {
-                         free (tab);
-                         return false;
-                       }
-                     tab = new_tab;
-                     tab[c].gt_entry.gt_g_value = val;
-                     tab[c].gt_entry.gt_bytes = add;
-
-                     /* Merge in the size for the next smallest -G
-                        value, since that will be implied by this new
-                        value.  */
-                     max = 0;
-                     for (look = 1; look < c; look++)
-                       {
-                         if (tab[look].gt_entry.gt_g_value < val
-                             && (max == 0
-                                 || (tab[look].gt_entry.gt_g_value
-                                     > tab[max].gt_entry.gt_g_value)))
-                           max = look;
-                       }
-                     if (max != 0)
-                       tab[c].gt_entry.gt_bytes +=
-                         tab[max].gt_entry.gt_bytes;
-
-                     ++c;
-                   }
-
-                 last = int_gptab.gt_entry.gt_bytes;
-               }
-
-             /* Hack: reset the SEC_HAS_CONTENTS flag so that
-                elf_link_input_bfd ignores this section.  */
-             input_section->flags &=~ SEC_HAS_CONTENTS;
-           }
-
-         /* The table must be sorted by -G value.  */
-         if (c > 2)
-           qsort (tab + 1, c - 1, sizeof (tab[0]), gptab_compare);
-
-         /* Swap out the table.  */
-         ext_tab = ((Elf64_External_gptab *)
-                    bfd_alloc (abfd, c * sizeof (Elf64_External_gptab)));
-         if (ext_tab == NULL)
-           {
-             free (tab);
-             return false;
-           }
-
-         for (i = 0; i < c; i++)
-           bfd_alpha_elf64_swap_gptab_out (abfd, tab + i, ext_tab + i);
-         free (tab);
-
-         o->_raw_size = c * sizeof (Elf64_External_gptab);
-         o->contents = (bfd_byte *) ext_tab;
-
-         /* Skip this section later on (I don't think this currently
-            matters, but someday it might).  */
-         o->link_order_head = (struct bfd_link_order *) NULL;
-       }
-#endif
-
     }
 
   /* Invoke the regular ELF backend linker to do all the work.  */
@@ -4601,18 +4109,6 @@ elf64_alpha_final_link (abfd, info)
       }
   }
 
-#ifdef ERIC_neverdef
-  if (reginfo_sec != (asection *) NULL)
-    {
-      Elf64_External_RegInfo ext;
-
-      bfd_alpha_elf64_swap_reginfo_out (abfd, &reginfo, &ext);
-      if (! bfd_set_section_contents (abfd, reginfo_sec, (PTR) &ext,
-                                     (file_ptr) 0, sizeof ext))
-       return false;
-    }
-#endif
-
   if (mdebug_sec != (asection *) NULL)
     {
       BFD_ASSERT (abfd->output_has_begun);
@@ -4624,24 +4120,6 @@ elf64_alpha_final_link (abfd, info)
       bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
     }
 
-  if (gptab_data_sec != (asection *) NULL)
-    {
-      if (! bfd_set_section_contents (abfd, gptab_data_sec,
-                                     gptab_data_sec->contents,
-                                     (file_ptr) 0,
-                                     gptab_data_sec->_raw_size))
-       return false;
-    }
-
-  if (gptab_bss_sec != (asection *) NULL)
-    {
-      if (! bfd_set_section_contents (abfd, gptab_bss_sec,
-                                     gptab_bss_sec->contents,
-                                     (file_ptr) 0,
-                                     gptab_bss_sec->_raw_size))
-       return false;
-    }
-
   return true;
 }
 
@@ -4758,6 +4236,8 @@ const struct elf_size_info alpha_elf_size_info =
 
 #define elf_backend_section_from_shdr \
   elf64_alpha_section_from_shdr
+#define elf_backend_section_flags \
+  elf64_alpha_section_flags
 #define elf_backend_fake_sections \
   elf64_alpha_fake_sections
 
This page took 0.035246 seconds and 4 git commands to generate.