* elf32-i386.c (elf_i386_grok_prstatus): New function.
[deliverable/binutils-gdb.git] / bfd / elf64-alpha.c
index 2a0cdb57962deab4cd6666dd686135e92e6bf91a..0dc4d4c7fcbbf893273b89a1795dddbcdcba9826 100644 (file)
@@ -1,5 +1,6 @@
 /* Alpha specific support for 64-bit ELF
-   Copyright 1996, 97, 98, 1999 Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -34,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define NO_COFF_SYMBOLS
 #define NO_COFF_LINENOS
 
-/* Get the ECOFF swapping routines.  Needed for the debug information. */
+/* Get the ECOFF swapping routines.  Needed for the debug information.  */
 #include "coff/internal.h"
 #include "coff/sym.h"
 #include "coff/symconst.h"
@@ -46,7 +47,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define ECOFF_64
 #include "ecoffswap.h"
 
-static boolean elf64_alpha_mkobject PARAMS ((bfd *));
+static int alpha_elf_dynamic_symbol_p
+  PARAMS((struct elf_link_hash_entry *, struct bfd_link_info *));
 static struct bfd_hash_entry * elf64_alpha_link_hash_newfunc
   PARAMS((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
 static struct bfd_link_hash_table * elf64_alpha_bfd_link_hash_table_create
@@ -66,6 +68,8 @@ static reloc_howto_type * elf64_alpha_bfd_reloc_type_lookup
 static void elf64_alpha_info_to_howto
   PARAMS((bfd *, arelent *, Elf64_Internal_Rela *));
 
+static boolean elf64_alpha_mkobject
+  PARAMS((bfd *));
 static boolean elf64_alpha_object_p
   PARAMS((bfd *));
 static boolean elf64_alpha_section_from_shdr
@@ -125,7 +129,12 @@ 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));
+static enum elf_reloc_type_class elf64_alpha_reloc_type_class
+  PARAMS ((int));
 \f
 struct alpha_elf_link_hash_entry
 {
@@ -152,7 +161,7 @@ struct alpha_elf_link_hash_entry
     bfd *gotobj;
 
     /* the addend in effect for this entry.  */
-    bfd_vma addend;
+    bfd_signed_vma addend;
 
     /* the .got offset for this entry.  */
     int got_offset;
@@ -175,7 +184,10 @@ struct alpha_elf_link_hash_entry
     asection *srel;
 
     /* what kind of relocation? */
-    unsigned long rtype;
+    unsigned int rtype;
+
+    /* is this against read-only section? */
+    unsigned int reltext : 1;
 
     /* how many did we find?  */
     unsigned long count;
@@ -220,14 +232,46 @@ struct alpha_elf_link_hash_table
 
 /* Should we do dynamic things to this symbol?  */
 
-#define alpha_elf_dynamic_symbol_p(h, info)                            \
-  ((((info)->shared && !(info)->symbolic)                              \
-    || (((h)->elf_link_hash_flags                                      \
-        & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))     \
-        == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))    \
-    || (h)->root.type == bfd_link_hash_undefweak                       \
-    || (h)->root.type == bfd_link_hash_defweak)                                \
-   && (h)->dynindx != -1)
+static int
+alpha_elf_dynamic_symbol_p (h, info)
+     struct elf_link_hash_entry *h;
+     struct bfd_link_info *info;
+{
+  if (h == NULL)
+    return false;
+
+  while (h->root.type == bfd_link_hash_indirect
+        || h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (h->dynindx == -1)
+    return false;
+
+  if (h->root.type == bfd_link_hash_undefweak
+      || h->root.type == bfd_link_hash_defweak)
+    return true;
+
+  switch (ELF_ST_VISIBILITY (h->other))
+    {
+    case STV_DEFAULT:
+      break;
+    case STV_HIDDEN:
+    case STV_INTERNAL:
+      return false;
+    case STV_PROTECTED:
+      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+        return false;
+      break;
+    }
+
+  if ((info->shared && !info->symbolic)
+      || ((h->elf_link_hash_flags
+          & (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR))
+         == (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
+    return true;
+
+  return false;
+}
 
 /* Create an entry in a Alpha ELF linker hash table.  */
 
@@ -527,7 +571,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         false,                 /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        false),                /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   /* 32 bit PC relative offset.  */
   HOWTO (R_ALPHA_SREL32,       /* type */
@@ -542,7 +586,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         false,                 /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        false),                /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   /* A 64 bit PC relative offset.  */
   HOWTO (R_ALPHA_SREL64,       /* type */
@@ -557,7 +601,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         false,                 /* partial_inplace */
         MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
-        false),                /* pcrel_offset */
+        true),                 /* pcrel_offset */
 
   /* Push a value on the reloc evaluation stack.  */
   /* Not implemented -- it's dumb.  */
@@ -707,7 +751,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         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 
+     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,
@@ -758,7 +802,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
         0,                     /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* Misc ELF relocations. */
+  /* Misc ELF relocations.  */
 
   /* A dynamic relocation to copy the target into our .dynbss section.  */
   /* Not generated, as all Alpha objects use PIC, so it is not needed.  It
@@ -828,13 +872,13 @@ static reloc_howto_type elf64_alpha_howto_table[] =
 
 static bfd_reloc_status_type
 elf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      arelent *reloc;
-     asymbol *sym;
-     PTR data;
+     asymbol *sym ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
      asection *sec;
      bfd *output_bfd;
-     char **error_message;
+     char **error_message ATTRIBUTE_UNUSED;
 {
   if (output_bfd)
     reloc->address += sec->output_offset;
@@ -845,13 +889,13 @@ elf64_alpha_reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
 
 static bfd_reloc_status_type
 elf64_alpha_reloc_bad (abfd, reloc, sym, data, sec, output_bfd, error_message)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      arelent *reloc;
-     asymbol *sym;
-     PTR data;
+     asymbol *sym ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
      asection *sec;
      bfd *output_bfd;
-     char **error_message;
+     char **error_message ATTRIBUTE_UNUSED;
 {
   if (output_bfd)
     reloc->address += sec->output_offset;
@@ -908,7 +952,7 @@ elf64_alpha_reloc_gpdisp (abfd, reloc_entry, sym, data, input_section,
                          output_bfd, err_msg)
      bfd *abfd;
      arelent *reloc_entry;
-     asymbol *sym;
+     asymbol *sym ATTRIBUTE_UNUSED;
      PTR data;
      asection *input_section;
      bfd *output_bfd;
@@ -972,13 +1016,24 @@ static const struct elf_reloc_map elf64_alpha_reloc_map[] =
   {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},
 };
 
 /* Given a BFD reloc type, return a HOWTO structure.  */
 
 static reloc_howto_type *
 elf64_alpha_bfd_reloc_type_lookup (abfd, code)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      bfd_reloc_code_real_type code;
 {
   const struct elf_reloc_map *i, *e;
@@ -996,7 +1051,7 @@ elf64_alpha_bfd_reloc_type_lookup (abfd, code)
 
 static void
 elf64_alpha_info_to_howto (abfd, cache_ptr, dst)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      arelent *cache_ptr;
      Elf64_Internal_Rela *dst;
 {
@@ -1007,7 +1062,7 @@ elf64_alpha_info_to_howto (abfd, cache_ptr, dst)
   cache_ptr->howto = &elf64_alpha_howto_table[r_type];
 }
 \f
-/* These functions do relaxation for Alpha ELF. 
+/* These functions do relaxation for Alpha ELF.
 
    Currently I'm only handling what I can do with existing compiler
    and assembler support, which means no instructions are removed,
@@ -1047,11 +1102,11 @@ struct alpha_relax_info
 };
 
 static Elf_Internal_Rela * elf64_alpha_relax_with_lituse
-  PARAMS((struct alpha_relax_info *info, bfd_vma symval, 
+  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
           Elf_Internal_Rela *irel, Elf_Internal_Rela *irelend));
 
 static boolean elf64_alpha_relax_without_lituse
-  PARAMS((struct alpha_relax_info *info, bfd_vma symval, 
+  PARAMS((struct alpha_relax_info *info, bfd_vma symval,
           Elf_Internal_Rela *irel));
 
 static bfd_vma elf64_alpha_relax_opt_call
@@ -1069,7 +1124,8 @@ elf64_alpha_find_reloc_at_ofs (rel, relend, offset, type)
 {
   while (rel < relend)
     {
-      if (rel->r_offset == offset && ELF64_R_TYPE (rel->r_info) == type)
+      if (rel->r_offset == offset
+         && ELF64_R_TYPE (rel->r_info) == (unsigned int) type)
        return rel;
       ++rel;
     }
@@ -1110,14 +1166,15 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
        flags |= 1 << urel->r_addend;
     }
 
-  /* A little preparation for the loop... */
+  /* 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)
@@ -1130,14 +1187,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 
+             /* 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);
+             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;
@@ -1150,8 +1216,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);
@@ -1200,12 +1265,12 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
              {
                Elf_Internal_Rela *xrel;
 
-               /* Preserve branch prediction call stack when possible. */
+               /* Preserve branch prediction call stack when possible.  */
                if ((insn & INSN_JSR_MASK) == INSN_JSR)
                  insn = (OP_BSR << 26) | (insn & 0x03e00000);
                else
                  insn = (OP_BR << 26) | (insn & 0x03e00000);
-                 
+
                urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
                                             R_ALPHA_BRADDR);
                urel->r_addend = irel->r_addend;
@@ -1219,7 +1284,7 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
 
                /* Kill any HINT reloc that might exist for this insn.  */
                xrel = (elf64_alpha_find_reloc_at_ofs
-                       (info->relocs, info->relend, urel->r_offset, 
+                       (info->relocs, info->relend, urel->r_offset,
                         R_ALPHA_HINT));
                if (xrel)
                  xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
@@ -1234,7 +1299,7 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
               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. 
+              are enabled in gcc.
 
               Perhaps conditionalize this on a flag being set in the target
               object file's header, and have gcc set it?  */
@@ -1280,22 +1345,22 @@ elf64_alpha_relax_opt_call (info, symval)
 
   /* If the symbol is marked NOPV, we are being told the function never
      needs its procedure value.  */
-  if (info->other == STO_ALPHA_NOPV)
+  if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
     return symval;
 
   /* If the symbol is marked STD_GP, we are being told the function does
-     a normal ldgp in the first two words.  */ 
-  else if (info->other == STO_ALPHA_STD_GPLOAD)
+     a normal ldgp in the first two words.  */
+  else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD)
     ;
 
   /* Otherwise, we may be able to identify a GP load in the first two
      words, which we can then skip.  */
-  else 
+  else
     {
       Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
       bfd_vma ofs;
 
-      /* Load the relocations from the section that the target symbol is in. */
+      /* Load the relocations from the section that the target symbol is in.  */
       if (info->sec == info->tsec)
        {
          tsec_relocs = info->relocs;
@@ -1317,7 +1382,7 @@ elf64_alpha_relax_opt_call (info, symval)
       /* Recover the symbol's offset within the section.  */
       ofs = (symval - info->tsec->output_section->vma
             - info->tsec->output_offset);
-  
+
       /* Look for a GPDISP reloc.  */
       gpdisp = (elf64_alpha_find_reloc_at_ofs
                (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
@@ -1332,7 +1397,7 @@ elf64_alpha_relax_opt_call (info, symval)
         free (tsec_free);
     }
 
-  /* We've now determined that we can skip an initial gp load.  Verify 
+  /* We've now determined that we can skip an initial gp load.  Verify
      that the call and the target use the same gp.   */
   if (info->link_info->hash->creator != info->tsec->owner->xvec
       || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
@@ -1393,7 +1458,7 @@ elf64_alpha_relax_without_lituse (info, symval, irel)
 
      Any such memory load insn may be substituted by a load directly
      off the GP.  This allows the memory load insn to be issued before
-     the calculated GP register would otherwise be ready. 
+     the calculated GP register would otherwise be ready.
 
      Any such jsr insn can be replaced by a bsr if it is in range.
 
@@ -1445,7 +1510,7 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
   if (! link_info->keep_memory)
     free_relocs = internal_relocs;
 
-  memset(&info, 0, sizeof(info));
+  memset(&info, 0, sizeof (info));
   info.abfd = abfd;
   info.sec = sec;
   info.link_info = link_info;
@@ -1528,8 +1593,8 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
            info.tsec = bfd_abs_section_ptr;
          else if (isym.st_shndx == SHN_COMMON)
            info.tsec = bfd_com_section_ptr;
-         else 
-           continue;   /* who knows. */
+         else
+           continue;   /* who knows.  */
 
          info.h = NULL;
          info.other = isym.st_other;
@@ -1556,7 +1621,6 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
            continue;
 
          info.h = h;
-         info.gotent = gotent;
          info.tsec = h->root.root.u.def.section;
          info.other = h->root.other;
          gotent = h->got_entries;
@@ -1789,14 +1853,14 @@ elf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
      bfd *abfd;
      struct bfd_link_info *info;
      const Elf_Internal_Sym *sym;
-     const char **namep;
-     flagword *flagsp;
+     const char **namep ATTRIBUTE_UNUSED;
+     flagword *flagsp ATTRIBUTE_UNUSED;
      asection **secp;
      bfd_vma *valp;
 {
   if (sym->st_shndx == SHN_COMMON
       && !info->relocateable
-      && sym->st_size <= bfd_get_gp_size (abfd))
+      && sym->st_size <= elf_gp_size (abfd))
     {
       /* Common symbols less than or equal to -G nn bytes are
         automatically put into .sbss.  */
@@ -1825,7 +1889,7 @@ elf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
 static boolean
 elf64_alpha_create_got_section(abfd, info)
      bfd *abfd;
-     struct bfd_link_info *info;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
 {
   asection *s;
 
@@ -1947,7 +2011,7 @@ elf64_alpha_read_ecoff_info (abfd, section, debug)
   char *ext_hdr = NULL;
 
   swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
-  memset (debug, 0, sizeof(*debug));
+  memset (debug, 0, sizeof (*debug));
 
   ext_hdr = (char *) bfd_malloc ((size_t) swap->external_hdr_size);
   if (ext_hdr == NULL && swap->external_hdr_size != 0)
@@ -2028,7 +2092,7 @@ elf64_alpha_read_ecoff_info (abfd, section, debug)
 
 static boolean
 elf64_alpha_is_local_label_name (abfd, name)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      const char *name;
 {
   return name[0] == '$';
@@ -2058,6 +2122,12 @@ elf64_alpha_find_nearest_line (abfd, section, symbols, offset, filename_ptr,
 {
   asection *msec;
 
+  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+                                    filename_ptr, functionname_ptr,
+                                    line_ptr, 0,
+                                    &elf_tdata (abfd)->dwarf2_find_line_info))
+    return true;
+
   msec = bfd_get_section_by_name (abfd, ".mdebug");
   if (msec != NULL)
     {
@@ -2524,7 +2594,10 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
                  sreloc = bfd_make_section (dynobj, rel_sec_name);
                  if (sreloc == NULL
                      || !bfd_set_section_flags (dynobj, sreloc,
-                                                (SEC_ALLOC|SEC_LOAD
+                                                (((sec->flags
+                                                   & SEC_ALLOC)
+                                                  ? (SEC_ALLOC
+                                                     | SEC_LOAD) : 0)
                                                  | SEC_HAS_CONTENTS
                                                  | SEC_IN_MEMORY
                                                  | SEC_LINKER_CREATED
@@ -2540,7 +2613,7 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
                 don't know whether we'll actually need a dynamic relocation
                 entry for this reloc.  So make a record of it.  Once we
                 find out if this thing needs dynamic relocation we'll
-                expand the relocation sections by the appropriate amount. */
+                expand the relocation sections by the appropriate amount.  */
 
              struct alpha_elf_reloc_entry *rent;
 
@@ -2559,6 +2632,7 @@ elf64_alpha_check_relocs (abfd, info, sec, relocs)
                  rent->srel = sreloc;
                  rent->rtype = r_type;
                  rent->count = 1;
+                 rent->reltext = (sec->flags & SEC_READONLY) != 0;
 
                  rent->next = h->reloc_entries;
                  h->reloc_entries = rent;
@@ -2566,10 +2640,13 @@ 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);
+             if (sec->flags & SEC_READONLY)
+               info->flags |= DF_TEXTREL;
            }
          break;
        }
@@ -2672,7 +2749,7 @@ elf64_alpha_adjust_dynamic_symbol (info, h)
 static boolean
 elf64_alpha_merge_ind_symbols (hi, dummy)
      struct alpha_elf_link_hash_entry *hi;
-     PTR dummy;
+     PTR dummy ATTRIBUTE_UNUSED;
 {
   struct alpha_elf_link_hash_entry *hs;
 
@@ -2764,7 +2841,7 @@ elf64_alpha_can_merge_gots (a, b)
       Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
       int i, n;
 
-      n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info;
+      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
       for (i = 0; i < n; ++i)
        {
          struct alpha_elf_got_entry *ae, *be;
@@ -2836,7 +2913,7 @@ elf64_alpha_merge_gots (a, b)
       hashes = alpha_elf_sym_hashes (bsub);
       symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
 
-      n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info;
+      n = NUM_SHDR_ENTRIES (symtab_hdr) - symtab_hdr->sh_info;
       for (i = 0; i < n; ++i)
         {
          struct alpha_elf_got_entry *ae, *be, **pbe, **start;
@@ -2894,7 +2971,7 @@ elf64_alpha_merge_gots (a, b)
 static boolean
 elf64_alpha_calc_got_offsets_for_symbol (h, arg)
      struct alpha_elf_link_hash_entry *h;
-     PTR arg;
+     PTR arg ATTRIBUTE_UNUSED;
 {
   struct alpha_elf_got_entry *gotent;
 
@@ -2960,10 +3037,10 @@ elf64_alpha_calc_got_offsets (info)
 
 static boolean
 elf64_alpha_size_got_sections (output_bfd, info)
-     bfd *output_bfd;
+     bfd *output_bfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
 {
-  bfd *i, *got_list, *cur_got_obj;
+  bfd *i, *got_list, *cur_got_obj = NULL;
   int something_changed = 0;
 
   got_list = alpha_elf_hash_table (info)->got_list;
@@ -3111,7 +3188,9 @@ elf64_alpha_calc_dynrel_sizes (h, info)
            || relent->rtype == R_ALPHA_REFQUAD)
          {
            relent->srel->_raw_size +=
-             sizeof(Elf64_External_Rela) * relent->count;
+             sizeof (Elf64_External_Rela) * relent->count;
+           if (relent->reltext)
+             info->flags |= DT_TEXTREL;
          }
 
       dynobj = elf_hash_table(info)->dynobj;
@@ -3140,12 +3219,11 @@ elf64_alpha_calc_dynrel_sizes (h, info)
 
 static boolean
 elf64_alpha_size_dynamic_sections (output_bfd, info)
-     bfd *output_bfd;
+     bfd *output_bfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
 {
   bfd *dynobj;
   asection *s;
-  boolean reltext;
   boolean relplt;
 
   dynobj = elf_hash_table(info)->dynobj;
@@ -3186,7 +3264,7 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
               i = alpha_elf_tdata(i)->got_link_next)
            count += alpha_elf_tdata(i)->n_local_got_entries;
 
-         srel->_raw_size += count * sizeof(Elf64_External_Rela);
+         srel->_raw_size += count * sizeof (Elf64_External_Rela);
        }
     }
   /* else we're not dynamic and by definition we don't need such things.  */
@@ -3194,7 +3272,6 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
-  reltext = false;
   relplt = false;
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
@@ -3224,19 +3301,6 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
 
          if (!strip)
            {
-             const char *outname;
-             asection *target;
-
-             /* If this relocation section applies to a read only
-                section, then we probably need a DT_TEXTREL entry.  */
-             outname = bfd_get_section_name (output_bfd,
-                                             s->output_section);
-             target = bfd_get_section_by_name (output_bfd, outname + 5);
-             if (target != NULL
-                 && (target->flags & SEC_READONLY) != 0
-                 && (target->flags & SEC_ALLOC) != 0)
-               reltext = true;
-
              if (strcmp(name, ".rela.plt") == 0)
                relplt = true;
 
@@ -3252,7 +3316,7 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
        }
 
       if (strip)
-       _bfd_strip_section_from_output (s);
+       _bfd_strip_section_from_output (info, s);
       else
        {
          /* Allocate memory for the section contents.  */
@@ -3289,10 +3353,10 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
       if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0)
          || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0)
          || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT,
-                                           sizeof(Elf64_External_Rela)))
+                                           sizeof (Elf64_External_Rela)))
        return false;
 
-      if (reltext)
+      if (info->flags & DF_TEXTREL)
        {
          if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
            return false;
@@ -3358,7 +3422,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
       struct alpha_elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       bfd_vma relocation;
-      bfd_vma addend;
+      bfd_signed_vma addend;
       bfd_reloc_status_type r;
 
       r_type = ELF64_R_TYPE(rel->r_info);
@@ -3378,7 +3442,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
             in which case we have to adjust according to where the
             section symbol winds up in the output section.  */
 
-         /* The symbol associated with GPDISP and LITUSE is 
+         /* The symbol associated with GPDISP and LITUSE is
             immaterial.  Only the addend is significant.  */
          if (r_type == R_ALPHA_GPDISP || r_type == R_ALPHA_LITUSE)
            continue;
@@ -3459,13 +3523,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;
            }
@@ -3497,7 +3565,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_ALPHA_OP_PSUB:
        case R_ALPHA_OP_PRSHIFT:
          /* We hate these silly beasts.  */
-         abort();
+         abort ();
 
        case R_ALPHA_LITERAL:
          {
@@ -3551,7 +3619,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                                               ((Elf64_External_Rela *)
                                                srelgot->contents)
                                               + srelgot->reloc_count++);
-                   BFD_ASSERT (sizeof(Elf64_External_Rela)
+                   BFD_ASSERT (sizeof (Elf64_External_Rela)
                                * srelgot->reloc_count
                                <= srelgot->_cooked_size);
                  }
@@ -3607,7 +3675,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;
@@ -3656,7 +3724,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
                                       ((Elf64_External_Rela *)
                                        srel->contents)
                                       + srel->reloc_count++);
-           BFD_ASSERT (sizeof(Elf64_External_Rela) * srel->reloc_count
+           BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
                        <= srel->_cooked_size);
          }
          goto default_reloc;
@@ -3809,7 +3877,7 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
                                             ((Elf64_External_Rela *)
                                              srel->contents)
                                             + srel->reloc_count++);
-                 BFD_ASSERT (sizeof(Elf64_External_Rela) * srel->reloc_count
+                 BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
                              <= srel->_cooked_size);
                }
 
@@ -3842,7 +3910,7 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
          bfd_elf64_swap_reloca_out (output_bfd, &outrel,
                                     ((Elf64_External_Rela *)srel->contents
                                      + srel->reloc_count++));
-         BFD_ASSERT (sizeof(Elf64_External_Rela) * srel->reloc_count
+         BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
                      <= srel->_cooked_size);
        }
     }
@@ -4094,7 +4162,7 @@ elf64_alpha_final_link (abfd, info)
            {
              asection *s;
              EXTR esym;
-             bfd_vma last;
+             bfd_vma last = 0;
              unsigned int i;
              static const char * const name[] =
                {
@@ -4260,7 +4328,6 @@ elf64_alpha_final_link (abfd, info)
            }
 #endif
 
-
          /* Build the external symbol information.  */
          einfo.abfd = abfd;
          einfo.info = info;
@@ -4577,10 +4644,27 @@ elf64_alpha_final_link (abfd, info)
 
   return true;
 }
+
+static enum elf_reloc_type_class
+elf64_alpha_reloc_type_class (type)
+     int type;
+{
+  switch (type)
+    {
+    case R_ALPHA_RELATIVE:
+      return reloc_class_relative;
+    case R_ALPHA_JMP_SLOT:
+      return reloc_class_plt;
+    case R_ALPHA_COPY:
+      return reloc_class_copy;
+    default:
+      return reloc_class_normal;
+    }
+}
 \f
 /* ECOFF swapping routines.  These are used when dealing with the
    .mdebug section, which is in the ECOFF debugging format.  Copied
-   from elf32-mips.c. */
+   from elf32-mips.c.  */
 static const struct ecoff_debug_swap
 elf64_alpha_ecoff_debug_swap =
 {
@@ -4623,11 +4707,41 @@ 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
-#define ELF_MACHINE_CODE       EM_ALPHA
-#define ELF_MAXPAGESIZE        0x10000
+#define ELF_MACHINE_CODE       EM_ALPHA
+#define ELF_MAXPAGESIZE        0x10000
 
 #define bfd_elf64_bfd_link_hash_table_create \
   elf64_alpha_bfd_link_hash_table_create
@@ -4674,13 +4788,16 @@ elf64_alpha_ecoff_debug_swap =
   elf64_alpha_finish_dynamic_sections
 #define bfd_elf64_bfd_final_link \
   elf64_alpha_final_link
+#define elf_backend_reloc_type_class \
+  elf64_alpha_reloc_type_class
 
 #define elf_backend_ecoff_debug_swap \
   &elf64_alpha_ecoff_debug_swap
 
-/*
- * A few constants that determine how the .plt section is set up.
- */
+#define elf_backend_size_info \
+  alpha_elf_size_info
+
+/* A few constants that determine how the .plt section is set up.  */
 #define elf_backend_want_got_plt 0
 #define elf_backend_plt_readonly 0
 #define elf_backend_want_plt_sym 1
This page took 0.03517 seconds and 4 git commands to generate.