OSDN Git Service

mips64*-*-toppers* support.
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf64-alpha.c
index 3d4350d..501e2ef 100644 (file)
@@ -1,13 +1,13 @@
 /* Alpha specific support for 64-bit ELF
    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007 Free Software Foundation, Inc.
+   2006, 2007, 2008, 2009  Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@tamu.edu>.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,7 +17,9 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
 
 /* We need a published ABI spec for this.  Until one comes out, don't
    assume this'll remain unchanged forever.  */
@@ -101,6 +103,57 @@ bfd_boolean elf64_alpha_use_secureplt = FALSE;
 
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
 \f
+
+/* Used to implement multiple .got subsections.  */
+struct alpha_elf_got_entry
+{
+  struct alpha_elf_got_entry *next;
+
+  /* Which .got subsection?  */
+  bfd *gotobj;
+
+  /* The addend in effect for this entry.  */
+  bfd_vma addend;
+
+  /* The .got offset for this entry.  */
+  int got_offset;
+
+  /* The .plt offset for this entry.  */
+  int plt_offset;
+
+  /* How many references to this entry?  */
+  int use_count;
+
+  /* The relocation type of this entry.  */
+  unsigned char reloc_type;
+
+  /* How a LITERAL is used.  */
+  unsigned char flags;
+
+  /* Have we initialized the dynamic relocation for this entry?  */
+  unsigned char reloc_done;
+
+  /* Have we adjusted this entry for SEC_MERGE?  */
+  unsigned char reloc_xlated;
+};
+
+struct alpha_elf_reloc_entry
+{
+  struct alpha_elf_reloc_entry *next;
+
+  /* Which .reloc section? */
+  asection *srel;
+
+  /* What kind of relocation? */
+  unsigned int rtype;
+
+  /* Is this against read-only section? */
+  unsigned int reltext : 1;
+
+  /* How many did we find?  */
+  unsigned long count;
+};
+
 struct alpha_elf_link_hash_entry
 {
   struct elf_link_hash_entry root;
@@ -123,56 +176,11 @@ struct alpha_elf_link_hash_entry
 #define ALPHA_ELF_LINK_HASH_TLS_IE      0x80
 
   /* Used to implement multiple .got subsections.  */
-  struct alpha_elf_got_entry
-  {
-    struct alpha_elf_got_entry *next;
-
-    /* Which .got subsection?  */
-    bfd *gotobj;
-
-    /* The addend in effect for this entry.  */
-    bfd_vma addend;
-
-    /* The .got offset for this entry.  */
-    int got_offset;
-
-    /* The .plt offset for this entry.  */
-    int plt_offset;
-
-    /* How many references to this entry?  */
-    int use_count;
-
-    /* The relocation type of this entry.  */
-    unsigned char reloc_type;
-
-    /* How a LITERAL is used.  */
-    unsigned char flags;
-
-    /* Have we initialized the dynamic relocation for this entry?  */
-    unsigned char reloc_done;
-
-    /* Have we adjusted this entry for SEC_MERGE?  */
-    unsigned char reloc_xlated;
-  } *got_entries;
+  struct alpha_elf_got_entry *got_entries;
 
   /* Used to count non-got, non-plt relocations for delayed sizing
      of relocation sections.  */
-  struct alpha_elf_reloc_entry
-  {
-    struct alpha_elf_reloc_entry *next;
-
-    /* Which .reloc section? */
-    asection *srel;
-
-    /* What kind of relocation? */
-    unsigned int rtype;
-
-    /* Is this against read-only section? */
-    unsigned int reltext : 1;
-
-    /* How many did we find?  */
-    unsigned long count;
-  } *reloc_entries;
+  struct alpha_elf_reloc_entry *reloc_entries;
 };
 
 /* Alpha ELF linker hash table.  */
@@ -322,17 +330,16 @@ struct alpha_elf_obj_tdata
 #define alpha_elf_tdata(abfd) \
   ((struct alpha_elf_obj_tdata *) (abfd)->tdata.any)
 
+#define is_alpha_elf(bfd) \
+  (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+   && elf_tdata (bfd) != NULL \
+   && elf_object_id (bfd) == ALPHA_ELF_TDATA)
+
 static bfd_boolean
 elf64_alpha_mkobject (bfd *abfd)
 {
-  if (abfd->tdata.any == NULL)
-    {
-      bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
-      abfd->tdata.any = bfd_zalloc (abfd, amt);
-      if (abfd->tdata.any == NULL)
-       return FALSE;
-    }
-  return bfd_elf_mkobject (abfd);
+  return bfd_elf_allocate_object (abfd, sizeof (struct alpha_elf_obj_tdata),
+                                 ALPHA_ELF_TDATA);
 }
 
 static bfd_boolean
@@ -457,8 +464,9 @@ elf64_alpha_reloc_gpdisp (bfd *abfd, arelent *reloc_entry,
    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)
+  HOWTO(N, 0, 0, 0, 0, 0, complain_overflow_dont, elf64_alpha_reloc_bad, 0, 0, 0, 0, 0)
 
 static reloc_howto_type elf64_alpha_howto_table[] =
 {
@@ -1232,6 +1240,9 @@ elf64_alpha_create_got_section (bfd *abfd,
   flagword flags;
   asection *s;
 
+  if (! is_alpha_elf (abfd))
+    return FALSE;
+
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
           | SEC_LINKER_CREATED);
   s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
@@ -1258,6 +1269,9 @@ elf64_alpha_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flagword flags;
   struct elf_link_hash_entry *h;
 
+  if (! is_alpha_elf (abfd))
+    return FALSE;
+
   /* We need to create .plt, .rela.plt, .got, and .rela.got sections.  */
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY
@@ -1741,7 +1755,6 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 {
   bfd *dynobj;
   asection *sreloc;
-  const char *rel_sec_name;
   Elf_Internal_Shdr *symtab_hdr;
   struct alpha_elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel, *relend;
@@ -1759,14 +1772,15 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
   if ((sec->flags & SEC_ALLOC) == 0)
     return TRUE;
 
-  dynobj = elf_hash_table(info)->dynobj;
+  BFD_ASSERT (is_alpha_elf (abfd));
+
+  dynobj = elf_hash_table (info)->dynobj;
   if (dynobj == NULL)
-    elf_hash_table(info)->dynobj = dynobj = abfd;
+    elf_hash_table (info)->dynobj = dynobj = abfd;
 
   sreloc = NULL;
-  rel_sec_name = NULL;
-  symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
-  sym_hashes = alpha_elf_sym_hashes(abfd);
+  symtab_hdr = &elf_symtab_hdr (abfd);
+  sym_hashes = alpha_elf_sym_hashes (abfd);
 
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; ++rel)
@@ -1914,41 +1928,16 @@ elf64_alpha_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
       if (need & NEED_DYNREL)
        {
-         if (rel_sec_name == NULL)
-           {
-             rel_sec_name = (bfd_elf_string_from_elf_section
-                             (abfd, elf_elfheader(abfd)->e_shstrndx,
-                              elf_section_data(sec)->rel_hdr.sh_name));
-             if (rel_sec_name == NULL)
-               return FALSE;
-
-             BFD_ASSERT (CONST_STRNEQ (rel_sec_name, ".rela")
-                         && strcmp (bfd_get_section_name (abfd, sec),
-                                    rel_sec_name+5) == 0);
-           }
-
          /* We need to create the section here now whether we eventually
             use it or not so that it gets mapped to an output section by
-            the linker.  If not used, we'll kill it in
-            size_dynamic_sections.  */
+            the linker.  If not used, we'll kill it in size_dynamic_sections.  */
          if (sreloc == NULL)
            {
-             sreloc = bfd_get_section_by_name (dynobj, rel_sec_name);
+             sreloc = _bfd_elf_make_dynamic_reloc_section
+               (sec, dynobj, 3, abfd, /*rela?*/ TRUE);
+
              if (sreloc == NULL)
-               {
-                 flagword flags;
-
-                 flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
-                          | SEC_LINKER_CREATED | SEC_READONLY);
-                 if (sec->flags & SEC_ALLOC)
-                   flags |= SEC_ALLOC | SEC_LOAD;
-                 sreloc = bfd_make_section_with_flags (dynobj,
-                                                       rel_sec_name,
-                                                       flags);
-                 if (sreloc == NULL
-                     || !bfd_set_section_alignment (dynobj, sreloc, 3))
-                   return FALSE;
-               }
+               return FALSE;
            }
 
          if (h)
@@ -2388,7 +2377,12 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
     {
       for (i = info->input_bfds; i ; i = i->link_next)
        {
-         bfd *this_got = alpha_elf_tdata (i)->gotobj;
+         bfd *this_got;
+
+         if (! is_alpha_elf (i))
+           continue;
+
+         this_got = alpha_elf_tdata (i)->gotobj;
          if (this_got == NULL)
            continue;
 
@@ -2419,6 +2413,9 @@ elf64_alpha_size_got_sections (struct bfd_link_info *info)
     }
 
   cur_got_obj = got_list;
+  if (cur_got_obj == NULL)
+    return FALSE;
+
   i = alpha_elf_tdata(cur_got_obj)->got_link_next;
   while (i != NULL)
     {
@@ -3087,7 +3084,7 @@ elf64_alpha_relax_opt_call (struct alpha_relax_info *info, bfd_vma symval)
 
   /* 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
+  if (info->link_info->output_bfd->xvec != info->tsec->owner->xvec
       || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
     return 0;
 
@@ -3610,6 +3607,8 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
       || sec->reloc_count == 0)
     return TRUE;
 
+  BFD_ASSERT (is_alpha_elf (abfd));
+
   /* Make sure our GOT and PLT tables are up-to-date.  */
   if (alpha_elf_hash_table(link_info)->relax_trip != link_info->relax_trip)
     {
@@ -3626,7 +3625,7 @@ elf64_alpha_relax_section (bfd *abfd, asection *sec,
        }
     }
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  symtab_hdr = &elf_symtab_hdr (abfd);
   local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
 
   /* Load the relocations for this section.  */
@@ -3933,7 +3932,7 @@ elf64_alpha_relocate_section_r (bfd *output_bfd ATTRIBUTE_UNUSED,
   struct elf_link_hash_entry **sym_hashes;
   bfd_boolean ret_val = TRUE;
 
-  symtab_hdr_sh_info = elf_tdata (input_bfd)->symtab_hdr.sh_info;
+  symtab_hdr_sh_info = elf_symtab_hdr (input_bfd).sh_info;
   sym_hashes = elf_sym_hashes (input_bfd);
 
   relend = relocs + input_section->reloc_count;
@@ -4021,6 +4020,8 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   struct alpha_elf_got_entry **local_got_entries;
   bfd_boolean ret_val;
 
+  BFD_ASSERT (is_alpha_elf (input_bfd));
+  
   /* Handle relocatable links with a smaller loop.  */
   if (info->relocatable)
     return elf64_alpha_relocate_section_r (output_bfd, info, input_bfd,
@@ -4031,7 +4032,7 @@ elf64_alpha_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
   ret_val = TRUE;
 
-  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  symtab_hdr = &elf_symtab_hdr (input_bfd);
 
   dynobj = elf_hash_table (info)->dynobj;
   if (dynobj)
@@ -5041,15 +5042,11 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
              input_section = p->u.indirect.section;
              input_bfd = input_section->owner;
 
-             if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
-                 || (get_elf_backend_data (input_bfd)
-                     ->elf_backend_ecoff_debug_swap) == NULL)
-               {
-                 /* I don't know what a non ALPHA ELF bfd would be
-                    doing with a .mdebug section, but I don't really
-                    want to deal with it.  */
-                 continue;
-               }
+             if (! is_alpha_elf (input_bfd))
+               /* I don't know what a non ALPHA ELF bfd would be
+                  doing with a .mdebug section, but I don't really
+                  want to deal with it.  */
+               continue;
 
              input_swap = (get_elf_backend_data (input_bfd)
                            ->elf_backend_ecoff_debug_swap);
@@ -5072,7 +5069,7 @@ elf64_alpha_final_link (bfd *abfd, struct bfd_link_info *info)
                 interesting information, try to find the symbol in
                 the linker global hash table and save the information
                 for the output external symbols.  */
-             eraw_src = input_debug.external_ext;
+             eraw_src = (char *) input_debug.external_ext;
              eraw_end = (eraw_src
                          + (input_debug.symbolic_header.iextMax
                             * input_swap->external_ext_size));
@@ -5275,6 +5272,7 @@ static const struct elf_size_info alpha_elf_size_info =
   ELFCLASS64, EV_CURRENT,
   bfd_elf64_write_out_phdrs,
   bfd_elf64_write_shdrs_and_ehdr,
+  bfd_elf64_checksum_contents,
   bfd_elf64_write_relocs,
   bfd_elf64_swap_symbol_in,
   bfd_elf64_swap_symbol_out,
@@ -5326,6 +5324,8 @@ static const struct elf_size_info alpha_elf_size_info =
 
 #define elf_backend_add_symbol_hook \
   elf64_alpha_add_symbol_hook
+#define elf_backend_relocs_compatible \
+  _bfd_elf_relocs_compatible
 #define elf_backend_check_relocs \
   elf64_alpha_check_relocs
 #define elf_backend_create_dynamic_sections \