Created attachment 11985 [details] a test file Compile the attached file without optimizations and run it. You'll get a crash: $ arm-linux-gnueabihf-gcc -mthumb long.c $ ./a.out Segmentation fault (core dumped) If you look at the assembler output, you'll see that the beq.w instruction that is supposed to jump over the function body points backwards. 0000050c <f>: 50c: b580 push {r7, lr} 50e: b082 sub sp, #8 510: af00 add r7, sp, #0 512: 6078 str r0, [r7, #4] 514: 687b ldr r3, [r7, #4] 516: 2b00 cmp r3, #0 518: f406 8e45 beq.w fff871a6 <__bss_end__+0xffdef15e> <<<<<<< BUG 51c: f8df 3ffc ldr.w r3, [pc, #4092] ; 151c <f+0x1010> 520: 447b add r3, pc 522: 4618 mov r0, r3 524: f7ff ef52 blx 3cc <puts@plt> 528: f8df 3ff4 ldr.w r3, [pc, #4084] ; 1520 <f+0x1014> 52c: 447b add r3, pc 52e: 4618 mov r0, r3 530: f7ff ef4c blx 3cc <puts@plt> 534: f8df 3fec ldr.w r3, [pc, #4076] ; 1524 <f+0x1018> 538: 447b add r3, pc 53a: 4618 mov r0, r3 53c: f7ff ef46 blx 3cc <puts@plt> 540: f8df 3fe4 ldr.w r3, [pc, #4068] ; 1528 <f+0x101c> 544: 447b add r3, pc 546: 4618 mov r0, r3
Hi Mikulas, Please could you upload a copy of the compiled executable *and* a copy of the assembler output from gcc. It is possible that this is a compiler bug - ie it could be generating a branch that is not going to the correct location - and the assembler output should help us determine if this is the case. It could also be both a compiler and an assembler bug. eg the compiler might be producing a branch that is out of range, and the assembler could be assembling it without complaining. Cheers Nick
Created attachment 11988 [details] Compiler output
Created attachment 11989 [details] Assembler output
Created attachment 11990 [details] Linker output
I've attached the files. It is both the compiler and assembler bug - the compiler generates out of range jump and the assembler incorrectly assembles it as a backward jump.
GCC bug filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91816 here. Gas patch being submitted.
The master branch has been updated by Tamar Christina <tnfchris@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e8f8842d90abe5eafa8c32f08fbc3a747a45747c commit e8f8842d90abe5eafa8c32f08fbc3a747a45747c Author: Tamar Christina <tamar.christina@arm.com> Date: Tue Sep 24 14:46:17 2019 +0100 Arm: Fix out of range conditional branch (PR/24991) The fix for PR12848 introduced an off by one error in the mask, this corrected the negative overflows but not the positive overflows. As a result the conditional branch instructions accepted a too wide positive immediate which resulted in it corrupting the instruction during encoding. The relocation I believe has been incorrectly named, to be consistent with the other relocations it should have been named BRANCH21 which is why the masks for it are confusing. I've replaced the masks with a function out_of_range_p which should make it harder to make such mistakes. The mask for BL/BLX on Armv6t+ is also wrong, the extended range is 25-bits and so the mask should be checking for 24-bits for positive overflow. gas/ChangeLog: PR gas/24991 * config/tc-arm.c (out_of_range_p): New. (md_apply_fix): Use it in BFD_RELOC_THUMB_PCREL_BRANCH9, BFD_RELOC_THUMB_PCREL_BRANCH12, BFD_RELOC_THUMB_PCREL_BRANCH20, BFD_RELOC_THUMB_PCREL_BRANCH23, BFD_RELOC_THUMB_PCREL_BRANCH25 * testsuite/gas/arm/pr24991.d: New test. * testsuite/gas/arm/pr24991.l: New test. * testsuite/gas/arm/pr24991.s: New test.
Gas part fixed, Will backport it to 2.33 after branch opens again.
The binutils-2_33-branch branch has been updated by Tamar Christina <tnfchris@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2948a47219b2000e389faaa3df6fa5eaf330b7ff commit 2948a47219b2000e389faaa3df6fa5eaf330b7ff Author: Tamar Christina <tamar.christina@arm.com> Date: Tue Sep 24 14:46:17 2019 +0100 Arm: Fix out of range conditional branch (PR/24991) The fix for PR12848 introduced an off by one error in the mask, this corrected the negative overflows but not the positive overflows. As a result the conditional branch instructions accepted a too wide positive immediate which resulted in it corrupting the instruction during encoding. The relocation I believe has been incorrectly named, to be consistent with the other relocations it should have been named BRANCH21 which is why the masks for it are confusing. I've replaced the masks with a function out_of_range_p which should make it harder to make such mistakes. The mask for BL/BLX on Armv6t+ is also wrong, the extended range is 25-bits and so the mask should be checking for 24-bits for positive overflow. gas/ChangeLog: PR gas/24991 * config/tc-arm.c (out_of_range_p): New. (md_apply_fix): Use it in BFD_RELOC_THUMB_PCREL_BRANCH9, BFD_RELOC_THUMB_PCREL_BRANCH12, BFD_RELOC_THUMB_PCREL_BRANCH20, BFD_RELOC_THUMB_PCREL_BRANCH23, BFD_RELOC_THUMB_PCREL_BRANCH25 * testsuite/gas/arm/pr24991.d: New test. * testsuite/gas/arm/pr24991.l: New test. * testsuite/gas/arm/pr24991.s: New test. (cherry picked from commit e8f8842d90abe5eafa8c32f08fbc3a747a45747c)
backport committed.