Fix issues with diff relocs that have a negative value
i.e. sym2 - sym1 where sym2 is lesser than sym1.
The assembler generates a diff reloc with symbol as start of section
and addend as sym2 offset, and encodes assembly time difference at
the reloc offset.
The existing relaxation logic adjusts addends if the relaxed insn lies
between symbol and addend. That doesn't work for diff relocs where
sym2 is less than sym1 *and* the relaxed insn happens to be between
sym2 and sym1.
Fix the problems by
1. Using signed handling of the difference value (bfd_signed_vma instead
of bfd_vma, bfd_{get,set}_signed_xxx instead of bfd_{get,set}_xxx).
2. Not assuming sym2 is bigger than sym1. It instead computes the actual
addresses and sets the lower and higher addresses as start and end
addresses respectively and then sees if insn is between start and end.
3. Creating a new function elf32_avr_adjust_reloc_if_spans_insn to
centralize reloc adjustment, and ensuring diff relocs get adjusted
correctly even if their sym + addend doesn't overlap a relaxed insn.
It also removes a redundant variable did_pad. It is never set if
did_shrink is TRUE, and the code does a early return if did_shrink is
FALSE.
bfd/ChangeLog
2016-11-15 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
PR ld/20789
* bfd/elf32-avr.c (elf32_avr_adjust_diff_reloc_value): Do signed
manipulation of diff value, and don't assume sym2 is less than sym1.
(elf32_avr_adjust_reloc_if_spans_insn): New function.
(elf32_avr_relax_delete_bytes): Use elf32_avr_adjust_diff_reloc_value,
and remove redundant did_pad.
ld/ChangeLog
2016-11-15 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
PR ld/20789
* ld/testsuite/ld-avr/pr20789.d: New test.
* ld/testsuite/ld-avr/pr20789.s: New test.
Prior to the patch, addends for relocs were being adjusted even if
they went beyond an alignment boundary. This is wrong - to
preserve alignment constraints, the relaxation logic adds as many padding
bytes at the alignment boundary as was deleted, so addends beyond the
boundary should not be adjusted. avr-prop-7.s reproduces this
scenario.
Also, prior to this patch, the relaxation logic assumed that the addr
parameter pointed to the middle of the instruction to be deleted, and
that addr - count would therefore be the shrinked instruction's
address. This is true when actually shrinking instructions.
The alignment constraints handling logic also invokes the same logic
though, with addr as the starting offset of padding bytes and
with count as the number of bytes to be deleted. Calculating the
shrinked insn's address as addr - count is obviously wrong in this
case - that offset would point to count bytes before the last
non-padded byte. avr-prop-8.s reproduces this scenario.
To fix scenario 1, the patch adds an additional check to ensure reloc addends
aren't adjusted if they cross a shrink boundary. The shrink boundary
is either the section size or an alignment boundary. Addends pointing
at an alignment boundary don't need to be adjusted, as padding would
occur and keep the boundary the same. Addends pointing at section size
need to be adjusted though, as no padding occurs and the section size
itself would get decremented. The patch records whether padding
occured (did_pad) and uses that to detect and handle this condition.
To fix scenario 2, the patch adds an additional parameter
(delete_shrinks_insn) to elf32_avr_relax_delete_bytes to distinguish
instruction bytes deletion from padding bytes deletion. It then uses that to
correctly set shrinked_insn_address.
bfd/ChangeLog:
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.
ld/ChangeLog:
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.
This patch fixes another edge case related to alignment property
records - reloc offsets adjacent to property record offsets were not
getting adjusted during relaxation.
bfd/
PR ld/20254
* elf32-avr.c (elf32_avr_relax_delete_bytes): Adjust reloc
offsets until reloc_toaddr.
ld/
PR ld/20254
* testsuite/ld-avr/avr-prop-6.d: New test.
* testsuite/ld-avr/avr-prop-6.s: New test.
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.
This patch adds default data address space origin (0x800000) to the symbol addresses.
when disassemble lds/sts instructions. So that symbol names shall be printed in comments
for lds/sts instructions disassemble.
ld/
* testsuite/ld-avr/lds-mega.d: New test.
* testsuite/ld-avr/lds-mega.s: New test source.
* testsuite/ld-avr/lds-tiny.d: New test.
* testsuite/ld-avr/lds-tiny.s: New test source.
opcodes/
* avr-dis.c (avr_operand): Add default data address space origin (0x800000) to the
address and set as symbol address for LDS/ STS immediate operands.
When generating relocation (tc_gen_reloc) 32 bit relocation fixup
is changed to new 32 bit PC relative relocation if the fixup has pc-relative
flag set.
bfd/ChangeLog
2015-07-06 Pitchumani Sivanupandi <pitchumani.s@atmel.com>
* elf32-avr.c: Add 32 bit PC relative relocation for AVR target.
gas/ChangeLog
2015-07-06 Pitchumani Sivanupandi <pitchumani.s@atmel.com>
* config/tc-avr.c (tc_gen_reloc): Change 32 bit relocation to
32 bit PC relative and update offset if the fixup is pc-relative.
* config/tc-avr.h (DIFF_EXPR_OK): Define to enable PC relative diff
relocs.
gas/testsuite/ChangeLog
2015-07-06 Pitchumani Sivanupandi <pitchumani.s@atmel.com>
* gas/avr/pc-relative-reloc.d: New test for 32 bit pc relative reloc.
* gas/avr/per-function-debugline.s: New test source.
include/ChangeLog
2015-07-06 Pitchumani Sivanupandi <pitchumani.s@atmel.com>
* elf/avr.h: Add new 32 bit PC relative relocation.
ld/testsuite/ChangeLog
2015-07-06 Pitchumani Sivanupandi <pitchumani.s@atmel.com>
* ld-avr/gc-section-debugline.d: New test.
* ld-avr/per-function-debugline.s: Source for new test.
Make use of the data held within the .avr.prop section during linker
relaxation in order to maintain the properties of the .org and .align
directives.
In relation to the .align directives, if enough bytes are deleted before
a .align directive then the alignment can be moved while still
maintaining the alignment requirement.
bfd/ChangeLog:
* elf32-avr.c (struct elf_avr_section_data): New structure.
(struct avr_relax_info): New structure.
(elf_avr_new_section_hook): New function.
(struct elf_avr_section_data): Add relax_info.
(get_avr_relax_info): New function.
(init_avr_relax_info): New function.
(elf32_avr_relax_delete_bytes): Find next property record before
deleting bytes. When deleting don't move bytes beyond the next
property record.
(avr_elf32_assign_records_to_section): New function.
(avr_property_record_compare): New function.
(avr_load_all_property_sections): New function.
(elf32_avr_relax_section): Load property data. After relaxing the
section, move any .align directives that have enough deleted bytes
before them.
(bfd_elf32_new_section_hook): Define.
ld/testsuite/ChangeLog:
* ld-avr/avr-prop-1.d: New file.
* ld-avr/avr-prop-1.s: New file.
* ld-avr/avr-prop-2.d: New file.
* ld-avr/avr-prop-2.s: New file.
* ld-avr/avr-prop-3.d: New file.
* ld-avr/avr-prop-3.s: New file.
* ld-avr/avr-prop-4.d: New file.
* ld-avr/avr-prop-4.s: New file.
ld * scripttempl/avr.sc: Add new user_signatures region. Define and Use
symbols for all region lengths.
* scripttempl/avrtiny.sc: Define and use symbols for all region lengths.
testsuite * ld-avr/region_overflow.d: New test.
* ld-avr/region_overflow.s: Likewise.
Have the assembler prepare for linker relaxation by default. This
means that users will be able to make use of linker relaxation without
having to adjust the assembler flags, this can make life easier when
compiling libraries.
Having this on by default in the assembler should make no difference to
the assembler code produced, however, some of the debug information will
be slightly less compressed.
A few tests needed to be updated as a result of this change as they
relied on linker relaxation support being off by default.
I've tightened up the definition of which sections can be relaxed on AVR
as part of this commit, the assembler used to think that all
non-debugging sections could be relaxed, when in reality only code
sections can be relaxed for AVR. The previous definition was not
dangerous, just over cautious. The new tighter definition allows an
extra test (gas/testsuite/gas/all/forward.d) to continue to pass.
gas/ChangeLog:
* config/tc-avr.c (struct avr_opt_s): Change link_relax to
no_link_relax, extend comment.
(enum options): Add new OPTION_NO_LINK_RELAX.
(md_longopts): Add entry for -mno-link-relax.
(md_parse_option): Handle OPTION_NO_LINK_RELAX, and update
OPTION_LINK_RELAX.
(md_begin): Initialise linkrelax from no_link_relax.
(md_show_usage): Include -mno-link-relax option.
(relaxable_section): Only allocatable code sections can be
relaxed.
* config/tc-avr.h (TC_LINKRELAX_FIXUP): Define.
gas/testsuite/ChangeLog:
* gas/all/gas.exp: Test will not pass on AVR due to linker
relaxation support.
* gas/avr/noreloc_withoutrelax.d: Add -mno-link-relax option.
* gas/avr/link-relax-elf-flag-clear.d: Likewise.
ld/testsuite/ChangeLog:
* ld/testsuite/ld-avr/relax-elf-flags-02.d: Add -mno-link-relax
option.
* ld/testsuite/ld-avr/relax-elf-flags-03.d: Likewise.
* ld/testsuite/ld-avr/relax-elf-flags-04.d: Likewise.
* ld/testsuite/ld-avr/relax-elf-flags-05.d: Likewise.
* ld/testsuite/ld-avr/relax-elf-flags-06.d: Likewise.
The AVR target has an elf header flag to indicate if an object was
assembler ready for linker relaxation. If a partial link is performed
then it is important that the link-relax flag in the output object is
set correctly, otherwise, during the final link, we might try to perform
linker relaxation on code that was not assembled suitably.
As the link-relax elf header covers the entire object file we must be
conservative when setting the flag in the output object, so, for a
partial link, any input object that does not have the link-relax flag
set will cause the output object to also not have the link-relax flag
set.
This conservative approach could be softened in future, we only need to
disable the link relax flag if an input file is not marked link-relax
ready, and the input file contains a relaxable section. However, I've
left this optimisation for a later day.
For the final link I've overloaded the use of the link-relax elf header
flag, in a final executable, the flag now indicates if the executable
was built with linker relaxation on or not.
ld/ChangeLog:
* emultempl/avrelf.em: Add include of elf/avr.h.
(avr_finish): New function.
(LDEMUL_FINISH): Added.
ld/testsuite/ChangeLog:
* ld-avr/relax-elf-flags-01.d: New file.
* ld-avr/relax-elf-flags-02.d: New file.
* ld-avr/relax-elf-flags-03.d: New file.
* ld-avr/relax-elf-flags-04.d: New file.
* ld-avr/relax-elf-flags-05.d: New file.
* ld-avr/relax-elf-flags-06.d: New file.
* ld-avr/relax-elf-flags-07.d: New file.
* ld-avr/relax-elf-flags-08.d: New file.
* ld-avr/relax-elf-flags-a.s: New file.
* ld-avr/relax-elf-flags-b.s: New file.
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.
Symbols at the very end of a section were not being updated correctly
when linker relaxation takes place due to the use of '<' instead of
'<='. Added a couple of tests to cover this behaviour.
bfd/ChangeLog:
* elf32-avr.c (elf32_avr_relax_delete_bytes): Modify symbols
located at the very end of the section.
ld/ChangeLog:
* ld/testsuite/ld-avr/relax-02.d: New file.
* ld/testsuite/ld-avr/relax-02.s: New file.
* ld/testsuite/ld-avr/relax-03.d: New file.
* ld/testsuite/ld-avr/relax-03.s: New file.