PR 9827
[deliverable/binutils-gdb.git] / bfd / elf32-avr.c
index 33d52269fd8e33b7c5d7f6d1ad1c16ca5d4eca27..afcef18aa30726c14297e649b71988d3c9a216a1 100644 (file)
@@ -1,5 +1,5 @@
 /* AVR-specific support for 32-bit ELF
-   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
+   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008
    Free Software Foundation, Inc.
    Contributed by Denis Chertykov <denisc@overta.ru>
 
@@ -7,7 +7,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,
@@ -20,8 +20,8 @@
    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/avr.h"
@@ -688,6 +688,22 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (elf_avr_howto_table) / sizeof (elf_avr_howto_table[0]);
+       i++)
+    if (elf_avr_howto_table[i].name != NULL
+       && strcasecmp (elf_avr_howto_table[i].name, r_name) == 0)
+      return &elf_avr_howto_table[i];
+
+  return NULL;
+}
+
 /* Set the howto pointer for an AVR ELF reloc.  */
 
 static void
@@ -713,7 +729,7 @@ elf32_avr_check_relocs (bfd *abfd,
                        const Elf_Internal_Rela *relocs)
 {
   Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+  struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
 
@@ -722,9 +738,6 @@ elf32_avr_check_relocs (bfd *abfd,
 
   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);
-  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++)
@@ -841,10 +854,11 @@ avr_final_link_relocate (reloc_howto_type *                 howto,
        {
           /* Relative distance is too large.  */
 
-         /* Always apply WRAPAROUND for avr2 and avr4.  */
+         /* Always apply WRAPAROUND for avr2, avr25, and avr4.  */
          switch (bfd_get_mach (input_bfd))
            {
            case bfd_mach_avr2:
+           case bfd_mach_avr25:
            case bfd_mach_avr4:
              break;
 
@@ -1283,10 +1297,22 @@ bfd_elf_avr_final_write_processing (bfd *abfd,
       val = E_AVR_MACH_AVR1;
       break;
 
+    case bfd_mach_avr25:
+      val = E_AVR_MACH_AVR25;
+      break;
+
     case bfd_mach_avr3:
       val = E_AVR_MACH_AVR3;
       break;
 
+    case bfd_mach_avr31:
+      val = E_AVR_MACH_AVR31;
+      break;
+
+    case bfd_mach_avr35:
+      val = E_AVR_MACH_AVR35;
+      break;
+
     case bfd_mach_avr4:
       val = E_AVR_MACH_AVR4;
       break;
@@ -1295,6 +1321,10 @@ bfd_elf_avr_final_write_processing (bfd *abfd,
       val = E_AVR_MACH_AVR5;
       break;
 
+    case bfd_mach_avr51:
+      val = E_AVR_MACH_AVR51;
+      break;
+
     case bfd_mach_avr6:
       val = E_AVR_MACH_AVR6;
       break;
@@ -1329,10 +1359,22 @@ elf32_avr_object_p (bfd *abfd)
          e_set = bfd_mach_avr1;
          break;
 
+       case E_AVR_MACH_AVR25:
+         e_set = bfd_mach_avr25;
+         break;
+
        case E_AVR_MACH_AVR3:
          e_set = bfd_mach_avr3;
          break;
 
+       case E_AVR_MACH_AVR31:
+         e_set = bfd_mach_avr31;
+         break;
+
+       case E_AVR_MACH_AVR35:
+         e_set = bfd_mach_avr35;
+         break;
+
        case E_AVR_MACH_AVR4:
          e_set = bfd_mach_avr4;
          break;
@@ -1341,6 +1383,10 @@ elf32_avr_object_p (bfd *abfd)
          e_set = bfd_mach_avr5;
          break;
 
+       case E_AVR_MACH_AVR51:
+         e_set = bfd_mach_avr51;
+         break;
+
        case E_AVR_MACH_AVR6:
          e_set = bfd_mach_avr6;
          break;
@@ -2021,7 +2067,8 @@ elf32_avr_relax_section (bfd *abfd,
                         /* Check for local symbols.  */
                         isym = (Elf_Internal_Sym *) symtab_hdr->contents;
                         isymend = isym + symtab_hdr->sh_info;
-                        for (; isym < isymend; isym++)
+                       /* PR 6019: There may not be any local symbols.  */
+                        for (; isym != NULL && isym < isymend; isym++)
                          {
                            if (isym->st_value == section_offset_of_ret_insn
                                && isym->st_shndx == sec_shndx)
@@ -2576,6 +2623,7 @@ get_local_syms (bfd *input_bfd, struct bfd_link_info *info)
   unsigned int bfd_indx;
   Elf_Internal_Sym *local_syms, **all_local_syms;
   struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info);
+  bfd_size_type amt;
 
   if (htab == NULL)
     return -1;
@@ -2583,7 +2631,7 @@ get_local_syms (bfd *input_bfd, struct bfd_link_info *info)
   /* We want to read in symbol extension records only once.  To do this
      we need to read in the local symbols in parallel and save them for
      later use; so hold pointers to the local symbols in an array.  */
-  bfd_size_type amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count;
+  amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count;
   all_local_syms = bfd_zmalloc (amt);
   htab->all_local_syms = all_local_syms;
   if (all_local_syms == NULL)
@@ -2744,15 +2792,20 @@ elf32_avr_size_stubs (bfd *output_bfd,
                       /* It's a local symbol.  */
                       Elf_Internal_Sym *sym;
                       Elf_Internal_Shdr *hdr;
+                     unsigned int shndx;
 
                       sym = local_syms + r_indx;
-                      hdr = elf_elfsections (input_bfd)[sym->st_shndx];
-                      sym_sec = hdr->bfd_section;
                       if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
                         sym_value = sym->st_value;
-                      destination = (sym_value + irela->r_addend
-                                     + sym_sec->output_offset
-                                     + sym_sec->output_section->vma);
+                     shndx = sym->st_shndx;
+                     if (shndx < elf_numsections (input_bfd))
+                       {
+                         hdr = elf_elfsections (input_bfd)[shndx];
+                         sym_sec = hdr->bfd_section;
+                         destination = (sym_value + irela->r_addend
+                                        + sym_sec->output_offset
+                                        + sym_sec->output_section->vma);
+                       }
                     }
                   else
                     {
This page took 0.027772 seconds and 4 git commands to generate.