One of the remaining libgo testsuite failures on Solaris/SPARC is

--- FAIL: TestExecutable (0.04s)
    executable_test.go:46: exec(self) failed: fork/exec .: permission denied

FAIL: os

This happens only for 64-bit.  truss indeed shows

3181:   execve(".", 0xC000170240, 0xC000178340)         Err#13 EACCES

which is completely bogus.  Further investigation shows that
os.Executable() returns an empty string here.  I traced this down to
go/runtime/os3_solaris.go (solarisExecutablePath) which tries to locate
auxv from argv (I suppose the layout is prescribed by the psABIs, but
haven't looked) and extract the AT_PAGESZ and AT_SUN_EXECNAME members.

In doing so, it assumes that auxv ist just an uintptr[], which is wrong:
<sys/auxv.h> has

typedef struct
{
        int     a_type;
        union {
                long    a_val;
                void    *a_ptr;
                void    (*a_fcn)();
        } a_un;
} auxv_t;

Interpreting this as uintptr[] works for 32-bit and accidentally on
little-endian 64-bit (amd64), but breaks on big-endian 64-bit (sparcv9)
as observed.

While this could be corrected, there's a far easier and more portable
way to get at the required information: AT_PAGESZ/pysPageSize can be
obtained via getpagesize(3C) and AT_SUN_EXECNAME/executablePath is
available via getexecname(3C), both of which are available as far back
as Solaris 10 at least.

The following patch does just that.  Tested on i386-pc-solaris2.11 and
sparc-sun-solaris2.11 (both 32 and 64-bit) without regressions, but
fixing the os failure on sparcv9.  I'm running Solaris 10 bootstraps
right now for good measure, but don't expect any issues there.

        Rainer

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


2019-02-28  Rainer Orth  <r...@cebitec.uni-bielefeld.de>

        * go/runtime/os3_solaris.go: Don't import "runtime/internal/sys".
        (sysargs): Remove auxv determination.
        Don't call sysauxv.
        Determine physPageSize using getpagesize, executablePath using
        getexecnam.
        (getexecname, getpagesize): Declare.
        (sysauxv): Remove.

# HG changeset patch
# Parent  3ec7f28626855dacbeef9ee1f5b470388110e16a
Properly determine executable path on Solaris

diff --git a/libgo/go/runtime/os3_solaris.go b/libgo/go/runtime/os3_solaris.go
--- a/libgo/go/runtime/os3_solaris.go
+++ b/libgo/go/runtime/os3_solaris.go
@@ -4,45 +4,19 @@
 
 package runtime
 
-import (
-	"runtime/internal/sys"
-	"unsafe"
-)
+import _ "unsafe"
 
 var executablePath string
 
-func sysargs(argc int32, argv **byte) {
-	n := argc + 1
-
-	// skip over argv, envp to get to auxv
-	for argv_index(argv, n) != nil {
-		n++
-	}
-
-	// skip NULL separator
-	n++
-
-	// now argv+n is auxv
-	auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
-	sysauxv(auxv[:])
-}
+//extern getexecname
+func getexecname() *byte
 
-const (
-	_AT_NULL         = 0    // Terminates the vector
-	_AT_PAGESZ       = 6    // Page size in bytes
-	_AT_SUN_EXECNAME = 2014 // exec() path name
-)
+//extern getpagesize
+func getpagesize() int32
 
-func sysauxv(auxv []uintptr) {
-	for i := 0; auxv[i] != _AT_NULL; i += 2 {
-		tag, val := auxv[i], auxv[i+1]
-		switch tag {
-		case _AT_PAGESZ:
-			physPageSize = val
-		case _AT_SUN_EXECNAME:
-			executablePath = gostringnocopy((*byte)(unsafe.Pointer(val)))
-		}
-	}
+func sysargs(argc int32, argv **byte) {
+	physPageSize = uintptr(getpagesize())
+	executablePath = gostringnocopy(getexecname())
 }
 
 //go:linkname solarisExecutablePath os.solarisExecutablePath

Reply via email to