PR ld/12494
* bfd/elf32-avr.c: Consider all sections to determine if linker relaxation can safely delete a ret after a call/jmp
This commit is contained in:
parent
4d13caa0b9
commit
8d6a12ee15
2 changed files with 82 additions and 73 deletions
|
@ -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
|
||||
|
|
149
bfd/elf32-avr.c
149
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;
|
||||
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);
|
||||
|
||||
relend = elf_section_data (sec)->relocs
|
||||
+ sec->reloc_count;
|
||||
relend = rel + isec->reloc_count;
|
||||
|
||||
for (rel = elf_section_data (sec)->relocs;
|
||||
rel < relend; rel++)
|
||||
{
|
||||
bfd_vma reloc_target = 0;
|
||||
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)
|
||||
/* 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;
|
||||
|
|
Loading…
Reference in a new issue