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

--- Comment #3 from Vincent Riviere <vincent.riviere at freesbee dot fr> ---
(In reply to Andrew Pinski from comment #1)
> I don't see any issues with the output of gcc. Are you sure this is not a
> binutils gnu as issue where the offsets are done incorrectly there.

Yes, I'm sure it's a gcc bug.

With the testcase I initially provided, by chance it's the favourable case.
But if I artificially add a misalignment with a nop, for example, the wrong
result appears:

$ cat swi2.c
int g;

void f(int i)
{
        asm("nop");
        switch (i)
        {
                case 0: g = 6082; break;
                case 1: g = 9332; break;
                case 2: g = 5642; break;
                case 3: g = 1423; break;
                case 4: g = 2152; break;
                case 5: g = 6779; break;
                case 6: g = 7074; break;
                case 7: g = 8280; break;
        }
}

$ m68k-linux-gcc -Os -c swi2.c -mlong-jump-table-offsets -malign-int
$ m68k-linux-objdump -d swi2.o

swi2.o:    file format elf32-m68k


Disassembly of section .text:

00000000 <f>:
   0:   202f 0004       movel %sp@(4),%d0
   4:   4e71            nop
   6:   7207            moveq #7,%d1
   8:   b280            cmpl %d0,%d1
   a:   6536            bcss 42 <f+0x42>
   c:   e588            lsll #2,%d0
   e:   203b 0808       movel %pc@(18 <f+0x18>,%d0:l),%d0  |right offset
  12:   4efb 0802       jmp %pc@(16 <f+0x16>,%d0:l)  |wrong offset
  16:   284c            moveal %a4,%a4   |harmful filler
  18:   0000 0020       orib #32,%d0
  1c:   0000 002c       orib #44,%d0
  20:   0000 0038       orib #56,%d0

See that:
- actual jump table starts at offset 0x18
- at offset 0x16, a useless "moveal %a4,%a4" instruction is inserted as filler
- at offset 0xe, offset 0x18 is used appropriately for label .L4. So the right
jump table entry is properly read.
- but at offset 0x12, a *wrong* offset 0x16 is used for the jump. That's
actually the offset of the filler, while it should be 0x18 for label .L4.

This can't work:
- the jump table offsets are computed from the start of the jump table
- but jmp, with that "2" hardcoded as offset, expects offsets being relative to
the address right after itself.
So if a filler is inserted between jmp and actual table contents, as in the
example above, the jump occurs to a wrong address.

Reply via email to