diff mbox

[build] Support libgo on Solaris 2

Message ID yddzkrfnpsb.fsf@manam.CeBiTec.Uni-Bielefeld.DE
State New
Headers show

Commit Message

Rainer Orth Jan. 5, 2011, 6:55 p.m. UTC
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.

Comments

Joseph Myers Jan. 5, 2011, 8:24 p.m. UTC | #1
On Wed, 5 Jan 2011, Rainer Orth wrote:

> * 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.

Since this is a target library, shouldn't it be configured with --host 
being the target and CC being the target compiler?

> * 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.

It's meant to be linked with static libstdc++ to avoid this problem.

> * Since mksysinfo.sh uses set -e, it silently exists upon the first
>   error.  This script is massively unportable (e.g. if ! ...), heavily

What's wrong with "if ! ..."?  It's in POSIX (1992) and install.texi 
documents a POSIX shell should be used when configuring GCC (in general, 
and specifically ksh rather than /bin/sh for Solaris).  Maybe we need to 
use CONFIG_SHELL for running this script - is there anything non-POSIX 
about the script?

> * testsuite/gotest again calls nm -s, who'se output format isn't
>   portable.  nm -ps works on Solaris, though.

And of course for target files the configured target nm should be used.

> * 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.

Again, the configured target objcopy should be used.  I see toplevel 
configure only checks for objcopy for the host not the target; it should 
have a target check added and Makefile.tpl adjusted accordingly.  This may 
not solve your problem, however.
Ian Lance Taylor Jan. 6, 2011, 6:25 a.m. UTC | #2
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> writes:

> The problems were only in libgo so far (oh wonder :-):

Thanks very much for trying this out.


> * 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.

It should work fine if you build using "make all-target-libgo" from the
top level.  I have no objection to making it work if you build in the
libgo directory directly.


> * 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.

If you do not use --disable-bootstrap, then go1 should be built with
-static-libstdc++ and this should not happen.  So, I assume you did
disable bootstrap.  In that case go1 will be built with the installed
g++, and the assumption is that the installed g++ uses a libstdc++.so
which the dynamic linker knows how to find.  I assume that is not the
case on your system, but I don't know what else to do when bootstrap is
disabled.  You can of course use the --with-host-libstdcxx or
--with-stage1-libs options to set -rpath options as appropriate for your
system.


> * 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?

Removing the set -e will just tend to hide problems, though I'm
certainly open to suggestions for how to make the script easier to work
with.  As far as I know "if !" is POSIX, but if it doesn't work it can
be removed easily enough.

The script can be augmented by autoconf tests where that makes sense,
but it can't really be replaced by them.  I don't think a C program is
really right here, because the script is mainly running sed, which is a
job more appropriate for the shell than for a C program.


>   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

The use of float80 is a bug in godump.c.  The Go language used to have a
float80 type but it no longer does.


>   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.

I guess this should be handled in godump.c too, somehow.  In Go all
names are in the same namespace, unlike C.


> * 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.

Thanks.  This stuff is definitely awkward.  Part of the complexity comes
from the master Go library; I want to minimize differences with that.


> * 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.

Where possible, yes.

>   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?

That comes from the master library, which would be the place to fix it.

> * testsuite/gotest again calls nm -s, who'se output format isn't
>   portable.  nm -ps works on Solaris, though.

Actually using -s is a bug inherited from the master gotest script.  The
intent is to use the option which avoids sorting the symbols.

> * 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 :-)

Let's just make the libgo testsuite output match whatever
mail-report.log wants.  Using DejaGNU for the libgo tests will just make
them harder to run.  The output is determined by the CHECK variable in
libgo/Makefile.am.

> * 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.

I think this means that libtool got confused and thought that it had to
pass the sources to gccgo one at a time rather than all at once.  They
must be passed all at once for gccgo to work correctly.  This happens
when some libtool test fails, so check your config.log.

> FAIL: go.test/test/env.go execution,  -O2 -g 
>
> $GOARCH: no such environment variable
>
>   Where would this be set?

This test, like everything under go.test/test, comes from the master
sources.  GOARCH should really be set by go-test.exp.

> 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

The possible values for syscall.ARCH today are: 386, amd64, arm.  For
SPARC we can pick whatever we want, presumably sparc32 and sparc64 or
something like that.  For x86 it should be 386 or amd64.

> 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?

It depends on whether you are using gold with split stack support or
not.  On SPARC you are presumably not, since it is not implemented for
SPARC.  There is no right answer to how low the stack size can get when
split stacks are not supported; it's going to depend on the program.


> * 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.

The symbol should be in the read-only data section.  I'm not sure why
the linker is creating a COPY reloc for it.

>   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.

The netchan test passed; the messages are not meaningful, only the PASS
or FAIL.

> FAIL
> make: *** [path/check] Error 1

Odd.

> FAIL
> make: *** [os/check] Error 1

Some of this is odd, some is just system differences.

> FAIL
> make: *** [time/check] Error 1

Odd.

> go/parser 
> --- FAIL: parser.TestParse4
> 	incorrect number of packages: 0
> 	package "parser" not found
> FAIL
> make: *** [go/parser/check] Error 1

There seems to be something wrong with finding the test data.

> Btw., could this be 4.6.0 material, given how new Go support in GCC is?

Yes, I think so.

> 2011-01-03  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

No ChangeLog file in libgo, the master sources are not in the gcc
repository.  I'm not sure if there is going to be a split in libgo
between gcc-specific code and non-gcc-specific code.  I'm not opposed to
it at all, but there is very little code that is gcc-specific.

Thanks very much for looking at this.

Ian
Joseph Myers Jan. 6, 2011, 1:21 p.m. UTC | #3
On Wed, 5 Jan 2011, Ian Lance Taylor wrote:

> > * 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 :-)
> 
> Let's just make the libgo testsuite output match whatever
> mail-report.log wants.  Using DejaGNU for the libgo tests will just make
> them harder to run.  The output is determined by the CHECK variable in
> libgo/Makefile.am.

DejaGNU generally makes things easier to run if you are using remote 
targets or hosts, testing cross tools, doing installed testing without a 
build tree, etc., because you already have a working configuration for all 
the other testsuites.  Yes, it's *possible* to hook up non-DejaGNU 
testsuites to DejaGNU board files, but it shouldn't be necessary; using a 
single harness (which at present means DejaGNU, and definitely means 
proper test harness software rather than ad hoc shell scripts) for all the 
GCC testsuites is better.
Ian Lance Taylor Jan. 6, 2011, 2:13 p.m. UTC | #4
"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Wed, 5 Jan 2011, Ian Lance Taylor wrote:
>
>> > * 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 :-)
>> 
>> Let's just make the libgo testsuite output match whatever
>> mail-report.log wants.  Using DejaGNU for the libgo tests will just make
>> them harder to run.  The output is determined by the CHECK variable in
>> libgo/Makefile.am.
>
> DejaGNU generally makes things easier to run if you are using remote 
> targets or hosts, testing cross tools, doing installed testing without a 
> build tree, etc., because you already have a working configuration for all 
> the other testsuites.  Yes, it's *possible* to hook up non-DejaGNU 
> testsuites to DejaGNU board files, but it shouldn't be necessary; using a 
> single harness (which at present means DejaGNU, and definitely means 
> proper test harness software rather than ad hoc shell scripts) for all the 
> GCC testsuites is better.

libgo supports using DejaGNU, it just doesn't require it.  We should
make it default to DejaGNU in a cross-configuration (and we should fix
the DejaGNU support).

Ian
Rainer Orth Jan. 10, 2011, 10:50 a.m. UTC | #5
"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Wed, 5 Jan 2011, Rainer Orth wrote:
>
>> * 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.
>
> Since this is a target library, shouldn't it be configured with --host 
> being the target and CC being the target compiler?

It is.  The problem is that this setting of CC isn't communicated to
mksysinfo.sh: either CC should be passed in the environment on the
command line or mksysinfo.sh turned into mksysinfo.in and CC substituted
by configure.

>> * 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.
>
> It's meant to be linked with static libstdc++ to avoid this problem.

True.  I think this happens already if bootstrapping GCC with a C++
compiler.  The trouble is, this depends on HAVE_LD_STATIC_DYNAMIC, whose
detection only works with GNU ld ;-(  Fixed.  I'll check IRIX and Tru64
UNIX once I get there.

>> * Since mksysinfo.sh uses set -e, it silently exists upon the first
>>   error.  This script is massively unportable (e.g. if ! ...), heavily
>
> What's wrong with "if ! ..."?  It's in POSIX (1992) and install.texi 
> documents a POSIX shell should be used when configuring GCC (in general, 
> and specifically ksh rather than /bin/sh for Solaris).  Maybe we need to 
> use CONFIG_SHELL for running this script - is there anything non-POSIX 
> about the script?

I hadn't checked in detail: I only remember having had trouble with if ! -e 
in libjava somewhere, even when using Solaris 2 /bin/ksh.  There's a
section in the Autoconf manual about issues with if !, so it may be
better to avoid id.

>> * testsuite/gotest again calls nm -s, who'se output format isn't
>>   portable.  nm -ps works on Solaris, though.
>
> And of course for target files the configured target nm should be used.

Which would simply be $NM, which would have to be either substituted
into gotest or passed in the environment.

This doesn't help for the nm options to use, though.  I'd have to check
if autoconf provides anything here, but this area has traditionally been
a can of worms (cf. the trouble with nm use in collect2 for LTO lately).

>> * 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.
>
> Again, the configured target objcopy should be used.  I see toplevel 
> configure only checks for objcopy for the host not the target; it should 
> have a target check added and Makefile.tpl adjusted accordingly.  This may 
> not solve your problem, however.

True.  The missing search for the g-prefixed binutils (on Solaris and
elsewhere) is general problem, independent of the current issue.

I have no idea if objcopy could be avoided here, though.  Ian?

	Rainer
Rainer Orth Jan. 10, 2011, 10:54 a.m. UTC | #6
Ian Lance Taylor <ian@airs.com> writes:

>> DejaGNU generally makes things easier to run if you are using remote 
>> targets or hosts, testing cross tools, doing installed testing without a 
>> build tree, etc., because you already have a working configuration for all 
>> the other testsuites.  Yes, it's *possible* to hook up non-DejaGNU 
>> testsuites to DejaGNU board files, but it shouldn't be necessary; using a 
>> single harness (which at present means DejaGNU, and definitely means 
>> proper test harness software rather than ad hoc shell scripts) for all the 
>> GCC testsuites is better.
>
> libgo supports using DejaGNU, it just doesn't require it.  We should
> make it default to DejaGNU in a cross-configuration (and we should fix
> the DejaGNU support).

As I said: I think we should default to DejaGnu in the GCC tree for all
configurations for consistency and ease of use/maintenance.  I'll later
try to get a patch for that up and running.

	Rainer
diff mbox

Patch

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