[build] Support libgo on Solaris 2

Rainer Orth ro@CeBiTec.Uni-Bielefeld.DE
Wed Jan 5 19:38:00 GMT 2011


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

  <sys/types.h> 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 <sys/stat.h>.

* 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 <nil>: 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  <ro@CeBiTec.Uni-Bielefeld.DE>

	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
 


-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University



More information about the Gcc-patches mailing list