Bug 24991 - the assembler generates incorrect offset for jumps on arm thumb2
Summary: the assembler generates incorrect offset for jumps on arm thumb2
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: 2.34
: P2 normal
Target Milestone: 2.33
Assignee: Tamar Christina
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-09-10 18:36 UTC by Mikulas Patocka
Modified: 2019-10-14 11:32 UTC (History)
3 users (show)

See Also:
Host: arm-linux-gnueabihf
Target: arm-linux-gnueabihf
Build: arm-linux-gnueabihf
Last reconfirmed: 2019-09-19 00:00:00


Attachments
a test file (191 bytes, text/x-csrc)
2019-09-10 18:36 UTC, Mikulas Patocka
Details
Compiler output (252.05 KB, text/plain; charset=utf-8)
2019-09-11 11:31 UTC, Mikulas Patocka
Details
Assembler output (34.95 KB, text/plain; charset=utf-8)
2019-09-11 11:32 UTC, Mikulas Patocka
Details
Linker output (256.82 KB, application/octet-stream)
2019-09-11 11:34 UTC, Mikulas Patocka
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mikulas Patocka 2019-09-10 18:36:44 UTC
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
Comment 1 Nick Clifton 2019-09-11 09:28:23 UTC
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
Comment 2 Mikulas Patocka 2019-09-11 11:31:14 UTC
Created attachment 11988 [details]
Compiler output
Comment 3 Mikulas Patocka 2019-09-11 11:32:42 UTC
Created attachment 11989 [details]
Assembler output
Comment 4 Mikulas Patocka 2019-09-11 11:34:33 UTC
Created attachment 11990 [details]
Linker output
Comment 5 Mikulas Patocka 2019-09-11 11:38:00 UTC
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.
Comment 6 Tamar Christina 2019-09-19 10:03:35 UTC
GCC bug filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91816 here.
Gas patch being submitted.
Comment 7 Sourceware Commits 2019-09-24 14:02:08 UTC
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.
Comment 8 Tamar Christina 2019-09-24 14:04:15 UTC
Gas part fixed, Will backport it to 2.33 after branch opens again.
Comment 9 Sourceware Commits 2019-10-14 11:31:14 UTC
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)
Comment 10 Tamar Christina 2019-10-14 11:32:29 UTC
backport committed.