unix: add Auxv Fixes golang/go#67839 Change-Id: I3af38d21159f7cac3786b49ac17657d314fbc178 Reviewed-on: https://go-review.googlesource.com/c/sys/+/644295 Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Carlos Amedee <carlos@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
diff --git a/unix/auxv.go b/unix/auxv.go new file mode 100644 index 0000000..37a8252 --- /dev/null +++ b/unix/auxv.go
@@ -0,0 +1,36 @@ +// Copyright 2025 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. + +//go:build go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import ( + "syscall" + "unsafe" +) + +//go:linkname runtime_getAuxv runtime.getAuxv +func runtime_getAuxv() []uintptr + +// Auxv returns the ELF auxiliary vector as a sequence of key/value pairs. +// The returned slice is always a fresh copy, owned by the caller. +// It returns an error on non-ELF platforms, or if the auxiliary vector cannot be accessed, +// which happens in some locked-down environments and build modes. +func Auxv() ([][2]uintptr, error) { + vec := runtime_getAuxv() + vecLen := len(vec) + + if vecLen == 0 { + return nil, syscall.ENOENT + } + + if vecLen%2 != 0 { + return nil, syscall.EINVAL + } + + result := make([]uintptr, vecLen) + copy(result, vec) + return unsafe.Slice((*[2]uintptr)(unsafe.Pointer(&result[0])), vecLen/2), nil +}
diff --git a/unix/auxv_linux_test.go b/unix/auxv_linux_test.go new file mode 100644 index 0000000..928f3c9 --- /dev/null +++ b/unix/auxv_linux_test.go
@@ -0,0 +1,23 @@ +// Copyright 2025 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. + +//go:build go1.21 && linux + +package unix_test + +import ( + "testing" + + "golang.org/x/sys/unix" +) + +func TestAuxv(t *testing.T) { + vec, err := unix.Auxv() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(vec) == 0 { + t.Errorf("got zero auxv entries on linux, expected > 0") + } +}
diff --git a/unix/auxv_unsupported.go b/unix/auxv_unsupported.go new file mode 100644 index 0000000..1200487 --- /dev/null +++ b/unix/auxv_unsupported.go
@@ -0,0 +1,13 @@ +// Copyright 2025 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. + +//go:build !go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import "syscall" + +func Auxv() ([][2]uintptr, error) { + return nil, syscall.ENOTSUP +}