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

            Bug ID: 77300
           Summary: [MIPS] incorrectly moves instruction containing local
                    GOT16 relocation into a delay slot
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: james410 at cowgill dot org.uk
  Target Milestone: ---

Created attachment 39474
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39474&action=edit
reduced testcase

Debian bug: https://bugs.debian.org/834147

While I'm not sure about the exact conditions this bug occurs, I have managed
to get GCC to produce an object with a dangling GOT16 relocation (ie one
without a LO16) using the attached source. The bug was originally found in
blender, but I've managed to reduce it to something reasonably small.

Compile with:
 mipsel-linux-gnu-g++-6 -O2 -fPIC -c src.cpp

You can tell the bug occurs because attempting to link it gives this error:
 mipsel-linux-gnu-g++-6 src.o
 /usr/lib/gcc-cross/mipsel-linux-gnu/6/../../../../mipsel-linux-gnu/bin/ld:
src.o: Can't find matching LO16 reloc against `_ZN1HIiE5m_fn4ERK1G.isra.1' for
R_MIPS_GOT16 at 0xcc in section
`.text._ZN1HIiE5m_fn5ERK1G[_ZN1HIiE5m_fn5ERK1G]'

The offending assembly contains this:

===========
$L5:
        lw      $16,%got(_ZN1HIiE5m_fn4ERK1G.isra.1)($28)
$L17:
        addiu   $16,$16,%lo(_ZN1HIiE5m_fn4ERK1G.isra.1)
        move    $25,$16
        .reloc  1f,R_MIPS_JALR,_ZN1HIiE5m_fn4ERK1G.isra.1
1:      jalr    $25
        move    $4,$17

        move    $25,$16
        .reloc  1f,R_MIPS_JALR,_ZN1HIiE5m_fn4ERK1G.isra.1
1:      jalr    $25
        move    $4,$17
[...]
$L15:
        lw      $2,28($sp)
        beq     $2,$0,$L17
        lw      $16,%got(_ZN1HIiE5m_fn4ERK1G.isra.1)($28)

        b       $L16
        lw      $25,%call16(_ZN1HIiE5m_fn1Ev)($28)
===========

The error is that the bottommost %got relocation does not have a corresponding
%lo relocation. It seems that GCC has "optimized" the function by moving the lw
into the delay slot of the 'beq $2,$0,$L17' instruction, but this unfortunately
doesn't work because the corresponding %lo at $L17 also would need to be
copied.

My compiler is:
mipsel-linux-gnu-g++-6 (Debian 6.1.1-9) 6.1.1 20160705

Reply via email to