diff options
author | Denis Chertykov <chertykov@gmail.com> | 2016-06-09 19:17:43 +0300 |
---|---|---|
committer | Denis Chertykov <chertykov@gmail.com> | 2016-06-09 19:17:43 +0300 |
commit | 5c41dbc302c2dd87e201e4fd1d9ae3186f6e51a0 (patch) | |
tree | f97034bca2d7f3fa8d45fc6b6931d9117a6de79e /bfd/elf32-avr.c | |
parent | 1857fe72aff6f254217956d141bff4b9ca454bc5 (diff) | |
download | gdb-5c41dbc302c2dd87e201e4fd1d9ae3186f6e51a0.zip gdb-5c41dbc302c2dd87e201e4fd1d9ae3186f6e51a0.tar.gz gdb-5c41dbc302c2dd87e201e4fd1d9ae3186f6e51a0.tar.bz2 |
Fix PR 20221 - adjust syms and relocs only if relax shrunk section.
This patch fixes an edge case in linker relaxation that causes symbol
values to be computed incorrectly in the presence of align directives
in input source code.
bfd/
* elf32-avr.c (elf32_avr_relax_delete_bytes): Adjust syms
and relocs only if shrinking occurred.
ld/
* testsuite/ld-avr/avr-prop-5.d: New.
* testsuite/ld-avr/avr-prop-5.s: New.
Diffstat (limited to 'bfd/elf32-avr.c')
-rw-r--r-- | bfd/elf32-avr.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index d463d78..b95e251 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -1828,6 +1828,7 @@ elf32_avr_relax_delete_bytes (bfd *abfd, unsigned int symcount; struct avr_relax_info *relax_info; struct avr_property_record *prop_record = NULL; + bfd_boolean did_shrink = FALSE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); @@ -1863,10 +1864,16 @@ elf32_avr_relax_delete_bytes (bfd *abfd, /* Actually delete the bytes. */ if (toaddr - addr - count > 0) - memmove (contents + addr, contents + addr + count, - (size_t) (toaddr - addr - count)); + { + memmove (contents + addr, contents + addr + count, + (size_t) (toaddr - addr - count)); + did_shrink = TRUE; + } if (prop_record == NULL) - sec->size -= count; + { + sec->size -= count; + did_shrink = TRUE; + } else { /* Use the property record to fill in the bytes we've opened up. */ @@ -1885,6 +1892,11 @@ elf32_avr_relax_delete_bytes (bfd *abfd, prop_record->data.align.preceding_deleted += count; break; }; + /* If toaddr == (addr + count), then we didn't delete anything, yet + we fill count bytes backwards from toaddr. This is still ok - we + end up overwriting the bytes we would have deleted. We just need + to remember we didn't delete anything i.e. don't set did_shrink, + so that we don't corrupt reloc offsets or symbol values.*/ memset (contents + toaddr - count, fill, count); /* Adjust the TOADDR to avoid moving symbols located at the address @@ -1892,6 +1904,9 @@ elf32_avr_relax_delete_bytes (bfd *abfd, toaddr -= count; } + if (!did_shrink) + return TRUE; + /* Adjust all the reloc addresses. */ for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) { |