diff options
author | Andrew Burgess <andrew.burgess@embecosm.com> | 2014-10-27 10:45:18 +0000 |
---|---|---|
committer | Andrew Burgess <andrew.burgess@embecosm.com> | 2014-11-03 20:34:13 +0000 |
commit | 931b79ccd6cc6ad4d8fe60a9c6de9443322a7cc8 (patch) | |
tree | a59a2d3b7bbc68c89bba19de32222dd0fb6d6bbe /bfd/elf32-avr.c | |
parent | a12d0ffc72ee57f8db8b466fd9032360d8d15e09 (diff) | |
download | gdb-931b79ccd6cc6ad4d8fe60a9c6de9443322a7cc8.zip gdb-931b79ccd6cc6ad4d8fe60a9c6de9443322a7cc8.tar.gz gdb-931b79ccd6cc6ad4d8fe60a9c6de9443322a7cc8.tar.bz2 |
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.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index 8498d29..5aa3cf6 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; + } } } |