This appears to be similar to https://www.sourceware.org/bugzilla/show_bug.cgi?id=20545 However, as that one is "resolved fixed", opening a new bug instead. In a setup with an assembler file requesting alignment for a particular block of code, the ZH value for that block of code is miscalculated when linker relaxations are requested. Without linker relaxations, the correct code is generated. Testcode: .rept 300 call test .endr clr ZL ldi ZH,hi8(matrix) 1:rjmp 1b test: ret .balign 256 matrix: .byte 1,2,3,4,5 Compiler (i.e. combined assembler+linker) commandline: avr-gcc main.S -o main.elf -mmcu=atmega328 -nostartfiles -mrelax Without -mrelax, ZH is (correctly) loaded with 5, as matrix is located at 0x500. With -mrelax, as there are 300 CALL instructions turned into RCALLs, matrix is located at 0x300, yet the value loaded into ZH becomes 2 rather than 3. Cross reference: https://www.mikrocontroller.net/topic/528827 (German-language forum discussion the bug has been reported to originally.)
Hi Joerg, The root cause for this problem is the assembler. When it assembles the test file it created a relocation for the LDI instruction which references the .text section: % objdump -dr main.o [...] 4b2: f0 e0 ldi r31, 0x00 ; 0 4b2: R_AVR_HI8_LDI .text+0x500 So when the relaxation happens the code adjusts the relocation eventually ending up with .text+0x2ab which then translates into a value of 2 (the top 8 bits of the addition) for LDI instruction. This error of course is that the relocation should not be against an offset from the .text section, but rather against the matrix symbol itself. Since this symbol stays aligned, it does not move as far back as the .text+offset value. I am currently testing a local patch which stops the assembler from trying to optimize away symbol names in relocations if it knows that linker relaxation is going to occur. With this patch applied the object file looks like: % objdump -dr main.o [...] 4b2: f0 e0 ldi r31, 0x00 ; 0 4b2: R_AVR_HI8_LDI matrix And when finally linked the correct value - 3 - is used by the LDI instruction.
The master branch has been updated by Nick Clifton <nickc@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f3be70df1b1681ad1b9b0490587011bde433d220 commit f3be70df1b1681ad1b9b0490587011bde433d220 Author: Nick Clifton <nickc@redhat.com> Date: Thu Dec 16 16:40:57 2021 +0000 Fix AVR assembler so that it creates relocs that will work with linker relaxation. PR 28686 gas * config/tc-avr.h (tc_fix_adjustable): Define. * config/tc-avr.c (avr_fix_adjustable): New function. * testsuite/gas/all/gas.exp: Skip tests that need adjustable fixups. * testsuite/gas/elf/elf.exp: Likewise. * testsuite/gas/avr/diffreloc_withrelax.d: Adjust expected output. * testsuite/gas/avr/pc-relative-reloc.d: Adjust expected output. ld * testsuite/ld-avr/avr-prop-7.d: Adjust expected output. * testsuite/ld-avr/avr-prop-8.d: Likewise. * testsuite/ld-avr/pr13402.d: Likewise.
Patch applied.