https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94119

            Bug ID: 94119
           Summary: MIPS: Invalid use of branch delay slots leading to
                    corrupt jump
           Product: gcc
           Version: 8.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: d.dorau at avm dot de
  Target Milestone: ---

Created attachment 48007
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48007&action=edit
Example code + Makefile to reproduce issue

We found an issue with gcc 8.3 issuing wrong instructions in MIPS branch
delay slots. The issue is that in a chain of bne instructions an instruction is
put repeatedly into the delay slots of the bne instructions that should be
issued only once. This leads to an invalid calculation of a subsequent jalr
address which then leads to a crash.

By using git bisect we found commit cd36a4518d14aae18ac89a6232e009ee2bcb6008 to
be the commit that introduced this behaviour (first appeared in gcc 7.1)
although that commit is not directly related to MIPS. So it maybe just
triggering a MIPS specific bug elsewhere.
The issue is still present in the gcc 10 branch. Reverting this commit "fixes"
the issue.

The commit mentioned fixes PR71785.

Steps to reproduce:

Compile the provided sample .c file with 

CFLAGS := -mno-abicalls \
          -mno-branch-likely \
          -ffreestanding \
          -O2 \
          -fno-reorder-blocks \
          -mlong-calls \
          -static \
          -g \
          -save-temps


The bad branch delay slots are in the expansion of the 

#define BUFFER_IS_FF(_a)              \
    ((_a)[0] == 0xff &&                         \
     (_a)[1] == 0xff &&                         \
     (_a)[2] == 0xff &&                         \
     (_a)[3] == 0xff &&                         \
     (_a)[4] == 0xff &&                         \
     (_a)[5] == 0xff)

macro:

The addiu s0,s0,0 instruction must only be issued once but instead is in
several
places. This leads to an invalid call at 9c.


    if((subtype == 8) && !BUFFER_IS_FF(data->addr1))
  30:   14c20016        bne     a2,v0,8c <foo+0x8c>
  34:   a7a00018        sh      zero,24(sp)
  38:   90a20000        lbu     v0,0(a1)
  3c:   240300ff        li      v1,255
  40:   14430010        bne     v0,v1,84 <foo+0x84>
  44:   3c100000        lui     s0,0x0
                        44: R_MIPS_HI16 memcmp_
  48:   90a30001        lbu     v1,1(a1)
  4c:   14620015        bne     v1,v0,a4 <foo+0xa4>
  50:   26100000        addiu   s0,s0,0
                        50: R_MIPS_LO16 memcmp_
  54:   90a20002        lbu     v0,2(a1)
  58:   14430012        bne     v0,v1,a4 <foo+0xa4>
  5c:   26100000        addiu   s0,s0,0
                        5c: R_MIPS_LO16 memcmp_
  60:   90a30003        lbu     v1,3(a1)
  64:   1462000f        bne     v1,v0,a4 <foo+0xa4>
  68:   26100000        addiu   s0,s0,0
                        68: R_MIPS_LO16 memcmp_
  6c:   90a20004        lbu     v0,4(a1)
  70:   14430004        bne     v0,v1,84 <foo+0x84>
  74:   00000000        nop
  78:   90a30005        lbu     v1,5(a1)
  7c:   10620003        beq     v1,v0,8c <foo+0x8c>
  80:   00000000        nop
  84:   10000007        b       a4 <foo+0xa4>
  88:   26100000        addiu   s0,s0,0
                        88: R_MIPS_LO16 memcmp_
    if(!memcmp_(data->addr2, nullbuf, BUF_LEN))
  8c:   3c100000        lui     s0,0x0
                        8c: R_MIPS_HI16 memcmp_
  90:   24060006        li      a2,6
  94:   27a50014        addiu   a1,sp,20
  98:   26100000        addiu   s0,s0,0
                        98: R_MIPS_LO16 memcmp_
  9c:   0200f809        jalr    s0


The provided example code + Makefile will reprocude the crash.

Reply via email to