From patchwork Wed Jan 5 18:55:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rainer Orth X-Patchwork-Id: 77623 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 19A48B70FB for ; Thu, 6 Jan 2011 05:56:35 +1100 (EST) Received: (qmail 7006 invoked by alias); 5 Jan 2011 18:56:33 -0000 Received: (qmail 6993 invoked by uid 22791); 5 Jan 2011 18:56:28 -0000 X-SWARE-Spam-Status: No, hits=-0.0 required=5.0 tests=AWL, BAYES_50, TW_AJ, TW_BJ, TW_IV, TW_JC, TW_JF, TW_JS, TW_RW, TW_SN, TW_TW, TW_XP, TW_XR, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from snape.CeBiTec.Uni-Bielefeld.DE (HELO smtp-relay.CeBiTec.Uni-Bielefeld.DE) (129.70.160.84) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 05 Jan 2011 18:56:13 +0000 Received: from localhost (localhost.CeBiTec.Uni-Bielefeld.DE [127.0.0.1]) by smtp-relay.CeBiTec.Uni-Bielefeld.DE (Postfix) with ESMTP id 91019200; Wed, 5 Jan 2011 19:56:10 +0100 (CET) Received: from smtp-relay.CeBiTec.Uni-Bielefeld.DE ([127.0.0.1]) by localhost (malfoy.CeBiTec.Uni-Bielefeld.DE [127.0.0.1]) (amavisd-new, port 10024) with LMTP id NL7aeCgbIVMO; Wed, 5 Jan 2011 19:55:49 +0100 (CET) Received: from manam.CeBiTec.Uni-Bielefeld.DE (manam.CeBiTec.Uni-Bielefeld.DE [129.70.161.120]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp-relay.CeBiTec.Uni-Bielefeld.DE (Postfix) with ESMTPS id B7FF41FF; Wed, 5 Jan 2011 19:55:49 +0100 (CET) Received: (from ro@localhost) by manam.CeBiTec.Uni-Bielefeld.DE (8.14.4+Sun/8.14.4/Submit) id p05ItmXj017161; Wed, 5 Jan 2011 19:55:48 +0100 (MET) From: Rainer Orth To: gcc-patches@gcc.gnu.org Cc: Paolo Bonzini , Ian Lance Taylor Subject: [build] Support libgo on Solaris 2 Date: Wed, 05 Jan 2011 19:55:48 +0100 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (usg-unix-v) MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org While I had some spare time over the last couple of days, I tried with some to get Go working on Solaris 11/x86. The patch below captures the current state of affairs, but is not yet sufficient to get everything working. For the moment, I'm reporting issues here as we go, but could certainly file PRs if that's preferred. The problems were only in libgo so far (oh wonder :-): * Building in a configured tree doesn't work, e.g. mksysinfo.sh uses ${CC:-gcc}, which is wrong if the installed gcc isn't Go-capably (which it most likely isn't). Either fix the invokation or substitute the value into mksysinfo.sh. * go1 is linked with libstdc++.so.6, but if that isn't installed (or too old), compilation won't work. I had to manually set LD_LIBRARY_PATH (both for libstdc++.so.6 and libgcc_s.so.1) to avoid that. * Since mksysinfo.sh uses set -e, it silently exists upon the first error. This script is massively unportable (e.g. if ! ...), heavily Linux-specific, and I'm uncertain if this is the best approach here. Anyway, I've removed the set -e and manually fixed the issues with the generated sysinfo.go until it's decided how to proceed. Perhaps it could be replaced by a C program and autoconf tests? Here are the changes I had to make: -type _pad128_t struct { _q float80; } -type _upad128_t struct { _q float80; } +type _pad128_t struct { _l [4]int32; } +type _upad128_t struct { _l [4]uint32; } Without this, I get sysinfo.go:1841:28: error: use of undefined type 'float80' sysinfo.go:1841:25: error: struct field type is incomplete has typedef union { long double _q; int32_t _l[4]; } pad128_t; I've now idea why long double causes problems. I got sysinfo.go:2132:5: error: redefinition of '_timezone' sysinfo.go:1921:6: note: previous definition of '_timezone' was here corresponding to type _timezone struct { tz_minuteswest int32; tz_dsttime int32; } var _timezone int32 I'm removing the var for now. Similar issue for _utsname. +const O_ASYNC = 0 Provide dummy, not available on Solaris. +const _PTRACE_TRACEME = 0 Same, ptrace is more of an issue, see blow. @@ -2756,7 +2756,10 @@ type Timeval struct { Sec Timeval_sec_t; type Timespec_sec_t int32 type Timespec_nsec_t int32 type Timespec struct { Sec Timespec_sec_t; Nsec Timespec_nsec_t; } -type Stat_t struct { Dev uint32; st_pad1 [2+1]int32; Ino uint32; Mode uint32; Nlink uint32; Uid uint32; Gid uint32; Rdev uint32; st_pad2 [1+1]int32; Size int32; st_pad3 int32; Atime _timestruc_t; Mtime _timestruc_t; Ctime _timestruc_t; Blksize int32; Blocks int32; st_fstype [15+1]int8; st_pad4 [7+1]int32; } +type Timestruc_sec_t int32 +type Timestruc_nsec_t int32 +type Timestruc struct { Sec Timestruc_sec_t; Nsec Timestruc_nsec_t; } +type Stat_t struct { Dev uint32; st_pad1 [2+1]int32; Ino uint32; Mode uint32; Nlink uint32; Uid uint32; Gid uint32; Rdev uint32; st_pad2 [1+1]int32; Size int32; st_pad3 int32; Atime Timestruc; Mtime Timestruc; Ctime Timestruc; Blksize int32; Blocks int32; st_fstype [15+1]int8; st_pad4 [7+1]int32; } type Dirent struct { Ino uint32; Off int32; Reclen uint16; Name [0+1]byte; } type DIR _DIR type Rusage struct { Utime Timeval; Stime Timeval; Maxrss int32; Ixrss int32; Idrss int32; Isrss int32; Minflt int32; Majflt int32; Nswap int32; Inblock int32; Oublock int32; Msgsnd int32; Msgrcv int32; Nsignals int32; Nvcsw int32; Nivcsw int32; } Solaris uses timestruc_t in . * It's currently hard to identify which libgo sources require which OS features and which are completely portable. The deeply nested automake conditionals don't help either, especially since they give no real indication why which file is used where. I've tried to improve things by adding comments liberally. As usual, Solaris needs -lsocket (and eventually -lnsl, though things work without so far), so I've added support for NET_LIBS. The configure test is obviously a hack that needs to be done properly, though the code in libjava/configure.ac might be overkill. * Several other changes should be clear from comments in the code. Unfortunately, many files in syscalls seem to be largely identical copies of each other. It would be helpful to modularize this somewhat. I often see dummy implementations (like go/debug/regs/{proc, regs}_*); perhaps there should be a single dummy to use until a real one is provided? * ptrace(3C) is used unconditionally in exec.go, but Solaris provides it only in 32-bit mode and for backwards compatibility, suggesting to move over to /proc instead. We obviously need to do something about this, but first things first. * testsuite/gotest again calls nm -s, who'se output format isn't portable. nm -ps works on Solaris, though. * Currently, libgo prefers the gotest-bases testsuite instead of DejaGnu, which IMO is highly unfortunate since this gives us yet another test framework in GCC with a different output format and not integrated with mail-report.log. We should strive for the opposite here! Even if I force the DejaGnu-based one, it fails immediately since it sets GO_UNDER_TEST while the testsuite in gcc/testsuite/lib uses GOC_UNDER_TEST :-) Even with this fixed, no dice, but I haven't investigated further yet. CHECK in Makefile.am uses echo -n, again unportable. * The build relies on objcopy, which is available as gobjcopy on Solaris 10+. configure.ac should account for that, but it's a general issue not only pertaining to libgo. * With this stuff fixed, I can finally get a clean compile and link of the 32-bit libgo. 64-bit is strange, though: the build fails with mv: cannot stat `version.o': No such file or directory make[6]: *** [runtime/libruntime.a] Error 1 libtool: compile: mv -f "vector.o" "container/.libs/libvector.a.o" mv: cannot stat `vector.o': No such file or directory make[6]: *** [container/libvector.a] Error 1 libtool: compile: mv -f "tables.o" "unicode/.libs/libunicode.a.o" mv: cannot stat `tables.o': No such file or directory make[6]: *** [unicode/libunicode.a] Error 1 libtool: compile: mv -f "unsafe.o" "math/.libs/libmath.a.o" mv: cannot stat `unsafe.o': No such file or directory make[6]: *** [math/libmath.a] Error 1 make[6]: Target `all-am' not remade because of errors. and I find that in (some, all?) compilations with several .go source files, only the first is compiled. I've yet no idea what's going on here. * make check-go results are pretty good, fortunately: === go Summary === # of expected passes 1013 # of unexpected failures 3 # of expected failures 18 # of untested testcases 2 FAIL: go.test/test/env.go execution, -O2 -g $GOARCH: no such environment variable Where would this be set? FAIL: go.test/test/recover2.go compilation, -O2 -g output is: /vol/gcc/src/hg/trunk/solaris/gcc/testsuite/go.test/test/recover2.go:86:13: error: reference to undefined identifier 'syscall.ARCH' func test7() { if syscall.ARCH == "arm" || syscall.OS == "nacl" { // ARM doesn't have integer divide trap yet return } Only defined in libgo/syscalls/syscall_linux_*.go, probably need 4 files: syscall_solaris_{386, amd64, sparc, sparcv9}.go What is syscall.ARCH supposed to be anyway? I.e. how would I handle Solaris/SPARC (always 64-bit kernel), 32 or 64-bit binaries Solaris/x86 (32 or 64-bit kernel), 32 or 64-bit binaries FAIL: go.test/test/recover3.go compilation, -O2 -g Same issue. FAIL: go.test/test/chan/goroutines.go execution, -O2 -g /vol/gcc/src/hg/trunk/solaris/libgo/runtime/go-go.c:251: libgo assertion failure __go_go: /* Start the thread. */ i = pthread_create (&tid, &attr, start_go_thread, newm); __go_assert (i == 0); No wonder, the test tries to create 10000 threads, pthread_creates returns with ENOMEM at 3944 threads, each taking 4 kB of stack, default stack limit is 10240 kB. In pmap output, I see 08062000 160K rwx-- [ heap ] 081BD000 4K rwx-R [ anon ] 082BC000 4K rwx-R [ anon ] 083BB000 4K rwx-R [ anon ] 084BA000 4K rwx-R [ anon ] 085B9000 4K rwx-R [ anon ] 086B8000 4K rwx-R [ anon ] 087B7000 4K rwx-R [ stack tid=3938 ] 088B6000 4K rwx-R [ stack tid=3937 ] The stacks are placed widely apart, easily exhausting the address space. The delta is FF000, i.e 1044480, close to 1 MB, any way to influence that? pthread_attr_init(3C) documents Attribute Default Value Meaning of Default stacksize 0 1 or 2 megabyte Maybe we need to lower the default for Solaris? But how low is still safe? * libgo make check results are not too bad either. I've manually cleaned the output for two issues: the echo -n stuff above and ld warnings: asn1 ld: warning: relocation warning: R_386_COPY: file /vol/gcc/obj/gcc-4.6.0-20101223/11-gcc-go/i386-pc-solaris2.11/libgo/.libs/libgo.so: symbol __go_tdn_libgo_reflect.reflect.Type: relocation bound to a symbol with STV_PROTECTED visibility I still need to look into them. So, without further ado, here are the full results. There's certainly something fishy with the netchan tests: the testsuite was run on a laptop without any network connectivity and should be able to handle that. I'll retry with network and see what changes. log PASS expvar PASS exec PASS ebnf PASS flag flag provided but not defined: -x PASS html PASS asn1 PASS bufio PASS io PASS json PASS mime PASS bytes PASS netchan 2011/01/04 14:23:17 netchan export: sending error to client:no such channel: notAChannel 2011/01/04 14:23:17 netchan import: response error:no such channel: notAChannel PASS fmt mallocs per Sprintf(""): 1 mallocs per Sprintf("xxx"): 1 mallocs per Sprintf("%x"): 3 mallocs per Sprintf("%x %x"): 4 PASS path --- FAIL: path.TestGlob Glob(`mat?h.go`) = []string{} want match.go Glob(`*`) = []string{} want match.go --- FAIL: path.TestWalk node testdata/a mark = 0; expected 1 node testdata/b mark = 0; expected 1 node testdata/c mark = 0; expected 1 node testdata/d mark = 0; expected 1 node testdata/d/x mark = 0; expected 1 node testdata/d/y mark = 0; expected 1 node testdata/d/z mark = 0; expected 1 node testdata/d/z/u mark = 0; expected 1 node testdata/d/z/v mark = 0; expected 1 node testdata/a mark = 0; expected 1 node testdata/b mark = 0; expected 1 node testdata/c mark = 0; expected 1 node testdata/d mark = 0; expected 1 node testdata/d/x mark = 0; expected 1 node testdata/d/y mark = 0; expected 1 node testdata/d/z mark = 0; expected 1 node testdata/d/z/u mark = 0; expected 1 node testdata/d/z/v mark = 0; expected 1 1. error expected, none found node testdata/a mark = 0; expected 1 node testdata/b mark = 0; expected 1 node testdata/c mark = 0; expected 1 node testdata/d mark = 0; expected 1 removeTree: remove testdata: File exists FAIL make: *** [path/check] Error 1 gob PASS patch PASS cmath PASS http --- FAIL: http.TestClient Get http://www.google.com/robots.txt: dial tcp www.google.com:http: dial udp 129.70.160.15:53: Network is unreachable --- FAIL: http.TestClientHead dial tcp www.google.com:http: dial udp 129.70.160.15:53: Network is unreachable --- FAIL: http.TestRedirect Get http://google.com/: dial tcp google.com:http: dial udp 129.70.160.15:53: Network is unreachable FAIL make: *** [http/check] Error 1 regexp PASS scanner PASS rpc 2011/01/04 14:23:22 Test RPC server listening on 127.0.0.1:48456 2011/01/04 14:23:22 Test HTTP RPC server listening on 127.0.0.1:47576 2011/01/04 14:23:22 rpc: tearing down Arith connection: gob: type mismatch: no fields matched compiling decoder for Args 2011/01/04 14:23:22 rpc: client protocol error: unexpected EOF 2011/01/04 14:23:22 rpc: client protocol error: gob: type mismatch: no fields matched compiling decoder for Reply 2011/01/04 14:23:22 rpc: client protocol error: gob: type mismatch: no fields matched compiling decoder for Reply 2011/01/04 14:23:23 NewServer test RPC server listening on 127.0.0.1:36543 2011/01/04 14:23:23 ArgNotPointer arg type not a pointer: rpc.Args 2011/01/04 14:23:23 rpc Register: type ArgNotPointer has no exported methods of suitable type 2011/01/04 14:23:23 ReplyNotPointer reply type not a pointer: rpc.Reply 2011/01/04 14:23:23 rpc Register: type ReplyNotPointer has no exported methods of suitable type 2011/01/04 14:23:23 ArgNotPublic argument type not exported: *rpc.local 2011/01/04 14:23:23 rpc Register: type ArgNotPublic has no exported methods of suitable type 2011/01/04 14:23:23 ReplyNotPublic reply type not exported: *rpc.local 2011/01/04 14:23:23 rpc Register: type ReplyNotPublic has no exported methods of suitable type PASS smtp PASS reflect PASS sort PASS os --- FAIL: os_test.TestChdirAndGetwd Getwd returned "/usr/bin" want "/bin" --- FAIL: os_test.TestHostname open /proc/sys/kernel/hostname: No such file or directory --- FAIL: os_test.TestReaddir could not find env_unix.go could not find error.go could not find file.go could not find os_test.go could not find time.go could not find types.go could not find group could not find hosts could not find passwd --- FAIL: os_test.TestReaddirnames could not find env_unix.go could not find error.go could not find file.go could not find os_test.go could not find time.go could not find types.go could not find group could not find hosts could not find passwd --- FAIL: os_test.TestRemoveAll RemoveAll "_obj/_TestRemoveAll_" (first): remove _obj/_TestRemoveAll_: File exists FAIL make: *** [os/check] Error 1 rand PASS syslog --- FAIL: syslog.TestDial Dial() failed: Unix syslog delivery error --- FAIL: syslog.TestNew New() failed: Unix syslog delivery error --- FAIL: syslog.TestNewLogger NewLogger() failed FAIL make: *** [syslog/check] Error 1 sync PASS runtime PASS strings PASS tabwriter PASS try PASS template PASS utf16 PASS strconv PASS net --- FAIL: net.TestDialGoogle -- 74.125.19.99:80 -- Dial("tcp", "", "74.125.19.99:80") = _, dial tcp 74.125.19.99:80: Network is unreachable Dial("tcp4", "", "74.125.19.99:80") = _, dial tcp4 74.125.19.99:80: Network is unreachable Dial("tcp4", "", "74.125.19.99:80") = _, dial tcp4 74.125.19.99:80: Network is unreachable Dial("tcp6", "", "74.125.19.99:80") = _, dial tcp6 74.125.19.99:80: Network is unreachable -- www.google.com:80 -- Dial("tcp", "", "www.google.com:80") = _, dial tcp www.google.com:80: dial udp 129.70.160.15:53: Network is unreachable Dial("tcp4", "", "www.google.com:80") = _, dial tcp4 www.google.com:80: dial udp 129.70.160.15:53: Network is unreachable Dial("tcp4", "", "www.google.com:80") = _, dial tcp4 www.google.com:80: dial udp 129.70.160.15:53: Network is unreachable Dial("tcp6", "", "www.google.com:80") = _, dial tcp6 www.google.com:80: dial udp 129.70.160.15:53: Network is unreachable -- 74.125.19.99:http -- Dial("tcp", "", "74.125.19.99:http") = _, dial tcp 74.125.19.99:http: unknown port tcp/http Dial("tcp4", "", "74.125.19.99:http") = _, dial tcp4 74.125.19.99:http: unknown port tcp/http Dial("tcp4", "", "74.125.19.99:http") = _, dial tcp4 74.125.19.99:http: unknown port tcp/http Dial("tcp6", "", "74.125.19.99:http") = _, dial tcp6 74.125.19.99:http: unknown port tcp/http -- www.google.com:http -- Dial("tcp", "", "www.google.com:http") = _, dial tcp www.google.com:http: dial udp 129.70.160.15:53: Network is unreachable Dial("tcp4", "", "www.google.com:http") = _, dial tcp4 www.google.com:http: dial udp 129.70.160.15:53: Network is unreachable Dial("tcp4", "", "www.google.com:http") = _, dial tcp4 www.google.com:http: dial udp 129.70.160.15:53: Network is unreachable Dial("tcp6", "", "www.google.com:http") = _, dial tcp6 www.google.com:http: dial udp 129.70.160.15:53: Network is unreachable -- 074.125.019.099:0080 -- Dial("tcp", "", "074.125.019.099:0080") = _, dial tcp 74.125.19.99:80: Network is unreachable Dial("tcp4", "", "074.125.019.099:0080") = _, dial tcp4 74.125.19.99:80: Network is unreachable Dial("tcp4", "", "074.125.019.099:0080") = _, dial tcp4 74.125.19.99:80: Network is unreachable Dial("tcp6", "", "074.125.019.099:0080") = _, dial tcp6 74.125.19.99:80: Network is unreachable -- [::ffff:74.125.19.99]:80 -- Dial("tcp", "", "[::ffff:74.125.19.99]:80") = _, dial tcp 74.125.19.99:80: Network is unreachable Dial("tcp6", "", "[::ffff:74.125.19.99]:80") = _, dial tcp6 74.125.19.99:80: Network is unreachable -- [::ffff:4a7d:1363]:80 -- Dial("tcp", "", "[::ffff:4a7d:1363]:80") = _, dial tcp 74.125.19.99:80: Network is unreachable Dial("tcp6", "", "[::ffff:4a7d:1363]:80") = _, dial tcp6 74.125.19.99:80: Network is unreachable -- [0:0:0:0:0000:ffff:74.125.19.99]:80 -- Dial("tcp", "", "[0:0:0:0:0000:ffff:74.125.19.99]:80") = _, dial tcp 74.125.19.99:80: Network is unreachable Dial("tcp6", "", "[0:0:0:0:0000:ffff:74.125.19.99]:80") = _, dial tcp6 74.125.19.99:80: Network is unreachable -- [0:0:0:0:000000:ffff:74.125.19.99]:80 -- Dial("tcp", "", "[0:0:0:0:000000:ffff:74.125.19.99]:80") = _, dial tcp 74.125.19.99:80: Network is unreachable Dial("tcp6", "", "[0:0:0:0:000000:ffff:74.125.19.99]:80") = _, dial tcp6 74.125.19.99:80: Network is unreachable -- [0:0:0:0:0:ffff::74.125.19.99]:80 -- Dial("tcp", "", "[0:0:0:0:0:ffff::74.125.19.99]:80") = _, dial tcp 74.125.19.99:80: Network is unreachable Dial("tcp6", "", "[0:0:0:0:0:ffff::74.125.19.99]:80") = _, dial tcp6 74.125.19.99:80: Network is unreachable --- FAIL: net.TestGoogleSRV failed: dial udp 129.70.160.15:53: Network is unreachable no results --- FAIL: net.TestLookupPort LookupPort("tcp", "gopher") = 0, unknown port tcp/gopher; want 70 LookupPort("tcp", "http") = 0, unknown port tcp/http; want 80 --- FAIL: net.TestTimeoutTCP dial tcp 74.125.19.99:80 failed: dial tcp 74.125.19.99:80: Network is unreachable --- FAIL: net.TestUnixDatagramServer TestPacket unixgram /tmp/gotest1.net /tmp/gotest1.net TestPacket unixgram @gotest1/net @gotest1/net net.ListenPacket("unixgram", "@gotest1/net") = _, dial unixgram : No such file or directory --- FAIL: net.TestUnixServer Test unix /tmp/gotest.net /tmp/gotest.net Test unix @gotest/net @gotest/net net.Listen("unix", "@gotest/net") = _, listen unix @gotest/net: No such file or directory FAIL make: *** [net/check] Error 1 archive/zip PASS unicode PASS websocket 2011/01/04 14:23:33 Test WebSocket server listening on 127.0.0.1:63893 PASS compress/gzip PASS xml PASS utf8 PASS time --- FAIL: time_test.TestFormat ANSIC expected "Thu Feb 4 21:00:57 2010" got "Fri Feb 5 05:00:57 2010" UnixDate expected "Thu Feb 4 21:00:57 PST 2010" got "Fri Feb 5 05:00:57 UTC 2010" RubyDate expected "Thu Feb 04 21:00:57 -0800 2010" got "Fri Feb 05 05:00:57 +0000 2010" RFC822 expected "04 Feb 10 2100 PST" got "05 Feb 10 0500 UTC" RFC850 expected "Thursday, 04-Feb-10 21:00:57 PST" got "Friday, 05-Feb-10 05:00:57 UTC" RFC1123 expected "Thu, 04 Feb 2010 21:00:57 PST" got "Fri, 05 Feb 2010 05:00:57 UTC" RFC3339 expected "2010-02-04T21:00:57-08:00" got "2010-02-05T05:00:57Z" Kitchen expected "9:00PM" got "5:00AM" am/pm expected "9pm" got "5am" AM/PM expected "9PM" got "5AM" --- FAIL: time_test.TestParse UnixDate: bad tz offset: 0 not -28800 RFC850: bad tz offset: 0 not -28800 RFC1123: bad tz offset: 0 not -28800 --- FAIL: time_test.TestSecondsToLocalTime SecondsToLocalTime(0): want={Year:1969 Month:12 Day:31 Hour:16 Minute:0 Second:0 Weekday:3 ZoneOffset:-28800 Zone:PST} have={Year:1970 Month:1 Day:1 Hour:0 Minute:0 Second:0 Weekday:4 ZoneOffset:0 Zone:UTC} SecondsToLocalTime(1221681866): want={Year:2008 Month:9 Day:17 Hour:13 Minute:4 Second:26 Weekday:3 ZoneOffset:-25200 Zone:PDT} have={Year:2008 Month:9 Day:17 Hour:20 Minute:4 Second:26 Weekday:3 ZoneOffset:0 Zone:UTC} FAIL make: *** [time/check] Error 1 archive/tar PASS container/heap PASS container/list PASS compress/flate PASS compress/zlib PASS crypto/hmac PASS crypto/aes PASS crypto/blowfish PASS crypto/md4 PASS crypto/md5 PASS math PASS crypto/ocsp PASS crypto/rc4 PASS crypto/ripemd160 PASS container/vector PASS big PASS crypto/rand PASS crypto/sha1 PASS crypto/subtle PASS crypto/sha512 PASS crypto/sha256 PASS crypto/block PASS crypto/xtea PASS crypto/x509 PASS debug/macho PASS debug/elf PASS debug/pe PASS encoding/ascii85 PASS encoding/base64 PASS encoding/git85 PASS encoding/binary PASS encoding/pem PASS debug/dwarf PASS encoding/hex PASS exp/draw PASS exp/datafmt PASS go/scanner PASS hash/adler32 PASS crypto/tls PASS hash/crc32 PASS hash/crc64 PASS go/typechecker PASS index/suffixarray PASS go/parser --- FAIL: parser.TestParse4 incorrect number of packages: 0 package "parser" not found FAIL make: *** [go/parser/check] Error 1 mime/multipart PASS io/ioutil --- FAIL: ioutil_test.TestReadDir ReadDir .: test file not found FAIL make: *** [io/ioutil/check] Error 1 os/signal signal_test.go:14:26: error: reference to undefined identifier 'syscall.SYS_KILL' make: *** [os/signal/check] Error 1 net/textproto PASS testing/quick PASS testing/script PASS rpc/jsonrpc 2011/01/04 14:24:09 rpc: client protocol error: Invalid argument PASS go/printer PASS image/png PASS crypto/rsa PASS exp/eval PASS container/ring PASS Still, overall, they don't look too bad to me and probably stem from just a few issues. So here you go, patch included below. Any comments and suggestions welcome on how to procede from here, especially on how to get this into GCC. So far, it only seems to touch GCC-specific code, so my assignment should suffice. Perhaps there should be a libgo/ChangeLog? Btw., could this be 4.6.0 material, given how new Go support in GCC is? Rainer 2011-01-03 Rainer Orth libgo: * configure.ac (LIBGO_IS_SOLARIS): New conditional. Sort os cases. (LIBGO_IS_SPARC): New conditional. Sort arch cases. * Makefile.am (GOARCH): Handle sparc. Sort cases. (GOOS): Handle solaris. Sort cases. (proc_file, regs_file): Sort by OS. (syscall_os_file): Handle Solaris. (syscall_socket_os_file): Use syscalls/socket_bsd.go on non-Linux. * configure: Regenerate. * Makefile.in: Regenerate. * mksysinfo.sh: Disable set -e. * syscalls/syscall_solaris.go: New file. diff -r 779b637a1983 libgo/Makefile.am --- a/libgo/Makefile.am Wed Jan 05 14:33:43 2011 +0100 +++ b/libgo/Makefile.am Wed Jan 05 14:38:06 2011 +0100 @@ -1,6 +1,6 @@ # Makefile.am -- Go library Makefile. -# Copyright 2009, 2010 The Go Authors. All rights reserved. +# Copyright 2009, 2010, 2011 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. @@ -592,12 +592,19 @@ go/mime/mediatype.go \ go/mime/type.go -if LIBGO_IS_RTEMS -go_net_fd_os_file = go/net/fd_rtems.go -go_net_newpollserver_file = go/net/newpollserver_rtems.go -else +if LIBGO_IS_LINUX +# Uses epoll(2), probably Linux-specfic. go_net_fd_os_file = go/net/fd_linux.go go_net_newpollserver_file = go/net/newpollserver.go +else +# Uses select(2), probably portable. +go_net_fd_os_file = go/net/fd_rtems.go +if LIBGO_IS_SOLARIS +# Solaris doesn't support self-connected sockets, it seems. +go_net_newpollserver_file = go/net/newpollserver.go +else +go_net_newpollserver_file = go/net/newpollserver_rtems.go +endif endif go_net_files = \ @@ -684,34 +691,41 @@ if LIBGO_IS_386 GOARCH = 386 else +if LIBGO_IS_ARM +GOARCH = arm +else +if LIBGO_IS_SPARC +GOARCH = sparc if LIBGO_IS_X86_64 GOARCH = amd64 else -if LIBGO_IS_ARM -GOARCH = arm -else GOARCH = unknown endif endif endif +endif -if LIBGO_IS_LINUX -GOOS = linux -else if LIBGO_IS_DARWIN GOOS = darwin else if LIBGO_IS_FREEBSD GOOS = freebsd else +if LIBGO_IS_LINUX +GOOS = linux +else if LIBGO_IS_RTEMS GOOS = rtems else +if LIBGO_IS_SOLARIS +GOOS = solaris +else GOOS = unknown endif endif endif endif +endif version.go: s-version; @true s-version: Makefile @@ -929,18 +943,6 @@ go/debug/pe/file.go \ go/debug/pe/pe.go -if LIBGO_IS_LINUX -proc_file = go/debug/proc/proc_linux.go -if LIBGO_IS_386 -regs_file = go/debug/proc/regs_linux_386.go -else -if LIBGO_IS_X86_64 -regs_file = go/debug/proc/regs_linux_amd64.go -else -regs_file = -endif -endif -else if LIBGO_IS_DARWIN proc_file = go/debug/proc/proc_darwin.go if LIBGO_IS_386 @@ -965,6 +967,18 @@ endif endif else +if LIBGO_IS_LINUX +proc_file = go/debug/proc/proc_linux.go +if LIBGO_IS_386 +regs_file = go/debug/proc/regs_linux_386.go +else +if LIBGO_IS_X86_64 +regs_file = go/debug/proc/regs_linux_amd64.go +else +regs_file = +endif +endif +else proc_file = regs_file = endif @@ -1104,9 +1118,13 @@ endif endif else +if LIBGO_IS_SOLARIS +syscall_os_file = syscalls/syscall_solaris.go +else syscall_os_file = syscall_arch_file = endif +endif if LIBGO_IS_RTEMS syscall_exec_os_file = syscalls/exec_stubs.go @@ -1118,8 +1136,18 @@ syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go else syscall_exec_os_file = syscalls/exec.go +if LIBGO_IS_LINUX +syscall_socket_epoll_file = syscalls/socket_epoll.go syscall_socket_os_file = syscalls/socket_linux.go -syscall_socket_epoll_file = syscalls/socket_epoll.go +else +if LIBGO_IS_SOLARIS +syscall_socket_os_file = syscalls/socket_solaris.go +else +# FIXME: Really everywhere else? +syscall_socket_os_file = syscalls/socket_bsd.go +endif +endif +# FIXME: Works beyond Linux? syscall_sysfile_os_file = syscalls/sysfile_linux.go syscall_syscall_file = syscalls/syscall.go syscall_errstr_file = syscalls/errstr.go @@ -1268,7 +1296,8 @@ libgo_la_SOURCES = $(runtime_files) -libgo_la_LIBADD = $(libgo_go_objs) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) +libgo_la_LIBADD = $(libgo_go_objs) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) \ + $(NET_LIBS) libgobegin_a_SOURCES = \ runtime/go-main.c @@ -1284,7 +1313,7 @@ GOLINK = $(LIBTOOL) --tag GO --mode-link $(GOC) \ $(OPT_LDFLAGS) $(SECTION_LDFLAGS) $(AM_GOCFLAGS) $(LTLDFLAGS) \ - $(PTHREAD_LIBS) $(MATH_LIBS) -o $@ + $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS) -o $@ # Build a package. BUILDARCHIVE = \ @@ -1300,6 +1329,7 @@ .a.la: $(LINK) $<.lo +# FIXME: Should be configure option, why not use DejaGnu by default? if LIBGO_IS_RTEMS use_dejagnu = yes else diff -r 779b637a1983 libgo/configure.ac --- a/libgo/configure.ac Wed Jan 05 14:33:43 2011 +0100 +++ b/libgo/configure.ac Wed Jan 05 14:38:06 2011 +0100 @@ -1,6 +1,6 @@ # configure.ac -- Go library configure script. -# Copyright 2009 The Go Authors. All rights reserved. +# Copyright 2009, 2011 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. @@ -116,26 +116,36 @@ is_freebsd=no is_linux=no is_rtems=no +is_solaris=no case ${host} in - *-*-darwin*) is_darwin=yes ;; - *-*-freebsd*) is_freebsd=yes ;; - *-*-linux*) is_linux=yes ;; - *-*-rtems*) is_rtems=yes ;; + *-*-darwin*) is_darwin=yes ;; + *-*-freebsd*) is_freebsd=yes ;; + *-*-linux*) is_linux=yes ;; + *-*-rtems*) is_rtems=yes ;; + *-*-solaris2*) is_solaris=yes ;; esac AM_CONDITIONAL(LIBGO_IS_DARWIN, test $is_darwin = yes) AM_CONDITIONAL(LIBGO_IS_FREEBSD, test $is_freebsd = yes) AM_CONDITIONAL(LIBGO_IS_LINUX, test $is_linux = yes) AM_CONDITIONAL(LIBGO_IS_RTEMS, test $is_rtems = yes) +AM_CONDITIONAL(LIBGO_IS_SOLARIS, test $is_solaris = yes) is_386=no +is_arm=no +is_sparc=no is_x86_64=no -is_arm=no case ${host} in + arm*-*-* | strongarm*-*-* | ep9312*-*-* | xscale-*-*) + is_arm=yes + ;; changequote(,)dnl i[34567]86-*-*) changequote([,])dnl is_386=yes ;; + sparc*-*-*) + is_sparc=yes + ;; x86_64-*-*) if test "$with_multisubdir" = "32"; then is_386=yes @@ -143,13 +153,11 @@ is_x86_64=yes fi ;; - arm*-*-* | strongarm*-*-* | ep9312*-*-* | xscale-*-*) - is_arm=yes - ;; esac AM_CONDITIONAL(LIBGO_IS_386, test $is_386 = yes) AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes) AM_CONDITIONAL(LIBGO_IS_ARM, test $is_arm = yes) +AM_CONDITIONAL(LIBGO_IS_SPARC, test $is_sparc = yes) dnl Use -fsplit-stack when compiling C code if available. AC_CACHE_CHECK([whether -fsplit-stack is supported], @@ -192,6 +200,13 @@ AC_CHECK_LIB([m], [sqrt], MATH_LIBS=-lm) AC_SUBST(MATH_LIBS) +dnl Test for the -lsocket library. +NET_LIBS= +dnl FIXME: How to do this properly? +dnl There's code in libjava/configure.ac to handle this. +NET_LIBS=-lsocket +AC_SUBST(NET_LIBS) + dnl Test whether the compiler supports the -pthread option. AC_CACHE_CHECK([whether -pthread is supported], [ac_cv_libgo_pthread_supported], diff -r 779b637a1983 libgo/mksysinfo.sh --- a/libgo/mksysinfo.sh Wed Jan 05 14:33:43 2011 +0100 +++ b/libgo/mksysinfo.sh Wed Jan 05 14:38:06 2011 +0100 @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright 2009 The Go Authors. All rights reserved. +# Copyright 2009, 2011 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. @@ -19,7 +19,7 @@ CC=${CC:-gcc} OUT=tmp-sysinfo.go -set -e +#set -e rm -f sysinfo.go diff -r 779b637a1983 libgo/syscalls/socket.go --- a/libgo/syscalls/socket.go Wed Jan 05 14:33:43 2011 +0100 +++ b/libgo/syscalls/socket.go Wed Jan 05 14:38:06 2011 +0100 @@ -1,6 +1,6 @@ // socket.go -- Socket handling. -// Copyright 2009 The Go Authors. All rights reserved. +// Copyright 2009, 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -12,6 +12,7 @@ import "unsafe" +// FIXME: Partially Linux-specific, at least SizeofSockaddrInet6. const SizeofSockaddrInet4 = 16 const SizeofSockaddrInet6 = 28 const SizeofSockaddrUnix = 110 diff -r 779b637a1983 libgo/syscalls/socket_solaris.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgo/syscalls/socket_solaris.go Wed Jan 05 14:38:06 2011 +0100 @@ -0,0 +1,144 @@ +// socket_linux.go -- Socket handling specific to Solaris. + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Low-level socket interface. +// Only for implementing net package. + +// DO NOT USE DIRECTLY. + +package syscall + +import "unsafe" + +type RawSockaddrInet4 struct { + Family uint16; + Port uint16; + Addr [4]byte /* in_addr */; + Zero [8]uint8; +} + +type RawSockaddrInet6 struct { + Family uint16; + Port uint16; + Flowinfo uint32; + Addr [16]byte /* in6_addr */; + Scope_id uint32; + __Src_id uint32; +} + +type RawSockaddrUnix struct { + Family uint16; + Path [108]int8; +} + +type RawSockaddr struct { + Family uint16; + Data [14]int8; +} + +func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) { + if sa.Port < 0 || sa.Port > 0xFFFF { + return nil, 0, EINVAL; + } + sa.raw.Family = AF_INET; + p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); + p[0] = byte(sa.Port>>8); + p[1] = byte(sa.Port); + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i]; + } + return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet4, 0; +} + +func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) { + if sa.Port < 0 || sa.Port > 0xFFFF { + return nil, 0, EINVAL; + } + sa.raw.Family = AF_INET6; + p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)); + p[0] = byte(sa.Port>>8); + p[1] = byte(sa.Port); + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i]; + } + // FIXME: socket.go SizeofSockaddrInet6 is wrong on Solaris due to + // __sin6_src_id member. + //return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6, 0; + return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrInet6 + 4, 0; +} + +func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) { + name := sa.Name; + n := len(name); + if n >= len(sa.raw.Path) || n == 0 { + return nil, 0, EINVAL; + } + sa.raw.Family = AF_UNIX; + for i := 0; i < n; i++ { + sa.raw.Path[i] = int8(name[i]); + } + if sa.raw.Path[0] == '@' { + sa.raw.Path[0] = 0; + } + + // length is family, name, NUL. + return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 1 + Socklen_t(n) + 1, 0; +} + +func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) { + switch rsa.Addr.Family { + case AF_UNIX: + pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)); + sa := new(SockaddrUnix); + if pp.Path[0] == 0 { + // "Abstract" Unix domain socket. + // Rewrite leading NUL as @ for textual display. + // (This is the standard convention.) + // Not friendly to overwrite in place, + // but the callers below don't care. + pp.Path[0] = '@'; + } + + // Assume path ends at NUL. + // This is not technically the Linux semantics for + // abstract Unix domain sockets--they are supposed + // to be uninterpreted fixed-size binary blobs--but + // everyone uses this convention. + n := 0; + for n < len(pp.Path) - 3 && pp.Path[n] != 0 { + n++; + } + bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0])); + sa.Name = string(bytes[0:n]); + return sa, 0; + + case AF_INET: + pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)); + sa := new(SockaddrInet4); + p := (*[2]byte)(unsafe.Pointer(&pp.Port)); + sa.Port = int(p[0])<<8 + int(p[1]); + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i]; + } + return sa, 0; + + case AF_INET6: + pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)); + sa := new(SockaddrInet6); + p := (*[2]byte)(unsafe.Pointer(&pp.Port)); + sa.Port = int(p[0])<<8 + int(p[1]); + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i]; + } + return sa, 0; + } + return nil, EAFNOSUPPORT; +} + +// BindToDevice binds the socket associated with fd to device. +func BindToDevice(fd int, device string) (errno int) { + return ENOSYS +} diff -r 779b637a1983 libgo/syscalls/syscall_solaris.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgo/syscalls/syscall_solaris.go Wed Jan 05 14:38:06 2011 +0100 @@ -0,0 +1,17 @@ +// syscall_solaris.go -- Solaris 2 specific syscall interface. + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syscall + +import "unsafe" + +// FIXME: ptrace(3C) has this, but exec.go expects the next. +//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace") + +func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int __asm__ ("ptrace") + +var dummy *byte +const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy)) diff -r 779b637a1983 libgo/testsuite/gotest --- a/libgo/testsuite/gotest Wed Jan 05 14:33:43 2011 +0100 +++ b/libgo/testsuite/gotest Wed Jan 05 14:38:06 2011 +0100 @@ -272,7 +272,7 @@ # the grep -v eliminates methods and other special names # that have multiple dots. pattern='Test([^a-z].*)?' - tests=$(nm -s _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/') + tests=$(nm -ps _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/') if [ "x$tests" = x ]; then echo 'gotest: warning: no tests matching '$pattern in _gotest_.o $xofile 1>&2 exit 2 diff -r 779b637a1983 libgo/testsuite/lib/libgo.exp --- a/libgo/testsuite/lib/libgo.exp Wed Jan 05 14:33:43 2011 +0100 +++ b/libgo/testsuite/lib/libgo.exp Wed Jan 05 14:38:06 2011 +0100 @@ -1,4 +1,4 @@ -# Copyright (C) 2010 Free Software Foundation, Inc. +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ if {$gccdir != ""} { set gccdir [file dirname $gccdir] } -set GO_UNDER_TEST "$gccdir/gccgo -B$gccdir/" +set GOC_UNDER_TEST "$gccdir/gccgo -B$gccdir/" set TESTING_IN_BUILD_TREE 1 proc go_maybe_build_wrapper { args } { diff -r 779b637a1983 libgo/testsuite/libgo.testmain/testmain.exp --- a/libgo/testsuite/libgo.testmain/testmain.exp Wed Jan 05 14:33:43 2011 +0100 +++ b/libgo/testsuite/libgo.testmain/testmain.exp Wed Jan 05 14:38:06 2011 +0100 @@ -1,4 +1,4 @@ -# Copyright (C) 2010 Free Software Foundation, Inc. +# Copyright (C) 2010, 2011 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -44,7 +44,8 @@ } set object_files [glob -nocomplain "*.o"] -regsub $gluefile $object_files "" object_files +# FIXME: Not found, even with global gluefile!? +#regsub $gluefile $object_files "" object_files lappend options $ld_options