From 8d6a12ee15ed1ddd7c50f09015b9fdc13cb151e2 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 9 Apr 2013 15:50:38 +0000 Subject: [PATCH] PR ld/12494 * bfd/elf32-avr.c: Consider all sections to determine if linker relaxation can safely delete a ret after a call/jmp --- bfd/ChangeLog | 6 +++ bfd/elf32-avr.c | 151 +++++++++++++++++++++++++++++--------------------------- 2 files changed, 83 insertions(+), 74 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 812e1ea..77c268f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2013-04-09 Senthil Kumar Selvaraj + + 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 * bfd.c (typedef bfd, Error reporting, Miscellaneous): Add diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index a2d4401..43100cd 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -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 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; -- 2.7.4