diff options
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/elf32-avr.c | 40 | ||||
-rw-r--r-- | ld/ChangeLog | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-avr/avr-prop-7.d | 15 | ||||
-rw-r--r-- | ld/testsuite/ld-avr/avr-prop-7.s | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-avr/avr-prop-8.d | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-avr/avr-prop-8.s | 7 |
7 files changed, 94 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 71ec02f..56012b4 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2016-09-02 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + PR ld/20545 + * elf32-avr.c (elf32_avr_relax_delete_bytes): Add parameter + delete_shrinks_insn. Modify computation of shrinked_insn_address. + Compute shrink_boundary and adjust addend only if + addend_within_shrink_boundary. + (elf32_avr_relax_section): Modify calls to + elf32_avr_relax_delete_bytes to pass extra parameter. + 2016-09-01 Thomas Preud'homme <thomas.preudhomme@arm.com> * elf32-arm.c (cmse_entry_fct_p): Store instruction encoding in an diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index a0a5c69..eea76a4 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -1808,13 +1808,17 @@ elf32_avr_adjust_diff_reloc_value (bfd *abfd, /* Delete some bytes from a section while changing the size of an instruction. The parameter "addr" denotes the section-relative offset pointing just behind the shrinked instruction. "addr+count" point at the first - byte just behind the original unshrinked instruction. */ + byte just behind the original unshrinked instruction. If delete_shrinks_insn + is FALSE, we are deleting redundant padding bytes from relax_info prop + record handling. In that case, addr is section-relative offset of start + of padding, and count is the number of padding bytes to delete. */ static bfd_boolean elf32_avr_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, - int count) + int count, + bfd_boolean delete_shrinks_insn) { Elf_Internal_Shdr *symtab_hdr; unsigned int sec_shndx; @@ -1829,6 +1833,7 @@ elf32_avr_relax_delete_bytes (bfd *abfd, struct avr_relax_info *relax_info; struct avr_property_record *prop_record = NULL; bfd_boolean did_shrink = FALSE; + bfd_boolean did_pad = FALSE; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); @@ -1909,6 +1914,7 @@ elf32_avr_relax_delete_bytes (bfd *abfd, 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); + did_pad = TRUE; /* Adjust the TOADDR to avoid moving symbols located at the address of the property record, which has not moved. */ @@ -1965,7 +1971,9 @@ elf32_avr_relax_delete_bytes (bfd *abfd, continue; shrinked_insn_address = (sec->output_section->vma - + sec->output_offset + addr - count); + + sec->output_offset + addr); + if (delete_shrinks_insn) + shrinked_insn_address -= count; irel = elf_section_data (isec)->relocs; /* PR 12161: Read in the relocs for this section if necessary. */ @@ -2002,6 +2010,13 @@ elf32_avr_relax_delete_bytes (bfd *abfd, a symbol or section associated with it. */ if (sym_sec == sec) { + /* If there is an alignment boundary, we only need to + adjust addends that end up below the boundary. */ + bfd_vma shrink_boundary = (reloc_toaddr + + sec->output_section->vma + + sec->output_offset); + bfd_boolean addend_within_shrink_boundary = FALSE; + symval += sym_sec->output_section->vma + sym_sec->output_offset; @@ -2015,8 +2030,17 @@ elf32_avr_relax_delete_bytes (bfd *abfd, (unsigned int) (symval + irel->r_addend), (unsigned int) shrinked_insn_address); + /* If we padded bytes, then the boundary didn't change, + so there's no need to adjust addends pointing at the boundary. + If we didn't pad, then we actually shrank the boundary, so + addends pointing at the boundary need to be adjusted too. */ + addend_within_shrink_boundary = did_pad + ? ((symval + irel->r_addend) < shrink_boundary) + : ((symval + irel->r_addend) <= shrink_boundary); + if (symval <= shrinked_insn_address - && (symval + irel->r_addend) > shrinked_insn_address) + && (symval + irel->r_addend) > shrinked_insn_address + && addend_within_shrink_boundary) { if (elf32_avr_is_diff_reloc (irel)) { @@ -2648,7 +2672,8 @@ elf32_avr_relax_section (bfd *abfd, { /* Delete two bytes of data. */ if (!elf32_avr_relax_delete_bytes (abfd, sec, - irel->r_offset + 2, 2)) + irel->r_offset + 2, 2, + TRUE)) goto error_return; /* That will change things, so, we should relax again. @@ -2972,7 +2997,8 @@ elf32_avr_relax_section (bfd *abfd, /* Delete two bytes of data. */ if (!elf32_avr_relax_delete_bytes (abfd, sec, - irel->r_offset + insn_size, 2)) + irel->r_offset + insn_size, 2, + TRUE)) goto error_return; /* That will change things, so, we should relax @@ -3040,7 +3066,7 @@ elf32_avr_relax_section (bfd *abfd, record->offset -= count; elf32_avr_relax_delete_bytes (abfd, sec, addr - count, - count); + count, FALSE); *again = TRUE; } } diff --git a/ld/ChangeLog b/ld/ChangeLog index 8ef9e51..a13c8d1 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2016-09-02 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + PR ld/20545 + * testsuite/ld-avr/avr-prop-7.d: New test. + * testsuite/ld-avr/avr-prop-7.s: New test. + * testsuite/ld-avr/avr-prop-8.d: New test. + * testsuite/ld-avr/avr-prop-8.s: New test. + 2016-09-02 H.J. Lu <hongjiu.lu@intel.com> * testsuite/ld-elf/pr20513c.d: Limit to *-*-linux* and *-*-gnu* diff --git a/ld/testsuite/ld-avr/avr-prop-7.d b/ld/testsuite/ld-avr/avr-prop-7.d new file mode 100644 index 0000000..9f2cea9 --- /dev/null +++ b/ld/testsuite/ld-avr/avr-prop-7.d @@ -0,0 +1,15 @@ +#name: AVR .avr.prop, AVR_7_PCREL after align +#as: -mavrxmega2 -mlink-relax +#ld: -mavrxmega2 --relax +#source: avr-prop-7.s +#objdump: -S +#target: avr-*-* + +#... +00000000 <__ctors_end>: + 0: 04 d0 rcall .+8 ; 0xa <foo> + 2: 00 00 nop + 4: 00 00 nop + 6: 86 e0 ldi r24, 0x06 ; 6 + 8: f0 f7 brcc .-4 ; 0x6 <__ctors_end\+0x6> +#... diff --git a/ld/testsuite/ld-avr/avr-prop-7.s b/ld/testsuite/ld-avr/avr-prop-7.s new file mode 100644 index 0000000..38276ba --- /dev/null +++ b/ld/testsuite/ld-avr/avr-prop-7.s @@ -0,0 +1,8 @@ + call foo + nop + .p2align 1 + nop +.L618: + ldi r24,lo8(6) + brsh .L618 +foo: nop diff --git a/ld/testsuite/ld-avr/avr-prop-8.d b/ld/testsuite/ld-avr/avr-prop-8.d new file mode 100644 index 0000000..2905f98 --- /dev/null +++ b/ld/testsuite/ld-avr/avr-prop-8.d @@ -0,0 +1,13 @@ +#name: AVR .avr.prop, AVR_7_PCREL just before align +#as: -mavrxmega2 -mlink-relax +#ld: -mavrxmega2 --relax +#source: avr-prop-8.s +#objdump: -S +#target: avr-*-* + +#... +00000000 <__ctors_end>: + 0: ff cf rjmp .-2 ; 0x0 <__ctors_end> + 2: fe df rcall .-4 ; 0x0 <__ctors_end> + 4: f8 f7 brcc .-2 ; 0x4 <__ctors_end\+0x4> +#... diff --git a/ld/testsuite/ld-avr/avr-prop-8.s b/ld/testsuite/ld-avr/avr-prop-8.s new file mode 100644 index 0000000..34554f2 --- /dev/null +++ b/ld/testsuite/ld-avr/avr-prop-8.s @@ -0,0 +1,7 @@ +foo: + jmp foo + call foo +.L1: + brsh .L1 +.p2align 1 + nop |