Bug 72814 - reflect FAILs on 32-bit Solaris/SPARC: SIGILL
Summary: reflect FAILs on 32-bit Solaris/SPARC: SIGILL
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: go (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: 7.0
Assignee: Ian Lance Taylor
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-08-05 12:14 UTC by Rainer Orth
Modified: 2016-08-08 19:55 UTC (History)
0 users

See Also:
Host: sparc*-sun-solaris2.*
Target: sparc*-sun-solaris2.*
Build: sparc*-sun-solaris2.*
Known to work:
Known to fail:
Last reconfirmed: 2016-08-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rainer Orth 2016-08-05 12:14:15 UTC
When building to avoid PR go/72812, the 32-bit reflect test FAILs on Solaris/SPARC:

Illegal Instruction

runtime_sighandler
        /vol/gcc/src/hg/trunk/local/libgo/runtime/go-signal.c:223

        :0
[...]

Thread 6 received signal SIGILL, Illegal instruction.
[Switching to Thread 4 (LWP 4)]
0xff0d2ea8 in ffi_call_v8 ()
    at /vol/gcc/src/hg/trunk/local/libffi/src/sparc/v8.S:225
225             rept256; rept256; rept256; rept256
1: x/i $pc
=> 0xff0d2ea8 <ffi_call_v8+440>:        illtrap  0x1
(gdb) where
#0  0xff0d2ea8 in ffi_call_v8 ()
    at /vol/gcc/src/hg/trunk/local/libffi/src/sparc/v8.S:225
#1  0xfeca7da4 in reflect.call (
    func_type=0x981b4 <__go_td_FrN24_reflect_test.emptyStructee>, 
    func_val=0x98188 <reflect_test.returnEmpty$descriptor>, 
    is_interface=<optimized out>, is_method=<optimized out>, params=0x0, 
    results=0x1030cbc8)
    at /vol/gcc/src/hg/trunk/local/libgo/runtime/go-reflect-call.c:225
#2  0x000b23d0 in reflect.call.N13_reflect.Value (
    pointer=pointer@entry=0x111aa590, 
    op=<error reading variable: Cannot access memory at address 0x99>, 
    param=...) at value.go:451
#3  0x000b18cc in reflect.Call.N13_reflect.Value (
    pointer=pointer@entry=0x10d71d3c, in=...) at value.go:299
#4  0x000ce690 in reflect_test.TestCallWithStruct (t=0x1074e680)
    at all_test.go:1509
#5  0xfeda315c in testing.tRunner (param=0x1074e680, 
    fn=0x98310 <reflect_test.TestCallWithStruct$descriptor>)
    at /vol/gcc/src/hg/trunk/local/libgo/go/testing/testing.go:609
#6  0xfeda31cc in testing.$thunk22 (__go_thunk_parameter=0x1030cb98)
    at /vol/gcc/src/hg/trunk/local/libgo/go/testing/testing.go:645
#7  0xfecb75bc in kickoff ()
    at /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:235
#8  0xfe14a46c in __makecontext_v2 () from /lib/libc.so.1


It seems that the SIGILL is expected here and libgo catching it interferes
with libffi.

  Rainer
Comment 1 Ian Lance Taylor 2016-08-08 17:40:56 UTC
The failing test is a function that returns a zero-sized struct.  The libffi library does not support a zero-sized struct, so libgo and libffi togther wind up treating the return type as a struct whose size is 1 byte.  On 32-bit SPARC, a call to a function that returns a struct whose size is larger than 0 is followed by an unimp instruction.  The function is compiled to skip the unimp instruction when it returns.  See the handling of %) in sparc_print_operand in gcc/config/sparc/sparc.c.  So libffi, thinking that the function returns a non-empty struct, provides an unimp instruction to be skipped.  But the actual function returns an empty struct, and therefore does not expect the unimp instruction, and therefore does not skip it.  The result is an attempt to execute the instruction, causing the SIGILL.
Comment 2 ian@gcc.gnu.org 2016-08-08 19:54:16 UTC
Author: ian
Date: Mon Aug  8 19:53:44 2016
New Revision: 239252

URL: https://gcc.gnu.org/viewcvs?rev=239252&root=gcc&view=rev
Log:
	PR go/72814

    runtime: treat zero-sized result value as void
    
    Change the FFI interface to treat a call to a function that returns a
    zero-sized result as a call to a function that returns void.
    
    This is part of the fix for https://gcc.gnu.org/PR72814.  On 32-bit
    SPARC systems, a call to a function that returns a non-zero-sized struct
    is followed by an unimp instruction that describes the size of the
    struct.  The function returns to the address after the unimp
    instruction.  The libffi library can not represent a zero-sized struct,
    so we wind up treating it as a 1-byte struct.  Thus in that case libffi
    calls the function with an unimp instruction, but the function does not
    adjust the return address.  The result is that the program attempts to
    execute the unimp instruction, causing a crash.
    
    This is part of a change that fixes the crash by treating all functions
    that return zero bytes as functions that return void.
    
    Reviewed-on: https://go-review.googlesource.com/25585

	* go-gcc.cc (Gcc_backend::function_type): If the return type is
	zero bytes, treat the function as returning void.
	(return_statement): If the return type is zero bytes, don't
	actually return any values.

Modified:
    trunk/gcc/go/ChangeLog
    trunk/gcc/go/go-gcc.cc
    trunk/gcc/go/gofrontend/MERGE
    trunk/libgo/runtime/go-ffi.c
Comment 3 Ian Lance Taylor 2016-08-08 19:55:16 UTC
Fixed.