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 <[email protected]>
* 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