summaryrefslogtreecommitdiff
path: root/bfd/elf32-avr.c
diff options
context:
space:
mode:
authorAndrew Burgess <andrew.burgess@embecosm.com>2014-10-27 10:45:18 +0000
committerAndrew Burgess <andrew.burgess@embecosm.com>2014-11-03 20:34:13 +0000
commit931b79ccd6cc6ad4d8fe60a9c6de9443322a7cc8 (patch)
treea59a2d3b7bbc68c89bba19de32222dd0fb6d6bbe /bfd/elf32-avr.c
parenta12d0ffc72ee57f8db8b466fd9032360d8d15e09 (diff)
When relaxing, update size of symbols.
When performing linker relaxation, reduce the size of symbols that span the deleted bytes. This ensures that, for example, function symbols will have the correct size. bfd/ChangeLog: * elf32-avr.c (elf32_avr_relax_delete_bytes): During linker relaxation, reduce the size of symbols that span the deleted bytes. ld/ChangeLog: * testsuite/ld-avr/relax-02.d: Update to check size of symbols has changed. * testsuite/ld-avr/relax-03.d: Likewise.
Diffstat (limited to 'bfd/elf32-avr.c')
-rw-r--r--bfd/elf32-avr.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index 8498d29493..5aa3cf6e13 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -1881,10 +1881,22 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
isymend = isym + symtab_hdr->sh_info;
for (; isym < isymend; isym++)
{
- if (isym->st_shndx == sec_shndx
- && isym->st_value > addr
- && isym->st_value <= toaddr)
- isym->st_value -= count;
+ if (isym->st_shndx == sec_shndx)
+ {
+ if (isym->st_value > addr
+ && isym->st_value <= toaddr)
+ isym->st_value -= count;
+
+ if (isym->st_value <= addr
+ && isym->st_value + isym->st_size > addr)
+ {
+ /* If this assert fires then we have a symbol that ends
+ part way through an instruction. Does that make
+ sense? */
+ BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
+ isym->st_size -= count;
+ }
+ }
}
}
@@ -1898,11 +1910,22 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
struct elf_link_hash_entry *sym_hash = *sym_hashes;
if ((sym_hash->root.type == bfd_link_hash_defined
|| sym_hash->root.type == bfd_link_hash_defweak)
- && sym_hash->root.u.def.section == sec
- && sym_hash->root.u.def.value > addr
- && sym_hash->root.u.def.value <= toaddr)
+ && sym_hash->root.u.def.section == sec)
{
- sym_hash->root.u.def.value -= count;
+ if (sym_hash->root.u.def.value > addr
+ && sym_hash->root.u.def.value <= toaddr)
+ sym_hash->root.u.def.value -= count;
+
+ if (sym_hash->root.u.def.value <= addr
+ && (sym_hash->root.u.def.value + sym_hash->size > addr))
+ {
+ /* If this assert fires then we have a symbol that ends
+ part way through an instruction. Does that make
+ sense? */
+ BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
+ >= addr + count);
+ sym_hash->size -= count;
+ }
}
}