PR ld/12494
authorNick Clifton <nickc@redhat.com>
Tue, 9 Apr 2013 15:50:38 +0000 (15:50 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 9 Apr 2013 15:50:38 +0000 (15:50 +0000)
* bfd/elf32-avr.c: Consider all sections to determine if linker
relaxation can safely delete a ret after a call/jmp

bfd/ChangeLog
bfd/elf32-avr.c

index 812e1ea..77c268f 100644 (file)
@@ -1,3 +1,9 @@
+2013-04-09  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
+
+       PR ld/12494
+       * bfd/elf32-avr.c: Consider all sections to determine if linker
+       relaxation can safely delete a ret after a call/jmp
+
 2013-04-09  Mingjie Xing  <mingjie.xing@gmail.com>
 
        * bfd.c (typedef bfd, Error reporting, Miscellaneous): Add
index a2d4401..43100cd 100644 (file)
@@ -1,7 +1,5 @@
 /* AVR-specific support for 32-bit ELF
-   Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011, 2012
-   Free Software Foundation, Inc.
+   Copyright 1999-2013 Free Software Foundation, Inc.
    Contributed by Denis Chertykov <denisc@overta.ru>
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -2138,6 +2136,7 @@ elf32_avr_relax_section (bfd *abfd,
                          irel->r_offset + insn_size;
                         Elf_Internal_Sym *isym, *isymend;
                         unsigned int sec_shndx;
+                       struct bfd_section *isec;
 
                         sec_shndx =
                          _bfd_elf_section_from_bfd_section (abfd, sec);
@@ -2188,80 +2187,85 @@ elf32_avr_relax_section (bfd *abfd,
                                }
                            }
                        }
-                       /* Now we check for relocations pointing to ret.  */
-                       {
-                         Elf_Internal_Rela *rel;
-                         Elf_Internal_Rela *relend;
 
-                         relend = elf_section_data (sec)->relocs
-                           + sec->reloc_count;
+                       /* Now we check for relocations pointing to ret.  */
+                       for (isec = abfd->sections; isec && deleting_ret_is_safe; isec = isec->next)
+                         {
+                           Elf_Internal_Rela *rel;
+                           Elf_Internal_Rela *relend;
+              
+                           rel = elf_section_data (isec)->relocs;
+                           if (rel == NULL)
+                             rel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
 
-                         for (rel = elf_section_data (sec)->relocs;
-                              rel < relend; rel++)
-                           {
-                             bfd_vma reloc_target = 0;
+                           relend = rel + isec->reloc_count;
 
-                             /* Read this BFD's local symbols if we haven't
-                                done so already.  */
-                             if (isymbuf == NULL && symtab_hdr->sh_info != 0)
-                               {
-                                 isymbuf = (Elf_Internal_Sym *)
-                                   symtab_hdr->contents;
-                                 if (isymbuf == NULL)
-                                   isymbuf = bfd_elf_get_elf_syms
-                                     (abfd,
-                                      symtab_hdr,
-                                      symtab_hdr->sh_info, 0,
-                                      NULL, NULL, NULL);
-                                 if (isymbuf == NULL)
+                           for (; rel && rel < relend; rel++)
+                             {
+                               bfd_vma reloc_target = 0;
+
+                               /* Read this BFD's local symbols if we haven't
+                                  done so already.  */
+                               if (isymbuf == NULL && symtab_hdr->sh_info != 0)
+                                 {
+                                   isymbuf = (Elf_Internal_Sym *)
+                                     symtab_hdr->contents;
+                                   if (isymbuf == NULL)
+                                     isymbuf = bfd_elf_get_elf_syms
+                                       (abfd,
+                                        symtab_hdr,
+                                        symtab_hdr->sh_info, 0,
+                                        NULL, NULL, NULL);
+                                   if (isymbuf == NULL)
+                                     break;
+                                 }
+
+                               /* Get the value of the symbol referred to
+                                  by the reloc.  */
+                               if (ELF32_R_SYM (rel->r_info)
+                                   < symtab_hdr->sh_info)
+                                 {
+                                   /* A local symbol.  */
+                                   asection *sym_sec;
+
+                                   isym = isymbuf
+                                     + ELF32_R_SYM (rel->r_info);
+                                   sym_sec = bfd_section_from_elf_index
+                                     (abfd, isym->st_shndx);
+                                   symval = isym->st_value;
+
+                                   /* If the reloc is absolute, it will not
+                                      have a symbol or section associated
+                                      with it.  */
+
+                                   if (sym_sec)
+                                     {
+                                       symval +=
+                                         sym_sec->output_section->vma
+                                         + sym_sec->output_offset;
+                                       reloc_target = symval + rel->r_addend;
+                                     }
+                                   else
+                                     {
+                                       reloc_target = symval + rel->r_addend;
+                                       /* Reference symbol is absolute.  */
+                                     }
+                                 }
+                               /* else ... reference symbol is extern.  */
+
+                               if (address_of_ret == reloc_target)
+                                 {
+                                   deleting_ret_is_safe = 0;
+                                   if (debug_relax)
+                                     printf ("ret from "
+                                             "rjmp/jmp ret sequence at address"
+                                             " 0x%x could not be deleted. ret"
+                                             " is target of a relocation.\n",
+                                             (int) address_of_ret);
                                    break;
-                               }
-
-                             /* Get the value of the symbol referred to
-                                by the reloc.  */
-                             if (ELF32_R_SYM (rel->r_info)
-                                 < symtab_hdr->sh_info)
-                               {
-                                 /* A local symbol.  */
-                                 asection *sym_sec;
-
-                                 isym = isymbuf
-                                   + ELF32_R_SYM (rel->r_info);
-                                 sym_sec = bfd_section_from_elf_index
-                                   (abfd, isym->st_shndx);
-                                 symval = isym->st_value;
-
-                                 /* If the reloc is absolute, it will not
-                                    have a symbol or section associated
-                                    with it.  */
-
-                                 if (sym_sec)
-                                   {
-                                     symval +=
-                                       sym_sec->output_section->vma
-                                       + sym_sec->output_offset;
-                                     reloc_target = symval + rel->r_addend;
-                                   }
-                                 else
-                                   {
-                                     reloc_target = symval + rel->r_addend;
-                                     /* Reference symbol is absolute.  */
-                                   }
-                               }
-                             /* else ... reference symbol is extern.  */
-
-                             if (address_of_ret == reloc_target)
-                               {
-                                 deleting_ret_is_safe = 0;
-                                 if (debug_relax)
-                                   printf ("ret from "
-                                           "rjmp/jmp ret sequence at address"
-                                           " 0x%x could not be deleted. ret"
-                                           " is target of a relocation.\n",
-                                           (int) address_of_ret);
-                               }
-                           }
-                       }
+                                 }
+                             }
+                         }
 
                        if (deleting_ret_is_safe)
                          {
@@ -2282,7 +2286,6 @@ elf32_avr_relax_section (bfd *abfd,
                            break;
                          }
                       }
-
                   }
               }
             break;