diff mbox series

[libgo] Properly determine executable path on Solaris

Message ID yddo96uj4e6.fsf@CeBiTec.Uni-Bielefeld.DE
State New
Headers show
Series [libgo] Properly determine executable path on Solaris | expand

Commit Message

Rainer Orth March 1, 2019, 10:05 a.m. UTC
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

Comments

Ian Lance Taylor March 1, 2019, 2:20 p.m. UTC | #1
On Fri, Mar 1, 2019 at 2:06 AM Rainer Orth <ro@cebitec.uni-bielefeld.de> wrote:
>
> 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.

Thanks.  Committed to mainline.

Ian
diff mbox series

Patch

# 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