daily update
[deliverable/binutils-gdb.git] / bfd / elf32-microblaze.c
index c975e76800f8a2c5505291c7800a0b3a89d228fb..c0004248a269f6aaf1b9b4fc5d16b61f181a9324 100644 (file)
@@ -1,6 +1,6 @@
 /* Xilinx MicroBlaze-specific support for 32-bit ELF
 
-   Copyright 2009 Free Software Foundation, Inc.
+   Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -22,8 +22,8 @@
 
 int dbg = 0;
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
@@ -576,7 +576,8 @@ struct elf32_mb_link_hash_table
 /* Get the ELF linker hash table from a link_info structure.  */
 
 #define elf32_mb_hash_table(p)                         \
-  ((struct elf32_mb_link_hash_table *) ((p)->hash))
+  (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+  == MICROBLAZE_ELF_DATA ? ((struct elf32_mb_link_hash_table *) ((p)->hash)) : NULL)
 
 /* Create an entry in a microblaze ELF linker hash table.  */
 
@@ -621,7 +622,8 @@ microblaze_elf_link_hash_table_create (bfd *abfd)
     return NULL;
 
   if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
-                                     sizeof (struct elf32_mb_link_hash_entry)))
+                                     sizeof (struct elf32_mb_link_hash_entry),
+                                     MICROBLAZE_ELF_DATA))
     {
       free (ret);
       return NULL;
@@ -709,6 +711,9 @@ microblaze_elf_relocate_section (bfd *output_bfd,
     microblaze_elf_howto_init ();
 
   htab = elf32_mb_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   local_got_offsets = elf_local_got_offsets (input_bfd);
 
   sreloc = elf_section_data (input_section)->sreloc;
@@ -819,7 +824,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
            }
 
          /* Sanity check the address.  */
-         if (offset > bfd_get_section_limit (output_bfd, input_section))
+         if (offset > bfd_get_section_limit (input_bfd, input_section))
            {
              r = bfd_reloc_outofrange;
              goto check_reloc;
@@ -834,7 +839,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                /* Only relocate if the symbol is defined.  */
                if (sec)
                  {
-                   name = bfd_get_section_name (abfd, sec);
+                   name = bfd_get_section_name (sec->owner, sec);
 
                    if (strcmp (name, ".sdata2") == 0
                        || strcmp (name, ".sbss2") == 0)
@@ -863,7 +868,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                                               bfd_get_filename (input_bfd),
                                               sym_name,
                                               microblaze_elf_howto_table[(int) r_type]->name,
-                                              bfd_get_section_name (abfd, sec));
+                                              bfd_get_section_name (sec->owner, sec));
                        /*bfd_set_error (bfd_error_bad_value); ??? why? */
                        ret = FALSE;
                        continue;
@@ -879,7 +884,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                /* Only relocate if the symbol is defined.  */
                if (sec)
                  {
-                   name = bfd_get_section_name (abfd, sec);
+                   name = bfd_get_section_name (sec->owner, sec);
 
                    if (strcmp (name, ".sdata") == 0
                        || strcmp (name, ".sbss") == 0)
@@ -908,7 +913,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                                               bfd_get_filename (input_bfd),
                                               sym_name,
                                               microblaze_elf_howto_table[(int) r_type]->name,
-                                              bfd_get_section_name (abfd, sec));
+                                              bfd_get_section_name (sec->owner, sec));
                        /*bfd_set_error (bfd_error_bad_value); ??? why? */
                        ret = FALSE;
                        continue;
@@ -1062,10 +1067,10 @@ microblaze_elf_relocate_section (bfd *output_bfd,
            case (int) R_MICROBLAZE_64:
            case (int) R_MICROBLAZE_32:
              {
-               /* r_symndx will be zero only for relocs against symbols
+               /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
                   from removed linkonce sections, or sections discarded by
                   a linker script.  */
-               if (r_symndx == 0 || (input_section->flags & SEC_ALLOC) == 0)
+               if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
                  {
                    relocation += addend;
                    if (r_type == R_MICROBLAZE_32)
@@ -1104,7 +1109,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                  {
                    Elf_Internal_Rela outrel;
                    bfd_byte *loc;
-                   bfd_boolean skip, relocate = FALSE;
+                   bfd_boolean skip;
 
                    /* When generating a shared object, these relocations
                       are copied into the output file to be resolved at run
@@ -1120,7 +1125,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
                    if (outrel.r_offset == (bfd_vma) -1)
                      skip = TRUE;
                    else if (outrel.r_offset == (bfd_vma) -2)
-                     skip = TRUE, relocate = TRUE;
+                     skip = TRUE;
                    outrel.r_offset += (input_section->output_section->vma
                                        + input_section->output_offset);
 
@@ -1284,7 +1289,7 @@ microblaze_elf_relax_section (bfd *abfd,
   bfd_byte *free_contents = NULL;
   int rel_count;
   unsigned int shndx;
-  int i, index;
+  int i, sym_index;
   asection *o;
   struct elf_link_hash_entry *sym_hash;
   Elf_Internal_Sym *isymbuf, *isymend;
@@ -1319,8 +1324,7 @@ microblaze_elf_relax_section (bfd *abfd,
                                    0, NULL, NULL, NULL);
   BFD_ASSERT (isymbuf != NULL);
 
-  internal_relocs = _bfd_elf_link_read_relocs
-    (abfd, sec, NULL, NULL, link_info->keep_memory);
+  internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
   if (internal_relocs == NULL)
     goto error_return;
   if (! link_info->keep_memory)
@@ -1364,7 +1368,6 @@ microblaze_elf_relax_section (bfd *abfd,
       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
        {
          /* A local symbol.  */
-         Elf_Internal_Sym *isym;
          asection *sym_sec;
 
          isym = isymbuf + ELF32_R_SYM (irel->r_info);
@@ -1464,7 +1467,6 @@ microblaze_elf_relax_section (bfd *abfd,
                 range to be adjusted, and hence must be changed.  */
              if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
                {
-                 Elf_Internal_Sym *isym;
                  isym = isymbuf + ELF32_R_SYM (irel->r_info);
                  /* Only handle relocs against .text.  */
                  if (isym->st_shndx == shndx
@@ -1507,7 +1509,7 @@ microblaze_elf_relax_section (bfd *abfd,
       /* Look through all other sections.  */
       for (o = abfd->sections; o != NULL; o = o->next)
         {
-          Elf_Internal_Rela *internal_relocs;
+          Elf_Internal_Rela *irelocs;
           Elf_Internal_Rela *irelscan, *irelscanend;
           bfd_byte *ocontents;
 
@@ -1519,13 +1521,13 @@ microblaze_elf_relax_section (bfd *abfd,
           /* We always cache the relocs.  Perhaps, if info->keep_memory is
              FALSE, we should free them, if we are permitted to.  */
 
-          internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
-          if (internal_relocs == NULL)
+          irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
+          if (irelocs == NULL)
             goto error_return;
 
           ocontents = NULL;
-          irelscanend = internal_relocs + o->reloc_count;
-          for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
+          irelscanend = irelocs + o->reloc_count;
+          for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
             {
               if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
                 {
@@ -1745,9 +1747,9 @@ microblaze_elf_relax_section (bfd *abfd,
       /* Now adjust the global symbols defined in this section.  */
       isym = isymbuf + symtab_hdr->sh_info;
       isymend = isymbuf + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
-      for (index = 0; isym < isymend; isym++, index++)
+      for (sym_index = 0; isym < isymend; isym++, sym_index++)
         {
-          sym_hash = elf_sym_hashes (abfd)[index];
+          sym_hash = elf_sym_hashes (abfd)[sym_index];
           if (isym->st_shndx == shndx
               && (sym_hash->root.type == bfd_link_hash_defined
                   || sym_hash->root.type == bfd_link_hash_defweak)
@@ -1822,38 +1824,20 @@ microblaze_elf_relax_section (bfd *abfd,
 
 static asection *
 microblaze_elf_gc_mark_hook (asection *sec,
-                            struct bfd_link_info * info ATTRIBUTE_UNUSED,
+                            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_MICROBLAZE_GNU_VTINHERIT:
-       case R_MICROBLAZE_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);
-
-  return NULL;
+    switch (ELF32_R_TYPE (rel->r_info))
+      {
+      case R_MICROBLAZE_GNU_VTINHERIT:
+      case R_MICROBLAZE_GNU_VTENTRY:
+       return NULL;
+      }
+
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
 /* Update the got entry reference counts for the section being removed.  */
@@ -1888,12 +1872,16 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
   if (! _bfd_elf_create_got_section (dynobj, info))
     return FALSE;
   htab = elf32_mb_hash_table (info);
-  htab->sgot = bfd_get_section_by_name (dynobj, ".got");
-  htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
+  if (htab == NULL)
+    return FALSE;
+
+  htab->sgot = bfd_get_linker_section (dynobj, ".got");
+  htab->sgotplt = bfd_get_linker_section (dynobj, ".got.plt");
   if (!htab->sgot || !htab->sgotplt)
     return FALSE;
 
-  htab->srelgot = bfd_make_section (dynobj, ".rela.got");
+  if ((htab->srelgot = bfd_get_linker_section (dynobj, ".rela.got")) == NULL)
+    htab->srelgot = bfd_make_section_anyway (dynobj, ".rela.got");
   if (htab->srelgot == NULL
       || ! bfd_set_section_flags (dynobj, htab->srelgot, SEC_ALLOC
                                   | SEC_LOAD
@@ -1920,14 +1908,15 @@ microblaze_elf_check_relocs (bfd * abfd,
   const Elf_Internal_Rela *     rel;
   const Elf_Internal_Rela *     rel_end;
   struct elf32_mb_link_hash_table *htab;
-  bfd_vma *local_got_offsets;
   asection *sreloc = NULL;
 
   if (info->relocatable)
     return TRUE;
 
   htab = elf32_mb_hash_table (info);
-  local_got_offsets = elf_local_got_offsets (abfd);
+  if (htab == NULL)
+    return FALSE;
+
   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);
@@ -2072,7 +2061,7 @@ microblaze_elf_check_relocs (bfd * abfd,
                    const char *name;
                    bfd *dynobj;
                    unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
-                   unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name;
+                   unsigned int shnam = _bfd_elf_single_rel_hdr (sec)->sh_name;
 
                    name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
                    if (name == NULL)
@@ -2091,18 +2080,19 @@ microblaze_elf_check_relocs (bfd * abfd,
                      htab->elf.dynobj = abfd;
                    dynobj = htab->elf.dynobj;
 
-                   sreloc = bfd_get_section_by_name (dynobj, name);
+                   sreloc = bfd_get_linker_section (dynobj, name);
                    if (sreloc == NULL)
                      {
                        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_anyway_with_flags (dynobj,
+                                                                    name,
+                                                                    flags);
                        if (sreloc == NULL
-                           || ! bfd_set_section_flags (dynobj, sreloc, flags)
                            || ! bfd_set_section_alignment (dynobj, sreloc, 2))
                          return FALSE;
                      }
@@ -2169,17 +2159,20 @@ microblaze_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
   struct elf32_mb_link_hash_table *htab;
 
   htab = elf32_mb_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   if (!htab->sgot && !create_got_section (dynobj, info))
     return FALSE;
 
   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
     return FALSE;
 
-  htab->splt = bfd_get_section_by_name (dynobj, ".plt");
-  htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
-  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
+  htab->splt = bfd_get_linker_section (dynobj, ".plt");
+  htab->srelplt = bfd_get_linker_section (dynobj, ".rela.plt");
+  htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
   if (!info->shared)
-    htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
+    htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
 
   if (!htab->splt || !htab->srelplt || !htab->sdynbss
       || (!info->shared && !htab->srelbss))
@@ -2249,6 +2242,8 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   bfd *dynobj;
 
   htab = elf32_mb_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later,
@@ -2389,14 +2384,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    /* When warning symbols are created, they **replace** the "real"
-       entry in the hash table, thus we never get to see the real
-       symbol in a hash traversal.  So look at it now.  */
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   info = (struct bfd_link_info *) dat;
   htab = elf32_mb_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
 
   if (htab->elf.dynamic_sections_created
       && h->plt.refcount > 0)
@@ -2559,6 +2550,9 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   bfd *ibfd;
 
   htab = elf32_mb_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = htab->elf.dynobj;
   BFD_ASSERT (dynobj != NULL);
 
@@ -2747,11 +2741,11 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
                                      struct elf_link_hash_entry *h,
                                      Elf_Internal_Sym *sym)
 {
-  bfd *dynobj;
   struct elf32_mb_link_hash_table *htab;
 
   htab = elf32_mb_hash_table (info);
-  dynobj = htab->elf.dynobj;
+  if (htab == NULL)
+    return FALSE;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
@@ -2875,8 +2869,7 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       BFD_ASSERT (h->dynindx != -1);
 
-      s = bfd_get_section_by_name (h->root.u.def.section->owner,
-                                   ".rela.bss");
+      s = bfd_get_linker_section (htab->elf.dynobj, ".rela.bss");
       BFD_ASSERT (s != NULL);
 
       rela.r_offset = (h->root.u.def.value
@@ -2889,9 +2882,9 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
     }
 
   /* Mark some specially defined symbols as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
-      || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
+  if (h == htab->elf.hdynamic
+      || h == htab->elf.hgot
+      || h == htab->elf.hplt)
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -2909,16 +2902,19 @@ microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
   struct elf32_mb_link_hash_table *htab;
 
   htab = elf32_mb_hash_table (info);
+  if (htab == NULL)
+    return FALSE;
+
   dynobj = htab->elf.dynobj;
 
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (htab->elf.dynamic_sections_created)
     {
       asection *splt;
       Elf32_External_Dyn *dyncon, *dynconend;
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
+      splt = bfd_get_linker_section (dynobj, ".plt");
       BFD_ASSERT (splt != NULL && sdyn != NULL);
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
@@ -2973,7 +2969,7 @@ microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
 
   /* Set the first entry in the global offset table to the address of
      the dynamic section.  */
-  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+  sgot = bfd_get_linker_section (dynobj, ".got.plt");
   if (sgot && sgot->size > 0)
     {
       if (sdyn == NULL)
@@ -3009,7 +3005,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
     {
       /* Common symbols less than or equal to -G nn bytes are automatically
         put into .sbss.  */
-      *secp = bfd_make_section_anyway (abfd, ".sbss");
+      *secp = bfd_make_section_old_way (abfd, ".sbss");
       if (*secp == NULL
           || ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
         return FALSE;
@@ -3025,6 +3021,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
 #define TARGET_BIG_NAME                "elf32-microblaze"
 
 #define ELF_ARCH               bfd_arch_microblaze
+#define ELF_TARGET_ID          MICROBLAZE_ELF_DATA
 #define ELF_MACHINE_CODE       EM_MICROBLAZE
 #define ELF_MACHINE_ALT1       EM_MICROBLAZE_OLD
 #define ELF_MAXPAGESIZE                0x4             /* 4k, if we ever have 'em.  */
This page took 0.029698 seconds and 4 git commands to generate.