* pe-arm-wince.c (pe_print_compressed_pdata): Define new function to
[platform/upstream/binutils.git] / bfd / elf32-cris.c
index 44cae03..75d0695 100644 (file)
@@ -1,5 +1,5 @@
 /* CRIS-specific support for 32-bit ELF.
-   Copyright 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
    Contributed by Axis Communications AB.
    Written by Hans-Peter Nilsson, based on elf32-fr30.c
@@ -9,7 +9,7 @@
 
    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,
 
    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/cris.h"
@@ -51,14 +52,6 @@ static bfd_reloc_status_type cris_final_link_relocate
   PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
           Elf_Internal_Rela *, bfd_vma));
 
-static bfd_boolean cris_elf_gc_sweep_hook
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-
-static asection * cris_elf_gc_mark_hook
-  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
-          struct elf_link_hash_entry *, Elf_Internal_Sym *));
-
 static bfd_boolean cris_elf_object_p PARAMS ((bfd *));
 
 static void cris_elf_final_write_processing PARAMS ((bfd *, bfd_boolean));
@@ -156,7 +149,12 @@ static reloc_howto_type cris_elf_howto_table [] =
         32,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
+        /* We don't want overflow complaints for 64-bit vma builds
+           for e.g. sym+0x40000000 (or actually sym-0xc0000000 in
+           32-bit ELF) where sym=0xc0001234.
+           Don't do this for the PIC relocs, as we don't expect to
+           see them with large offsets.  */
+        complain_overflow_dont, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_CRIS_32",           /* name */
         FALSE,                 /* partial_inplace */
@@ -460,6 +458,21 @@ cris_reloc_type_lookup (abfd, code)
   return NULL;
 }
 
+static reloc_howto_type *
+cris_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (cris_elf_howto_table) / sizeof (cris_elf_howto_table[0]);
+       i++)
+    if (cris_elf_howto_table[i].name != NULL
+       && strcasecmp (cris_elf_howto_table[i].name, r_name) == 0)
+      return &cris_elf_howto_table[i];
+
+  return NULL;
+}
+
 /* Set the howto pointer for an CRIS ELF reloc.  */
 
 static void
@@ -844,8 +857,9 @@ elf_cris_link_hash_table_create (abfd)
   if (ret == (struct elf_cris_link_hash_table *) NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
-                                      elf_cris_link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+                                     elf_cris_link_hash_newfunc,
+                                     sizeof (struct elf_cris_link_hash_entry)))
     {
       free (ret);
       return NULL;
@@ -929,9 +943,6 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
-  if (info->relocatable)
-    return TRUE;
-
   dynobj = elf_hash_table (info)->dynobj;
   local_got_offsets = elf_local_got_offsets (input_bfd);
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
@@ -966,7 +977,6 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          || r_type == R_CRIS_GNU_VTENTRY)
        continue;
 
-      /* This is a final link.  */
       r_symndx = ELF32_R_SYM (rel->r_info);
       howto  = cris_elf_howto_table + r_type;
       h      = NULL;
@@ -1044,7 +1054,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                      || r_type == R_CRIS_16_PCREL
                      || r_type == R_CRIS_32_PCREL))
                relocation = 0;
-             else if (unresolved_reloc)
+             else if (!info->relocatable && unresolved_reloc)
                {
                  _bfd_error_handler
                    (_("%B, section %A: unresolvable relocation %s against symbol `%s'"),
@@ -1058,6 +1068,20 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
        }
 
+      if (sec != NULL && elf_discarded_section (sec))
+       {
+         /* For relocs against symbols from removed linkonce sections,
+            or sections discarded by a linker script, we just want the
+            section contents zeroed.  Avoid any special processing.  */
+         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+         rel->r_info = 0;
+         rel->r_addend = 0;
+         continue;
+       }
+
+      if (info->relocatable)
+       continue;
+
       switch (r_type)
        {
        case R_CRIS_16_GOTPLT:
@@ -1382,7 +1406,7 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  if (name == NULL)
                    return FALSE;
 
-                 BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+                 BFD_ASSERT (CONST_STRNEQ (name, ".rela")
                              && strcmp (bfd_get_section_name (input_bfd,
                                                               input_section),
                                         name + 5) == 0);
@@ -1432,11 +1456,12 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                }
              else
                {
+                 outrel.r_addend = relocation + rel->r_addend;
+
                  if (r_type == R_CRIS_32)
                    {
                      relocate = TRUE;
                      outrel.r_info = ELF32_R_INFO (0, R_CRIS_RELATIVE);
-                     outrel.r_addend = relocation + rel->r_addend;
                    }
                  else
                    {
@@ -1453,13 +1478,24 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                        {
                          asection *osec;
 
+                         /* We are turning this relocation into one
+                            against a section symbol.  It would be
+                            proper to subtract the symbol's value,
+                            osec->vma, from the emitted reloc addend,
+                            but ld.so expects buggy relocs.  */
                          osec = sec->output_section;
                          indx = elf_section_data (osec)->dynindx;
-                         BFD_ASSERT (indx > 0);
+                         if (indx == 0)
+                           {
+                             struct elf_cris_link_hash_table *htab;
+                             htab = elf_cris_hash_table (info);
+                             osec = htab->root.text_index_section;
+                             indx = elf_section_data (osec)->dynindx;
+                           }
+                         BFD_ASSERT (indx != 0);
                        }
 
                      outrel.r_info = ELF32_R_INFO (indx, r_type);
-                     outrel.r_addend = relocation + rel->r_addend;
                    }
                }
 
@@ -1764,7 +1800,7 @@ elf_cris_finish_dynamic_symbol (output_bfd, info, h, sym)
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+      || h == elf_hash_table (info)->hgot)
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -1917,50 +1953,30 @@ elf_cris_finish_dynamic_sections (output_bfd, info)
    relocation.  */
 
 static asection *
-cris_elf_gc_mark_hook (sec, info, rel, h, sym)
-     asection *sec;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     Elf_Internal_Rela *rel;
-     struct elf_link_hash_entry *h;
-     Elf_Internal_Sym *sym;
+cris_elf_gc_mark_hook (asection *sec,
+                      struct bfd_link_info *info,
+                      Elf_Internal_Rela *rel,
+                      struct elf_link_hash_entry *h,
+                      Elf_Internal_Sym *sym)
 {
   if (h != NULL)
-    {
-      switch (ELF32_R_TYPE (rel->r_info))
-       {
-       case R_CRIS_GNU_VTINHERIT:
-       case R_CRIS_GNU_VTENTRY:
-         break;
-
-       default:
-         switch (h->root.type)
-           {
-           case bfd_link_hash_defined:
-           case bfd_link_hash_defweak:
-             return h->root.u.def.section;
-
-           case bfd_link_hash_common:
-             return h->root.u.c.p->section;
-
-           default:
-             break;
-           }
-       }
-    }
-  else
-    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+    switch (ELF32_R_TYPE (rel->r_info))
+      {
+      case R_CRIS_GNU_VTINHERIT:
+      case R_CRIS_GNU_VTENTRY:
+       return NULL;
+      }
 
-  return NULL;
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
 /* Update the got entry reference counts for the section being removed.  */
 
 static bfd_boolean
-cris_elf_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info ATTRIBUTE_UNUSED;
-     asection *sec ATTRIBUTE_UNUSED;
-     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
+cris_elf_gc_sweep_hook (bfd *abfd,
+                       struct bfd_link_info *info,
+                       asection *sec,
+                       const Elf_Internal_Rela *relocs)
 {
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
@@ -1970,6 +1986,9 @@ cris_elf_gc_sweep_hook (abfd, info, sec, relocs)
   asection *sgot;
   asection *srelgot;
 
+  if (info->relocatable)
+    return TRUE;
+
   dynobj = elf_hash_table (info)->dynobj;
   if (dynobj == NULL)
     return TRUE;
@@ -2078,9 +2097,6 @@ elf_cris_adjust_gotplt_to_got (h, p)
      PTR p;
 {
   struct bfd_link_info *info = (struct bfd_link_info *) p;
-  bfd *dynobj = elf_hash_table (info)->dynobj;
-
-  BFD_ASSERT (dynobj != NULL);
 
   if (h->root.root.type == bfd_link_hash_warning)
     h = (struct elf_cris_link_hash_entry *) h->root.root.u.i.link;
@@ -2100,9 +2116,13 @@ elf_cris_adjust_gotplt_to_got (h, p)
   else
     {
       /* No GOT entry for this symbol.  We need to create one.  */
-      asection *sgot = bfd_get_section_by_name (dynobj, ".got");
-      asection *srelgot
-       = bfd_get_section_by_name (dynobj, ".rela.got");
+      bfd *dynobj = elf_hash_table (info)->dynobj;
+      asection *sgot;
+      asection *srelgot;
+
+      BFD_ASSERT (dynobj != NULL);
+      sgot = bfd_get_section_by_name (dynobj, ".got");
+      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
 
       /* Put an accurate refcount there.  */
       h->root.got.refcount = h->gotplt_refcount;
@@ -2205,7 +2225,6 @@ elf_cris_adjust_dynamic_symbol (info, h)
 {
   bfd *dynobj;
   asection *s;
-  unsigned int power_of_two;
   bfd_size_type plt_entry_size;
 
   dynobj = elf_hash_table (info)->dynobj;
@@ -2379,6 +2398,13 @@ elf_cris_adjust_dynamic_symbol (info, h)
   if (!h->non_got_ref)
     return TRUE;
 
+  if (h->size == 0)
+    {
+      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
+                            h->root.root.string);
+      return TRUE;
+    }
+
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -2406,31 +2432,7 @@ elf_cris_adjust_dynamic_symbol (info, h)
       h->needs_copy = 1;
     }
 
-  /* Historic precedent: m68k and i386 allow max 8-byte alignment for the
-     thing to copy; so do we.  */
-
-  /* We need to figure out the alignment required for this symbol.  I
-     have no idea how ELF linkers handle this.  */
-  power_of_two = bfd_log2 (h->size);
-  if (power_of_two > 3)
-    power_of_two = 3;
-
-  /* Apply the required alignment.  */
-  s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
-  if (power_of_two > bfd_get_section_alignment (dynobj, s))
-    {
-      if (!bfd_set_section_alignment (dynobj, s, power_of_two))
-       return FALSE;
-    }
-
-  /* Define the symbol as being at this point in the section.  */
-  h->root.u.def.section = s;
-  h->root.u.def.value = s->size;
-
-  /* Increment the section size to make room for the symbol.  */
-  s->size += h->size;
-
-  return TRUE;
+  return _bfd_elf_adjust_dynamic_copy (h, s);
 }
 
 /* Look through the relocs for a section during the first phase.  */
@@ -2444,7 +2446,7 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
 {
   bfd *dynobj;
   Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+  struct elf_link_hash_entry **sym_hashes;
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
@@ -2458,16 +2460,12 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
   dynobj = elf_hash_table (info)->dynobj;
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
-  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
   local_got_refcounts = elf_local_got_refcounts (abfd);
 
   sgot = NULL;
   srelgot = NULL;
   sreloc = NULL;
 
-  if (!elf_bad_symtab (abfd))
-    sym_hashes_end -= symtab_hdr->sh_info;
-
   rel_end = relocs + sec->reloc_count;
   for (rel = relocs; rel < rel_end; rel++)
     {
@@ -2479,7 +2477,12 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
       if (r_symndx < symtab_hdr->sh_info)
         h = NULL;
       else
-        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         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;
+       }
 
       r_type = ELF32_R_TYPE (rel->r_info);
 
@@ -2542,15 +2545,15 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
              srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
              if (srelgot == NULL)
                {
-                 srelgot = bfd_make_section (dynobj, ".rela.got");
+                 srelgot = bfd_make_section_with_flags (dynobj,
+                                                        ".rela.got",
+                                                        (SEC_ALLOC
+                                                         | SEC_LOAD
+                                                         | SEC_HAS_CONTENTS
+                                                         | SEC_IN_MEMORY
+                                                         | SEC_LINKER_CREATED
+                                                         | SEC_READONLY));
                  if (srelgot == NULL
-                     || !bfd_set_section_flags (dynobj, srelgot,
-                                                (SEC_ALLOC
-                                                 | SEC_LOAD
-                                                 | SEC_HAS_CONTENTS
-                                                 | SEC_IN_MEMORY
-                                                 | SEC_LINKER_CREATED
-                                                 | SEC_READONLY))
                      || !bfd_set_section_alignment (dynobj, srelgot, 2))
                    return FALSE;
                }
@@ -2780,22 +2783,21 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
              if (name == NULL)
                return FALSE;
 
-             BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+             BFD_ASSERT (CONST_STRNEQ (name, ".rela")
                          && strcmp (bfd_get_section_name (abfd, sec),
                                     name + 5) == 0);
 
              sreloc = bfd_get_section_by_name (dynobj, name);
              if (sreloc == NULL)
                {
-                 sreloc = bfd_make_section (dynobj, name);
+                 sreloc = bfd_make_section_with_flags (dynobj, name,
+                                                       (SEC_ALLOC
+                                                        | SEC_LOAD
+                                                        | SEC_HAS_CONTENTS
+                                                        | SEC_IN_MEMORY
+                                                        | SEC_LINKER_CREATED
+                                                        | SEC_READONLY));
                  if (sreloc == NULL
-                     || !bfd_set_section_flags (dynobj, sreloc,
-                                                (SEC_ALLOC
-                                                 | SEC_LOAD
-                                                 | SEC_HAS_CONTENTS
-                                                 | SEC_IN_MEMORY
-                                                 | SEC_LINKER_CREATED
-                                                 | SEC_READONLY))
                      || !bfd_set_section_alignment (dynobj, sreloc, 2))
                    return FALSE;
                }
@@ -2850,7 +2852,9 @@ cris_elf_check_relocs (abfd, info, sec, relocs)
         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
         case R_CRIS_GNU_VTENTRY:
-          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+          BFD_ASSERT (h != NULL);
+          if (h != NULL
+              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
             return FALSE;
           break;
 
@@ -2931,7 +2935,6 @@ elf_cris_size_dynamic_sections (output_bfd, info)
   for (s = dynobj->sections; s != NULL; s = s->next)
     {
       const char *name;
-      bfd_boolean strip;
 
       if ((s->flags & SEC_LINKER_CREATED) == 0)
        continue;
@@ -2940,38 +2943,14 @@ elf_cris_size_dynamic_sections (output_bfd, info)
         of the dynobj section names depend upon the input files.  */
       name = bfd_get_section_name (dynobj, s);
 
-      strip = FALSE;
-
       if (strcmp (name, ".plt") == 0)
        {
-         if (s->size == 0)
-           {
-             /* Strip this section if we don't need it; see the
-                 comment below.  */
-             strip = TRUE;
-           }
-         else
-           {
-             /* Remember whether there is a PLT.  */
-             plt = TRUE;
-           }
+         /* Remember whether there is a PLT.  */
+         plt = s->size != 0;
        }
-      else if (strncmp (name, ".rela", 5) == 0)
+      else if (CONST_STRNEQ (name, ".rela"))
        {
-         if (s->size == 0)
-           {
-             /* If we don't need this section, strip it from the
-                output file.  This is mostly to handle .rela.bss and
-                .rela.plt.  We must create both sections in
-                create_dynamic_sections, because they must be created
-                before the linker maps input sections to output
-                sections.  The linker does that before
-                adjust_dynamic_symbol is called, and it is that
-                function which decides whether anything needs to go
-                into these sections.  */
-             strip = TRUE;
-           }
-         else
+         if (s->size != 0)
            {
              /* Remember whether there are any reloc sections other
                  than .rela.plt.  */
@@ -2983,25 +2962,38 @@ elf_cris_size_dynamic_sections (output_bfd, info)
              s->reloc_count = 0;
            }
        }
-      else if (strncmp (name, ".got", 4) != 0)
+      else if (! CONST_STRNEQ (name, ".got")
+              && strcmp (name, ".dynbss") != 0)
        {
          /* It's not one of our sections, so don't allocate space.  */
          continue;
        }
 
-      if (strip)
+      if (s->size == 0)
        {
-         _bfd_strip_section_from_output (info, s);
+         /* If we don't need this section, strip it from the
+            output file.  This is mostly to handle .rela.bss and
+            .rela.plt.  We must create both sections in
+            create_dynamic_sections, because they must be created
+            before the linker maps input sections to output
+            sections.  The linker does that before
+            adjust_dynamic_symbol is called, and it is that
+            function which decides whether anything needs to go
+            into these sections.  */
+         s->flags |= SEC_EXCLUDE;
          continue;
        }
 
+      if ((s->flags & SEC_HAS_CONTENTS) == 0)
+       continue;
+
       /* Allocate memory for the section contents. We use bfd_zalloc here
         in case unused entries are not reclaimed before the section's
         contents are written out.  This should not happen, but this way
         if it does, we will not write out garbage.  For reloc sections,
         this will make entries have the type R_CRIS_NONE.  */
       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
-      if (s->contents == NULL && s->size != 0)
+      if (s->contents == NULL)
        return FALSE;
     }
 
@@ -3130,6 +3122,7 @@ elf_cris_discard_excess_program_dynamics (h, inf)
         introduce new problems.  Of course we don't do this if we're
         exporting all dynamic symbols.  */
       if (! info->export_dynamic
+         && h->root.dynindx != -1
          && !h->root.def_dynamic
          && !h->root.ref_dynamic)
        {
@@ -3404,6 +3397,7 @@ elf_cris_reloc_type_class (rela)
        cris_elf_copy_private_bfd_data
 
 #define bfd_elf32_bfd_reloc_type_lookup                cris_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup        cris_reloc_name_lookup
 
 #define bfd_elf32_bfd_link_hash_table_create \
        elf_cris_link_hash_table_create
@@ -3411,6 +3405,7 @@ elf_cris_reloc_type_class (rela)
        elf_cris_adjust_dynamic_symbol
 #define elf_backend_size_dynamic_sections \
        elf_cris_size_dynamic_sections
+#define elf_backend_init_index_section         _bfd_elf_init_1_index_section
 #define elf_backend_finish_dynamic_symbol \
        elf_cris_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
@@ -3436,8 +3431,6 @@ elf_cris_reloc_type_class (rela)
 
 #include "elf32-target.h"
 
-#define INCLUDED_TARGET_FILE
-
 #undef TARGET_LITTLE_SYM
 #undef TARGET_LITTLE_NAME
 #undef elf_symbol_leading_char
@@ -3445,5 +3438,7 @@ elf_cris_reloc_type_class (rela)
 #define TARGET_LITTLE_SYM bfd_elf32_us_cris_vec
 #define TARGET_LITTLE_NAME "elf32-us-cris"
 #define elf_symbol_leading_char '_'
+#undef elf32_bed
+#define elf32_bed elf32_us_cris_bed
 
 #include "elf32-target.h"