Browse Source

unix: update to use direct linking on Solaris

CL 9184 changed the runtime and syscall packages to link Solaris binaries
directly instead of using dlopen/dlsym but failed to update sys/unix to
reflect these changes.  This changes the Solaris port to use direct linking
as supported by Go 1.5.

Fixes golang/go#10086

Change-Id: I6747ed939775b18fd967f81853c7d84537aa3842
Reviewed-on: https://go-review.googlesource.com/13400
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Aram Hăvărneanu <aram@mgk.ro>
Shawn Walker-Salas 10 years ago
parent
commit
339fc2ca4b
5 changed files with 359 additions and 452 deletions
  1. 5 12
      unix/asm_solaris_amd64.s
  2. 23 16
      unix/mksyscall_solaris.pl
  3. 0 261
      unix/so_solaris.go
  4. 9 3
      unix/syscall_solaris.go
  5. 322 160
      unix/zsyscall_solaris_amd64.go

+ 5 - 12
unix/asm_solaris_amd64.s

@@ -4,21 +4,14 @@
 
 // +build !gccgo
 
+#include "textflag.h"
+
 //
-// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.goc
+// System calls for amd64, Solaris are implemented in runtime/syscall_solaris.go
 //
 
-TEXT ·sysvicall6(SB), 7, $0-64
+TEXT ·sysvicall6(SB),NOSPLIT,$0-64
 	JMP	syscall·sysvicall6(SB)
 
-TEXT ·rawSysvicall6(SB), 7, $0-64
+TEXT ·rawSysvicall6(SB),NOSPLIT,$0-64
 	JMP	syscall·rawSysvicall6(SB)
-
-TEXT ·dlopen(SB), 7, $0-16
-	JMP	syscall·dlopen(SB)
-
-TEXT ·dlclose(SB), 7, $0-8
-	JMP	syscall·dlclose(SB)
-
-TEXT ·dlsym(SB), 7, $0-16
-	JMP	syscall·dlsym(SB)

+ 23 - 16
unix/mksyscall_solaris.pl

@@ -65,9 +65,9 @@ sub parseparam($) {
 
 my $package = "";
 my $text = "";
-my $vars = "";
-my $mods = "";
-my $modnames = "";
+my $dynimports = "";
+my $linknames = "";
+my @vars = ();
 while(<>) {
 	chomp;
 	s/\s+/ /g;
@@ -95,11 +95,6 @@ while(<>) {
 	if($modname eq "") {
 		$modname = "libc";
 	}
-	my $modvname = "mod$modname";
-	if($modnames !~ /$modname/) {
-		$modnames .= ".$modname";
-		$mods .= "\t$modvname = newLazySO(\"$modname.so\")\n";
-	}
 
 	# System call name.
 	if($sysname eq "") {
@@ -112,9 +107,14 @@ while(<>) {
 	my $strconvfunc = "BytePtrFromString";
 	my $strconvtype = "*byte";
 
-	# Library proc address variable.
 	$sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
-	$vars .= "\t$sysvarname = $modvname.NewProc(\"$sysname\")\n";
+
+	# Runtime import of function to allow cross-platform builds.
+	$dynimports .= "//go:cgo_import_dynamic ${modname}_${sysname} ${sysname} \"$modname.so\"\n";
+	# Link symbol to proc address variable.
+	$linknames .= "//go:linkname ${sysvarname} ${modname}_${sysname}\n";
+	# Library proc address variable.
+	push @vars, $sysvarname;
 
 	# Go function header.
 	$out = join(', ', @out);
@@ -198,7 +198,7 @@ while(<>) {
 
 	# Actual call.
 	my $args = join(', ', @args);
-	my $call = "$asm($sysvarname.Addr(), $nargs, $args)";
+	my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)";
 
 	# Assign return values.
 	my $body = "";
@@ -269,19 +269,26 @@ print <<EOF;
 
 package $package
 
-import "unsafe"
+import (
+	"syscall"
+	"unsafe"
+)
 EOF
 
 print "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
 
-print <<EOF;
+my $vardecls = "\t" . join(",\n\t", @vars);
+$vardecls .= " syscallFunc";
 
+chomp($_=<<EOF);
+
+$dynimports
+$linknames
 var (
-$mods
-$vars
+$vardecls
 )
 
 $text
-
 EOF
+print $_;
 exit 0;

+ 0 - 261
unix/so_solaris.go

@@ -1,261 +0,0 @@
-// 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 unix
-
-import (
-	"sync"
-	"sync/atomic"
-	"syscall"
-	"unsafe"
-)
-
-// soError describes reasons for shared library load failures.
-type soError struct {
-	Err     error
-	ObjName string
-	Msg     string
-}
-
-func (e *soError) Error() string { return e.Msg }
-
-// Implemented in runtime/syscall_solaris.goc.
-func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
-func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
-func dlclose(handle uintptr) (err syscall.Errno)
-func dlopen(name *uint8, mode uintptr) (handle uintptr, err syscall.Errno)
-func dlsym(handle uintptr, name *uint8) (proc uintptr, err syscall.Errno)
-
-// A so implements access to a single shared library object.
-type so struct {
-	Name   string
-	Handle uintptr
-}
-
-// loadSO loads shared library file into memory.
-func loadSO(name string) (*so, error) {
-	namep, err := BytePtrFromString(name)
-	if err != nil {
-		return nil, err
-	}
-	h, e := dlopen(namep, 1) // RTLD_LAZY
-	if e != 0 {
-		return nil, &soError{
-			Err:     e,
-			ObjName: name,
-			Msg:     "Failed to load " + name + ": " + e.Error(),
-		}
-	}
-	d := &so{
-		Name:   name,
-		Handle: uintptr(h),
-	}
-	return d, nil
-}
-
-// mustLoadSO is like loadSO but panics if load operation fails.
-func mustLoadSO(name string) *so {
-	d, e := loadSO(name)
-	if e != nil {
-		panic(e)
-	}
-	return d
-}
-
-// FindProc searches shared library d for procedure named name and returns
-// *proc if found. It returns an error if the search fails.
-func (d *so) FindProc(name string) (*proc, error) {
-	namep, err := BytePtrFromString(name)
-	if err != nil {
-		return nil, err
-	}
-	a, _ := dlsym(uintptr(d.Handle), namep)
-	if a == 0 {
-		return nil, &soError{
-			Err:     ENOSYS,
-			ObjName: name,
-			Msg:     "Failed to find " + name + " procedure in " + d.Name,
-		}
-	}
-	p := &proc{
-		SO:   d,
-		Name: name,
-		addr: a,
-	}
-	return p, nil
-}
-
-// MustFindProc is like FindProc but panics if search fails.
-func (d *so) MustFindProc(name string) *proc {
-	p, e := d.FindProc(name)
-	if e != nil {
-		panic(e)
-	}
-	return p
-}
-
-// Release unloads shared library d from memory.
-func (d *so) Release() (err error) {
-	return dlclose(d.Handle)
-}
-
-// A proc implements access to a procedure inside a shared library.
-type proc struct {
-	SO   *so
-	Name string
-	addr uintptr
-}
-
-// Addr returns the address of the procedure represented by p.
-// The return value can be passed to Syscall to run the procedure.
-func (p *proc) Addr() uintptr {
-	return p.addr
-}
-
-// Call executes procedure p with arguments a. It will panic, if more then
-// 6 arguments are supplied.
-//
-// The returned error is always non-nil, constructed from the result of
-// GetLastError.  Callers must inspect the primary return value to decide
-// whether an error occurred (according to the semantics of the specific
-// function being called) before consulting the error. The error will be
-// guaranteed to contain syscall.Errno.
-func (p *proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
-	switch len(a) {
-	case 0:
-		return sysvicall6(p.Addr(), uintptr(len(a)), 0, 0, 0, 0, 0, 0)
-	case 1:
-		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], 0, 0, 0, 0, 0)
-	case 2:
-		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], 0, 0, 0, 0)
-	case 3:
-		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], 0, 0, 0)
-	case 4:
-		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0)
-	case 5:
-		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0)
-	case 6:
-		return sysvicall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5])
-	default:
-		panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".")
-	}
-	return
-}
-
-// A lazySO implements access to a single shared library.  It will delay
-// the load of the shared library until the first call to its Handle method
-// or to one of its lazyProc's Addr method.
-type lazySO struct {
-	mu   sync.Mutex
-	so   *so // non nil once SO is loaded
-	Name string
-}
-
-// Load loads single shared file d.Name into memory. It returns an error if
-// fails.  Load will not try to load SO, if it is already loaded into memory.
-func (d *lazySO) Load() error {
-	// Non-racy version of:
-	// if d.so == nil {
-	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.so))) == nil {
-		d.mu.Lock()
-		defer d.mu.Unlock()
-		if d.so == nil {
-			so, e := loadSO(d.Name)
-			if e != nil {
-				return e
-			}
-			// Non-racy version of:
-			// d.so = so
-			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.so)), unsafe.Pointer(so))
-		}
-	}
-	return nil
-}
-
-// mustLoad is like Load but panics if search fails.
-func (d *lazySO) mustLoad() {
-	e := d.Load()
-	if e != nil {
-		panic(e)
-	}
-}
-
-// Handle returns d's module handle.
-func (d *lazySO) Handle() uintptr {
-	d.mustLoad()
-	return uintptr(d.so.Handle)
-}
-
-// NewProc returns a lazyProc for accessing the named procedure in the SO d.
-func (d *lazySO) NewProc(name string) *lazyProc {
-	return &lazyProc{l: d, Name: name}
-}
-
-// newLazySO creates new lazySO associated with SO file.
-func newLazySO(name string) *lazySO {
-	return &lazySO{Name: name}
-}
-
-// A lazyProc implements access to a procedure inside a lazySO.
-// It delays the lookup until the Addr method is called.
-type lazyProc struct {
-	mu   sync.Mutex
-	Name string
-	l    *lazySO
-	proc *proc
-}
-
-// Find searches the shared library for procedure named p.Name. It returns an
-// error if search fails. Find will not search procedure, if it is already
-// found and loaded into memory.
-func (p *lazyProc) Find() error {
-	// Non-racy version of:
-	// if p.proc == nil {
-	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc))) == nil {
-		p.mu.Lock()
-		defer p.mu.Unlock()
-		if p.proc == nil {
-			e := p.l.Load()
-			if e != nil {
-				return e
-			}
-			proc, e := p.l.so.FindProc(p.Name)
-			if e != nil {
-				return e
-			}
-			// Non-racy version of:
-			// p.proc = proc
-			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.proc)), unsafe.Pointer(proc))
-		}
-	}
-	return nil
-}
-
-// mustFind is like Find but panics if search fails.
-func (p *lazyProc) mustFind() {
-	e := p.Find()
-	if e != nil {
-		panic(e)
-	}
-}
-
-// Addr returns the address of the procedure represented by p.
-// The return value can be passed to Syscall to run the procedure.
-func (p *lazyProc) Addr() uintptr {
-	p.mustFind()
-	return p.proc.Addr()
-}
-
-// Call executes procedure p with arguments a. It will panic, if more then
-// 6 arguments are supplied.
-//
-// The returned error is always non-nil, constructed from the result of
-// GetLastError.  Callers must inspect the primary return value to decide
-// whether an error occurred (according to the semantics of the specific
-// function being called) before consulting the error. The error will be
-// guaranteed to contain syscall.Errno.
-func (p *lazyProc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) {
-	p.mustFind()
-	return p.proc.Call(a...)
-}

+ 9 - 3
unix/syscall_solaris.go

@@ -17,6 +17,12 @@ import (
 	"unsafe"
 )
 
+// Implemented in runtime/syscall_solaris.go.
+type syscallFunc uintptr
+
+func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
+func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
+
 type SockaddrDatalink struct {
 	Family uint16
 	Index  uint16
@@ -289,7 +295,7 @@ func UtimesNano(path string, ts []Timespec) error {
 
 // FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
 func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
-	_, _, e1 := sysvicall6(procfcntl.Addr(), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
+	_, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
 	if e1 != 0 {
 		return e1
 	}
@@ -511,7 +517,7 @@ func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
 //sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.recvmsg
 
 func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
-	r0, _, e1 := sysvicall6(procread.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
+	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
 	n = int(r0)
 	if e1 != 0 {
 		err = e1
@@ -520,7 +526,7 @@ func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
 }
 
 func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
-	r0, _, e1 := sysvicall6(procwrite.Addr(), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
+	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
 	n = int(r0)
 	if e1 != 0 {
 		err = e1

File diff suppressed because it is too large
+ 322 - 160
unix/zsyscall_solaris_amd64.go


Some files were not shown because too many files changed in this diff