bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug gas/15602] New: .word L2-L1 fails to diagnose offsets larger than 1


From: mikpe at it dot uu.se
Subject: [Bug gas/15602] New: .word L2-L1 fails to diagnose offsets larger than 16 bits, resulting in broken jump tables on m68k
Date: Tue, 11 Jun 2013 12:18:49 +0000

http://sourceware.org/bugzilla/show_bug.cgi?id=15602

            Bug ID: 15602
           Summary: .word L2-L1 fails to diagnose offsets larger than 16
                    bits, resulting in broken jump tables on m68k
           Product: binutils
           Version: 2.24 (HEAD)
            Status: NEW
          Severity: normal
          Priority: P2
         Component: gas
          Assignee: unassigned at sourceware dot org
          Reporter: mikpe at it dot uu.se

The following test case emulates a GCC-generated switch/jump table on
m68k-linux:

> cat gasbug.s
        .file "gasbug.s"
        .text

        .align 2
        .globl main
        .type main, @function
main:
        moveq #0,%d0
        move.w .L1(%pc,%d0.l*2),%d0
        jmp %pc@(2,%d0:w)
        .balignw 2,0x284c
.L1:
        .rept 65536-3
        .word .L2-.L1
        .endr
.L2:
        moveq #0,%d0
        rts
        .size main, .-main
        .section .note.GNU-stack,"",@progbits

The jump table at L1 contains >32K 16-bit entries, so the value of .L2-.L1
needs more than the 16 bits as emitted by .word.  However, GAS fails to
diagnose this overflow and instead emits truncated values (0xfffe to be exact).
 At runtime, the code branches to L1 - 2, executes 0x0002 (harmless), falls
through to L1, and SIGILLs because 0xfffe is not a valid opcode.

> as -o gasbug.o gasbug.s
> gcc -o gasbug gasbug.o
> gdb ./gasbug
...
Breakpoint 1, 0x800003b8 in main ()
1: x/i $pc
=> 0x800003b8 <main>:   moveq #0,%d0
(gdb) stepi
0x800003ba in main ()
1: x/i $pc
=> 0x800003ba <main+2>: movew %pc@(0x800003c2 <main+10>,%d0:l:2),%d0
(gdb) 
0x800003be in main ()
1: x/i $pc
=> 0x800003be <main+6>: jmp %pc@(0x800003c2 <main+10>,%d0:w)
(gdb) 
0x800003c0 in main ()
1: x/i $pc
=> 0x800003c0 <main+8>: orib #-2,%d2
(gdb) 
0x800003c4 in main ()
1: x/i $pc
=> 0x800003c4 <main+12>:        .short 0xfffe
(gdb) 

Program received signal SIGILL, Illegal instruction.

If the operand to .word is a literal >= 64K, then GAS does flag the error:

> echo '.word 65536' | as > /dev/null
{standard input}: Assembler messages:
{standard input}:1: Warning: value 0x10000 truncated to 0x0

Looking at an objdump of gasbug.o it appears that GAS has attempted to route
the jump table entries to trampolines, but failed:

> objdump -d gasbug.o
gasbug.o:     file format elf32-m68k


Disassembly of section .text:

00000000 <main>:
       0:       7000            moveq #0,%d0
       2:       303b 0a06       movew %pc@(a <main+0xa>,%d0:l:2),%d0
       6:       4efb 0002       jmp %pc@(a <main+0xa>,%d0:w)
       a:       fffe            .short 0xfffe

(many many more ".short 0xfffe")

   20002:       fffe            .short 0xfffe
   20004:       6000 0008       braw 2000e <main+0x2000e>
   20008:       60ff 0000 0004  bral 2000e <main+0x2000e>
   2000e:       7000            moveq #0,%d0
   20010:       4e75            rts

This bug is related to <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583>.

-- 
You are receiving this mail because:
You are on the CC list for the bug.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]