public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug target/57583] New: large switches with jump tables are horribly broken on m68k
@ 2013-06-11 9:58 mikpe at it dot uu.se
2013-06-11 10:15 ` [Bug target/57583] " schwab@linux-m68k.org
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: mikpe at it dot uu.se @ 2013-06-11 9:58 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583
Bug ID: 57583
Summary: large switches with jump tables are horribly broken on
m68k
Product: gcc
Version: 4.8.1
Status: UNCONFIRMED
Severity: major
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: mikpe at it dot uu.se
Created attachment 30288
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=30288&action=edit
test case and generator program
Switch jump tables on m68k-linux use 16-bit PC-relative offsets. No
verification is made that the offsets actually fit in 16 bits, instead they are
silently truncated. As a result, a large switch may branch to a wrong address;
in my case it branches into the jump table itself causing a SIGILL.
There are two bugs here:
1. GCC seems to hard-code the use of 16-bit offsets in its jump tables on
m68k-linux. It should have an option to use 32-bit offsets instead.
2. GAS (not part of GCC I know) truncates ".word" operands to 16 bits without
warning or error when significant bits are lost. I'll file that separately at
the sourceware/binutils bugzilla.
The test case contains a for (;;) loop with a switch () with 64K cases 0 ..
64K-1, each case containing a function call and a break. That switch becomes
the following assembly code on m68k-linux with gcc-4.8.1:
.L259:
move.l (%a2),-(%sp)
move.l %a2,-(%sp)
jsr fetch
addq.l #8,%sp
and.l #65535,%d0
move.w .L262(%pc,%d0.l*2),%d0
jmp %pc@(2,%d0:w)
.balignw 2,0x284c
.L262:
.word .L260-.L262
(64K - 1 more of these with varying labels in the first operand)
When run on the target the code SIGILLs:
0x80000402 in fetch ()
1: x/i $pc
=> 0x80000402 <fetch+14>: rts
(gdb)
0x80001c0c in loop ()
1: x/i $pc
=> 0x80001c0c <loop+20>: addql #8,%sp
(gdb)
0x80001c0e in loop ()
1: x/i $pc
=> 0x80001c0e <loop+22>: andil #65535,%d0
(gdb)
0x80001c14 in loop ()
1: x/i $pc
=> 0x80001c14 <loop+28>: movew %pc@(0x80001c1c <loop+36>,%d0:l:2),%d0
(gdb)
0x80001c18 in loop ()
1: x/i $pc
=> 0x80001c18 <loop+32>: jmp %pc@(0x80001c1c <loop+36>,%d0:w)
(gdb) print $d0
$3 = 4
*** THIS "4" SHOWS THAT THE JUMP TABLE ENTRY HAS BEEN TRUNCATED
(gdb) stepi
0x80001c20 in loop ()
1: x/i $pc
=> 0x80001c20 <loop+40>: .short 0xfff2
(gdb) stepi
Program received signal SIGILL, Illegal instruction.
I'm attaching the test case (bug.c) and the program used to generate it
(genbug.c).
Classifying as a target bug since the code works on x86_64 and powerpc64.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug target/57583] large switches with jump tables are horribly broken on m68k
2013-06-11 9:58 [Bug target/57583] New: large switches with jump tables are horribly broken on m68k mikpe at it dot uu.se
@ 2013-06-11 10:15 ` schwab@linux-m68k.org
2013-06-11 12:20 ` mikpe at it dot uu.se
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: schwab@linux-m68k.org @ 2013-06-11 10:15 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583
--- Comment #1 from Andreas Schwab <schwab@linux-m68k.org> ---
Apparently GAS has lost its BROKEN_DOT_WORD handing.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug target/57583] large switches with jump tables are horribly broken on m68k
2013-06-11 9:58 [Bug target/57583] New: large switches with jump tables are horribly broken on m68k mikpe at it dot uu.se
2013-06-11 10:15 ` [Bug target/57583] " schwab@linux-m68k.org
@ 2013-06-11 12:20 ` mikpe at it dot uu.se
2013-06-12 11:37 ` mikpe at it dot uu.se
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: mikpe at it dot uu.se @ 2013-06-11 12:20 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583
--- Comment #2 from Mikael Pettersson <mikpe at it dot uu.se> ---
<http://sourceware.org/bugzilla/show_bug.cgi?id=15602> is the corresponding
binutils/gas bug.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug target/57583] large switches with jump tables are horribly broken on m68k
2013-06-11 9:58 [Bug target/57583] New: large switches with jump tables are horribly broken on m68k mikpe at it dot uu.se
2013-06-11 10:15 ` [Bug target/57583] " schwab@linux-m68k.org
2013-06-11 12:20 ` mikpe at it dot uu.se
@ 2013-06-12 11:37 ` mikpe at it dot uu.se
2013-06-12 19:22 ` hp at gcc dot gnu.org
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: mikpe at it dot uu.se @ 2013-06-12 11:37 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583
--- Comment #3 from Mikael Pettersson <mikpe at it dot uu.se> ---
It's not too difficult to make the m68k backend use 32-bit offsets in its jump
tables (adjust CASE_VECTOR_MODE, ASM_OUTPUT_ADDR_DIFF_ELT,
ASM_RETURN_CASE_JUMP, drop the sign-extend from the tablejump expander,
likewise in the unnamed insn that matches the output from the tablejump
expander). I have a crude patch to do that, and make it compile-time
selectable via an option.
However, it seems to me that the compiler should be able to figure out for
itself if a given jump table might need 32-bit offsets. In the worst case
every element will overflow a (signed) 16-bit offset (0..32K-1 positive range)
and need a GAS-inserted trampoline, for a total of 2 + 6 == 8 bytes per
element. So tables with no more than 4K elements should work with 16-bit
offsets. Tables larger than that may have their trampolines more than 32K away
from the table PC base, which cannot work with 16-bit offsets, so for those the
compiler should use 32-bit offsets. Seems to require implementing "casesi" for
m68k though.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug target/57583] large switches with jump tables are horribly broken on m68k
2013-06-11 9:58 [Bug target/57583] New: large switches with jump tables are horribly broken on m68k mikpe at it dot uu.se
` (2 preceding siblings ...)
2013-06-12 11:37 ` mikpe at it dot uu.se
@ 2013-06-12 19:22 ` hp at gcc dot gnu.org
2013-06-12 20:50 ` schwab@linux-m68k.org
2013-06-12 22:11 ` hp at gcc dot gnu.org
5 siblings, 0 replies; 7+ messages in thread
From: hp at gcc dot gnu.org @ 2013-06-12 19:22 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583
--- Comment #4 from Hans-Peter Nilsson <hp at gcc dot gnu.org> ---
(In reply to Mikael Pettersson from comment #3)
> It's not too difficult to make the m68k backend use 32-bit offsets in its
> jump tables (adjust CASE_VECTOR_MODE, ASM_OUTPUT_ADDR_DIFF_ELT,
> ASM_RETURN_CASE_JUMP, drop the sign-extend from the tablejump expander,
> likewise in the unnamed insn that matches the output from the tablejump
> expander). I have a crude patch to do that,
Does your patch define CASE_VECTOR_SHORTEN_MODE?
Otherwise that'll probably be one of the first review comments.
> and make it compile-time
> selectable via an option.
FWIW, -mbigtable for sh.
> However, it seems to me that the compiler should be able to figure out for
> itself if a given jump table might need 32-bit offsets.
The length insn attribute needs to be defined in order to take advantage of the
existing machinery. It seems it currently isn't, for m68k.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug target/57583] large switches with jump tables are horribly broken on m68k
2013-06-11 9:58 [Bug target/57583] New: large switches with jump tables are horribly broken on m68k mikpe at it dot uu.se
` (3 preceding siblings ...)
2013-06-12 19:22 ` hp at gcc dot gnu.org
@ 2013-06-12 20:50 ` schwab@linux-m68k.org
2013-06-12 22:11 ` hp at gcc dot gnu.org
5 siblings, 0 replies; 7+ messages in thread
From: schwab@linux-m68k.org @ 2013-06-12 20:50 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583
--- Comment #5 from Andreas Schwab <schwab@linux-m68k.org> ---
The assembler already handles jump targets that are too far away (via the
BROKEN_DOT_WORD hack), this issue is about growing the table itself too large
so that the overflow table is not reachable any more within 32K.
^ permalink raw reply [flat|nested] 7+ messages in thread
* [Bug target/57583] large switches with jump tables are horribly broken on m68k
2013-06-11 9:58 [Bug target/57583] New: large switches with jump tables are horribly broken on m68k mikpe at it dot uu.se
` (4 preceding siblings ...)
2013-06-12 20:50 ` schwab@linux-m68k.org
@ 2013-06-12 22:11 ` hp at gcc dot gnu.org
5 siblings, 0 replies; 7+ messages in thread
From: hp at gcc dot gnu.org @ 2013-06-12 22:11 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57583
--- Comment #6 from Hans-Peter Nilsson <hp at gcc dot gnu.org> ---
(In reply to Andreas Schwab from comment #5)
> The assembler already handles jump targets that are too far away (via the
> BROKEN_DOT_WORD hack), this issue is about growing the table itself too
> large so that the overflow table is not reachable any more within 32K.
There's no confusion here. While a less involved patch will suffice where just
the table is too big, CASE_VECTOR_SHORTEN_MODE can detect and handle both
issues. I think it will also allow for jump-tables closer to the 4K entries
than the significantly lower limit you'll find workable with a less involved
patch and relying on BROKEN_DOT_WORD.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-06-12 22:11 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-11 9:58 [Bug target/57583] New: large switches with jump tables are horribly broken on m68k mikpe at it dot uu.se
2013-06-11 10:15 ` [Bug target/57583] " schwab@linux-m68k.org
2013-06-11 12:20 ` mikpe at it dot uu.se
2013-06-12 11:37 ` mikpe at it dot uu.se
2013-06-12 19:22 ` hp at gcc dot gnu.org
2013-06-12 20:50 ` schwab@linux-m68k.org
2013-06-12 22:11 ` hp at gcc dot gnu.org
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).