2005-10-10 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / bfd / elf32-s390.c
index 65c27e0220f5ccee89e6be9c7e393e4d4043b9df..55090c6a0c0d4310337f6e94568867a04015268a 100644 (file)
@@ -1,5 +1,6 @@
 /* IBM S/390-specific support for 32-bit ELF
-   Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
    Contributed by Carl B. Pedersen and Martin Schwidefsky.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -16,8 +17,8 @@
 
    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"
@@ -350,7 +351,8 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst)
      arelent *cache_ptr;
      Elf_Internal_Rela *dst;
 {
-  switch (ELF32_R_TYPE(dst->r_info))
+  unsigned int r_type = ELF32_R_TYPE(dst->r_info);
+  switch (r_type)
     {
     case R_390_GNU_VTINHERIT:
       cache_ptr->howto = &elf32_s390_vtinherit_howto;
@@ -361,8 +363,13 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst)
       break;
 
     default:
-      BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_390_max);
-      cache_ptr->howto = &elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+      if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0]))
+       {
+         (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+                                abfd, (int) r_type);
+         r_type = R_390_NONE;
+       }
+      cache_ptr->howto = &elf_howto_table[r_type];
     }
 }
 
@@ -802,12 +809,13 @@ create_got_section (dynobj, info)
   if (!htab->sgot || !htab->sgotplt)
     abort ();
 
-  htab->srelgot = bfd_make_section (dynobj, ".rela.got");
+  htab->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 (htab->srelgot == NULL
-      || ! bfd_set_section_flags (dynobj, htab->srelgot,
-                                 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-                                  | SEC_IN_MEMORY | SEC_LINKER_CREATED
-                                  | SEC_READONLY))
       || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
     return FALSE;
   return TRUE;
@@ -989,7 +997,12 @@ elf_s390_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;
+       }
 
       /* Create got section and local_got_refcounts array if they
         are needed.  */
@@ -1280,13 +1293,14 @@ elf_s390_check_relocs (abfd, info, sec, relocs)
                    {
                      flagword flags;
 
-                     sreloc = bfd_make_section (dynobj, name);
                      flags = (SEC_HAS_CONTENTS | SEC_READONLY
                               | SEC_IN_MEMORY | SEC_LINKER_CREATED);
                      if ((sec->flags & SEC_ALLOC) != 0)
                        flags |= SEC_ALLOC | SEC_LOAD;
+                     sreloc = bfd_make_section_with_flags (dynobj,
+                                                           name,
+                                                           flags);
                      if (sreloc == NULL
-                         || ! bfd_set_section_flags (dynobj, sreloc, flags)
                          || ! bfd_set_section_alignment (dynobj, sreloc, 2))
                        return FALSE;
                    }
@@ -1305,14 +1319,15 @@ elf_s390_check_relocs (abfd, info, sec, relocs)
                     We really need local syms available to do this
                     easily.  Oh well.  */
                  asection *s;
+                 void *vpp;
 
                  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
                                                 sec, r_symndx);
                  if (s == NULL)
                    return FALSE;
 
-                 head = ((struct elf_s390_dyn_relocs **)
-                         &elf_section_data (s)->local_dynrel);
+                 vpp = &elf_section_data (s)->local_dynrel;
+                 head = (struct elf_s390_dyn_relocs **) vpp;
                }
 
              p = *head;
@@ -1437,6 +1452,9 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs)
          struct elf_s390_dyn_relocs *p;
 
          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;
          eh = (struct elf_s390_link_hash_entry *) h;
 
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
@@ -1666,6 +1684,13 @@ elf_s390_adjust_dynamic_symbol (info, h)
        }
     }
 
+  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
@@ -2014,10 +2039,7 @@ elf_s390_size_dynamic_sections (output_bfd, info)
        {
          struct elf_s390_dyn_relocs *p;
 
-         for (p = *((struct elf_s390_dyn_relocs **)
-                    &elf_section_data (s)->local_dynrel);
-              p != NULL;
-              p = p->next)
+         for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
            {
              if (!bfd_is_abs_section (p->sec)
                  && bfd_is_abs_section (p->sec->output_section))
@@ -2088,7 +2110,8 @@ elf_s390_size_dynamic_sections (output_bfd, info)
 
       if (s == htab->splt
          || s == htab->sgot
-         || s == htab->sgotplt)
+         || s == htab->sgotplt
+         || s == htab->sdynbss)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
@@ -2120,10 +2143,13 @@ elf_s390_size_dynamic_sections (output_bfd, info)
             function which decides whether anything needs to go
             into these sections.  */
 
-         _bfd_strip_section_from_output (info, s);
+         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,
@@ -2986,10 +3012,11 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section,
          && !((input_section->flags & SEC_DEBUGGING) != 0
               && h->def_dynamic))
        (*_bfd_error_handler)
-         (_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"),
+         (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
           input_bfd,
           input_section,
           (long) rel->r_offset,
+          howto->name,
           h->root.root.string);
 
       if (r_type == R_390_20
@@ -3029,8 +3056,9 @@ elf_s390_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)))
+                    (info, (h ? &h->root : NULL), name, howto->name,
+                     (bfd_vma) 0, input_bfd, input_section,
+                     rel->r_offset)))
                return FALSE;
            }
          else
This page took 0.025282 seconds and 4 git commands to generate.