https://sourceware.org/bugzilla/show_bug.cgi?id=16005
Bug ID: 16005 Summary: [avr] Linker crash on a particular instruction sequence with --relax Product: binutils Version: unspecified Status: NEW Severity: normal Priority: P2 Component: ld Assignee: unassigned at sourceware dot org Reporter: konfera at efton dot sk As reported in http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=136763 , the linker for avr target crashes when trying to relax a rjmp/ret sequence. The test case (crash.s): main: nop rjmp main ret rjmp main >avr-as crash.s -o crash.o >avr-ld --relax --debug-relax crash.o -o crash.elf Observations: 1. this occurs on various builds ranging back 5 years, hosted both on Win and Linux, although the visible symptoms vary, on some builds ld ends silently and generates an empty output file 2. the second rjmp is not needed, a nop or any other instruction would do. In fact, the observation is, that the error is not occuring if there is no instruction after the ret 3. the target of rjmp is irrelevant, it can be any symbol 4. adding --debug-relax switch reveals more details: the error occurs as the consequence of rjmp / ret detection and subsequent ret removal >avr-ld --relax --debug-relax crash.o -o crash.elf found rjmp / ret sequence at address 0x2 unreachable ret instruction at address 0x4 deleted. This locates the error into bfd/elf32-avr.c:elf32_avr_relax_delete_bytes(), being called just after the debug printout "unreachable ret instruction... deleted". 5. Replacing the first rjmp by jmp or rcall results in normal linking. This is interesting, because both the jmp/ret and rcall/ret sequences are in previous relaxation iteration replaced by rjmp/ret sequence, thus then undergo the same ret-removal procedure, which in this case is completed correctly: main: nop rcall main ret rjmp main >avr-as crash.s -o crash.o >avr-ld --relax --debug-relax crash.o -o crash.elf converted rcall/ret sequence at address 0x2 into rjmp/ret sequence. Section is . text found rjmp / ret sequence at address 0x2 unreachable ret instruction at address 0x4 deleted. Relocation at address 0x6 needs to be moved. Old section offset: 0x6, New section offset: 0x4 Checking if the relocation's addend needs corrections. Address of anchor symbol: 0x0 Address of relocation target: 0x0 Address of relaxed insn: 0x2 Checking if the relocation's addend needs corrections. Address of anchor symbol: 0x0 Address of relocation target: 0x0 Address of relaxed insn: 0x2 --- Stepping through elf32_avr_relax_delete_bytes() for the original input file results in crash in this line: memmove (contents + addr, contents + addr + count, (size_t) (toaddr - addr - count)); (which is conditionally executed only if there is anything to move, which btw. matches observation 2). contents was found to be NULL. As previously in this routine contents = elf_section_data (sec)->this_hdr.contents; it's elf_section_data (sec) which is not properly set up. Indeed, in the only other case when elf32_avr_relax_delete_bytes() is called (in the jmp/call shrink branch of the relaxation loop), there are several lines which might be relevant: /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; elf_section_data (sec)->this_hdr.contents = contents; symtab_hdr->contents = (unsigned char *) isymbuf; Copying these three lines just before the other call to elf32_avr_relax_delete_bytes() and recompiling the linker, appears to have fixed the problem. Unfortunately, I am not versed enough to judge, whether this is a proper fix to the problem. -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils