* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Don't build
[deliverable/binutils-gdb.git] / bfd / elf32-xstormy16.c
index 5be799e957b3eaa88baf1229fd2d6a6415014b5f..484acdded4713d8322615d5dc02bee58d5ad11f0 100644 (file)
@@ -1,5 +1,5 @@
 /* XSTORMY16-specific support for 32-bit ELF.
-   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/xstormy16.h"
+#include "libiberty.h"
 
 /* Forward declarations.  */
 static reloc_howto_type * xstormy16_reloc_type_lookup
@@ -245,26 +246,27 @@ static reloc_howto_type xstormy16_elf_howto_table2 [] =
 \f
 /* Map BFD reloc types to XSTORMY16 ELF reloc types.  */
 
-struct xstormy16_reloc_map
+typedef struct xstormy16_reloc_map
 {
-  bfd_reloc_code_real_type bfd_reloc_val;
-  unsigned int xstormy16_reloc_val;
-};
+  bfd_reloc_code_real_type  bfd_reloc_val;
+  unsigned int              xstormy16_reloc_val;
+  reloc_howto_type *        table;
+} reloc_map;
 
-static const struct xstormy16_reloc_map xstormy16_reloc_map [] =
+static const reloc_map xstormy16_reloc_map [] =
 {
-  { BFD_RELOC_NONE,                 R_XSTORMY16_NONE },
-  { BFD_RELOC_32,                   R_XSTORMY16_32 },
-  { BFD_RELOC_16,                   R_XSTORMY16_16 },
-  { BFD_RELOC_8,                    R_XSTORMY16_8 },
-  { BFD_RELOC_32_PCREL,             R_XSTORMY16_PC32 },
-  { BFD_RELOC_16_PCREL,             R_XSTORMY16_PC16 },
-  { BFD_RELOC_8_PCREL,              R_XSTORMY16_PC8 },
-  { BFD_RELOC_XSTORMY16_REL_12,      R_XSTORMY16_REL_12 },
-  { BFD_RELOC_XSTORMY16_24,        R_XSTORMY16_24 },
-  { BFD_RELOC_XSTORMY16_FPTR16,            R_XSTORMY16_FPTR16 },
-  { BFD_RELOC_VTABLE_INHERIT,       R_XSTORMY16_GNU_VTINHERIT },
-  { BFD_RELOC_VTABLE_ENTRY,         R_XSTORMY16_GNU_VTENTRY },
+  { BFD_RELOC_NONE,                 R_XSTORMY16_NONE,          xstormy16_elf_howto_table },
+  { BFD_RELOC_32,                   R_XSTORMY16_32,            xstormy16_elf_howto_table },
+  { BFD_RELOC_16,                   R_XSTORMY16_16,            xstormy16_elf_howto_table },
+  { BFD_RELOC_8,                    R_XSTORMY16_8,             xstormy16_elf_howto_table },
+  { BFD_RELOC_32_PCREL,             R_XSTORMY16_PC32,          xstormy16_elf_howto_table },
+  { BFD_RELOC_16_PCREL,             R_XSTORMY16_PC16,          xstormy16_elf_howto_table },
+  { BFD_RELOC_8_PCREL,              R_XSTORMY16_PC8,           xstormy16_elf_howto_table },
+  { BFD_RELOC_XSTORMY16_REL_12,     R_XSTORMY16_REL_12,        xstormy16_elf_howto_table },
+  { BFD_RELOC_XSTORMY16_24,        R_XSTORMY16_24,            xstormy16_elf_howto_table },
+  { BFD_RELOC_XSTORMY16_FPTR16,            R_XSTORMY16_FPTR16,        xstormy16_elf_howto_table },
+  { BFD_RELOC_VTABLE_INHERIT,       R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 },
+  { BFD_RELOC_VTABLE_ENTRY,         R_XSTORMY16_GNU_VTENTRY,   xstormy16_elf_howto_table2 },
 };
 
 static reloc_howto_type *
@@ -274,10 +276,16 @@ xstormy16_reloc_type_lookup (abfd, code)
 {
   unsigned int i;
 
-  for (i = sizeof (xstormy16_reloc_map) / sizeof (xstormy16_reloc_map[0]);
-       --i;)
-    if (xstormy16_reloc_map [i].bfd_reloc_val == code)
-      return & xstormy16_elf_howto_table [xstormy16_reloc_map[i].xstormy16_reloc_val];
+  for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
+    {
+      const reloc_map * entry;
+
+      entry = xstormy16_reloc_map + i;
+
+      if (entry->bfd_reloc_val == code)
+       return entry->table + (entry->xstormy16_reloc_val
+                              - entry->table[0].type);
+    }
   
   return NULL;
 }
@@ -492,6 +500,9 @@ xstormy16_relax_plt_check (h, xdata)
 {
   struct relax_plt_data *data = (struct relax_plt_data *) xdata;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h->plt.offset != (bfd_vma) -1)
     {
       bfd_vma address;
@@ -525,6 +536,9 @@ xstormy16_relax_plt_realloc (h, xdata)
 {
   bfd_vma *entry = (bfd_vma *) xdata;
 
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
   if (h->plt.offset != (bfd_vma) -1)
     {
       h->plt.offset = *entry;
@@ -577,32 +591,59 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
     {
       bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
       Elf_Internal_Shdr *symtab_hdr;
+      Elf_Internal_Shdr *shndx_hdr;
       Elf32_External_Sym *extsyms;
+      Elf_External_Sym_Shndx *shndx_buf;
       unsigned int idx;
 
       if (! local_plt_offsets)
        continue;
 
       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+      shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
 
       if (symtab_hdr->contents != NULL)
        extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
       else
        {
-         extsyms = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+         bfd_size_type amt;
+
+         amt = symtab_hdr->sh_info;
+         amt *= sizeof (Elf32_External_Sym);
+         extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
          if (extsyms == NULL)
            return false;
          if (bfd_seek (ibfd, symtab_hdr->sh_offset, SEEK_SET) != 0
-             || (bfd_bread (extsyms, symtab_hdr->sh_size, ibfd)
-                 != symtab_hdr->sh_size))
+             || bfd_bread ((PTR) extsyms, amt, ibfd) != amt)
            {
+           error_ret_free_extsyms:
              free (extsyms);
              return false;
            }
        }
 
+      shndx_buf = NULL;
+      if (shndx_hdr->sh_size != 0)
+       {
+         bfd_size_type amt;
+
+         amt = symtab_hdr->sh_info;
+         amt *= sizeof (Elf_External_Sym_Shndx);
+         shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+         if (shndx_buf == NULL)
+           goto error_ret_free_extsyms;
+         if (bfd_seek (ibfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+             || bfd_bread ((PTR) shndx_buf, amt, ibfd) != amt)
+           {
+             free (shndx_buf);
+             goto error_ret_free_extsyms;
+           }
+         shndx_hdr->contents = (bfd_byte *) shndx_buf;
+       }
+
       for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
        {
+         Elf_External_Sym_Shndx *shndx;
          Elf_Internal_Sym isym;
          asection *tsec;
          bfd_vma address;
@@ -610,15 +651,18 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
          if (local_plt_offsets[idx] == (bfd_vma) -1)
            continue;
 
-         bfd_elf32_swap_symbol_in (ibfd, extsyms + idx, &isym);
+         shndx = shndx_buf;
+         if (shndx != NULL)
+           shndx += idx;
+         bfd_elf32_swap_symbol_in (ibfd, extsyms + idx, shndx, &isym);
          if (isym.st_shndx == SHN_UNDEF)
            continue;
-         else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
-           tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx);
          else if (isym.st_shndx == SHN_ABS)
            tsec = bfd_abs_section_ptr;
+         else if (isym.st_shndx == SHN_COMMON)
+           tsec = bfd_com_section_ptr;
          else
-           continue;
+           tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx);
 
          address = (tsec->output_section->vma
                     + tsec->output_offset
@@ -631,7 +675,10 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
            }
        }
 
-      if (symtab_hdr->contents != extsyms)
+      if (shndx_buf != NULL)
+       free (shndx_buf);
+
+      if ((Elf32_External_Sym *) symtab_hdr->contents != extsyms)
         free (extsyms);
     }
 
@@ -1024,13 +1071,7 @@ xstormy16_elf_gc_mark_hook (abfd, info, rel, h, sym)
     }
   else
     {
-      if (!(elf_bad_symtab (abfd)
-           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-               && sym->st_shndx != SHN_COMMON))
-       {
-         return bfd_section_from_elf_index (abfd, sym->st_shndx);
-       }
+      return bfd_section_from_elf_index (abfd, sym->st_shndx);
     }
 
   return NULL;
This page took 0.034159 seconds and 4 git commands to generate.