Message ID | yddo96uj4e6.fsf@CeBiTec.Uni-Bielefeld.DE |
---|---|
State | New |
Headers | show |
Series | [libgo] Properly determine executable path on Solaris | expand |
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
# 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