summaryrefslogtreecommitdiff
path: root/bfd/elf32-avr.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2013-04-09 15:50:38 +0000
committerNick Clifton <nickc@redhat.com>2013-04-09 15:50:38 +0000
commitf43764d39f3718b3309ed9891413951f7553844d (patch)
tree991a9d4a9c54a112e8730b8c00f21f0ba7dfdc0a /bfd/elf32-avr.c
parent500f5daa531acffd877057da1f5630e53bb396df (diff)
downloadbinutils-redhat-f43764d39f3718b3309ed9891413951f7553844d.tar.gz
PR ld/12494
* bfd/elf32-avr.c: Consider all sections to determine if linker relaxation can safely delete a ret after a call/jmp
Diffstat (limited to 'bfd/elf32-avr.c')
-rw-r--r--bfd/elf32-avr.c151
1 files changed, 77 insertions, 74 deletions
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index a2d440129a..43100cd20f 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 <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;