From c955bb2040e601c474e547b8badbe44677c9fbdf Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 14 Apr 2016 12:12:45 -0400 Subject: [PATCH] runtime: common auxv parser Currently several different Linux architectures have separate copies of the auxv parser. Bring these all together into a single copy of the parser that calls out to a per-arch handler for each tag/value pair. This is in preparation for handling common auxv tags in one place. For #9993. Change-Id: Iceebc3afad6b4133b70fca7003561ae370445c10 Reviewed-on: https://go-review.googlesource.com/22061 Run-TryBot: Brad Fitzpatrick Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot Reviewed-by: Michael Hudson-Doyle --- src/runtime/os_linux.go | 23 +++++++++++++++ src/runtime/os_linux_386.go | 24 ++++----------- src/runtime/os_linux_arm.go | 48 +++++++++++------------------- src/runtime/os_linux_arm64.go | 32 ++++++-------------- src/runtime/os_linux_noauxv.go | 10 +++++++ src/runtime/vdso_linux_amd64.go | 52 ++++++++++----------------------- src/runtime/vdso_none.go | 5 +--- 7 files changed, 81 insertions(+), 113 deletions(-) create mode 100644 src/runtime/os_linux_noauxv.go diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 7d8cc7e5c4..eeb30c7dd9 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -176,6 +176,29 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer) { var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n") var failthreadcreate = []byte("runtime: failed to create new OS thread\n") +const ( + _AT_NULL = 0 // End of vector +) + +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)) + for i := 0; auxv[i] != _AT_NULL; i += 2 { + tag, val := auxv[i], auxv[i+1] + archauxv(tag, val) + } +} + func osinit() { ncpu = getproccount() } diff --git a/src/runtime/os_linux_386.go b/src/runtime/os_linux_386.go index 0f39cade3b..2383d962b2 100644 --- a/src/runtime/os_linux_386.go +++ b/src/runtime/os_linux_386.go @@ -4,30 +4,16 @@ package runtime -import ( - "runtime/internal/sys" - "unsafe" -) +import "unsafe" const ( - _AT_NULL = 0 _AT_RANDOM = 25 _AT_SYSINFO = 32 ) -func sysargs(argc int32, argv **byte) { - // skip over argv, envv to get to auxv - n := argc + 1 - for argv_index(argv, n) != nil { - n++ - } - n++ - auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) - - for i := 0; auxv[i] != _AT_NULL; i += 2 { - switch auxv[i] { - case _AT_RANDOM: - startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))[:] - } +func archauxv(tag, val uintptr) { + switch tag { + case _AT_RANDOM: + startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:] } } diff --git a/src/runtime/os_linux_arm.go b/src/runtime/os_linux_arm.go index 8fdfb585ba..a61be916b6 100644 --- a/src/runtime/os_linux_arm.go +++ b/src/runtime/os_linux_arm.go @@ -4,13 +4,9 @@ package runtime -import ( - "runtime/internal/sys" - "unsafe" -) +import "unsafe" const ( - _AT_NULL = 0 _AT_PLATFORM = 15 // introduced in at least 2.6.11 _AT_HWCAP = 16 // introduced in at least 2.6.11 _AT_RANDOM = 25 // introduced in 2.6.29 @@ -36,33 +32,23 @@ func checkgoarm() { } } -func sysargs(argc int32, argv **byte) { - // skip over argv, envv to get to auxv - n := argc + 1 - for argv_index(argv, n) != nil { - n++ - } - n++ - auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) - - for i := 0; auxv[i] != _AT_NULL; i += 2 { - switch auxv[i] { - case _AT_RANDOM: // kernel provides a pointer to 16-bytes worth of random data - startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))[:] - // the pointer provided may not be word aligned, so we must treat it - // as a byte array. - randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 | - uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24 - - case _AT_PLATFORM: // v5l, v6l, v7l - t := *(*uint8)(unsafe.Pointer(uintptr(auxv[i+1] + 1))) - if '5' <= t && t <= '7' { - armArch = t - '0' - } - - case _AT_HWCAP: // CPU capability bit flags - hwcap = auxv[i+1] +func archauxv(tag, val uintptr) { + switch tag { + case _AT_RANDOM: // kernel provides a pointer to 16-bytes worth of random data + startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:] + // the pointer provided may not be word aligned, so we must treat it + // as a byte array. + randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 | + uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24 + + case _AT_PLATFORM: // v5l, v6l, v7l + t := *(*uint8)(unsafe.Pointer(val + 1)) + if '5' <= t && t <= '7' { + armArch = t - '0' } + + case _AT_HWCAP: // CPU capability bit flags + hwcap = uint32(val) } } diff --git a/src/runtime/os_linux_arm64.go b/src/runtime/os_linux_arm64.go index 57184b0d3a..aa9d4d9885 100644 --- a/src/runtime/os_linux_arm64.go +++ b/src/runtime/os_linux_arm64.go @@ -4,36 +4,22 @@ package runtime -import ( - "runtime/internal/sys" - "unsafe" -) +import "unsafe" const ( - _AT_NULL = 0 _AT_RANDOM = 25 // introduced in 2.6.29 ) var randomNumber uint32 -func sysargs(argc int32, argv **byte) { - // skip over argv, envv to get to auxv - n := argc + 1 - for argv_index(argv, n) != nil { - n++ - } - n++ - auxv := (*[1 << 29]uint64)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) - - for i := 0; auxv[i] != _AT_NULL; i += 2 { - switch auxv[i] { - case _AT_RANDOM: // kernel provides a pointer to 16-bytes worth of random data - startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))[:] - // the pointer provided may not be word aligned, so we must treat it - // as a byte array. - randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 | - uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24 - } +func archauxv(tag, val uintptr) { + switch tag { + case _AT_RANDOM: // kernel provides a pointer to 16-bytes worth of random data + startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:] + // the pointer provided may not be word aligned, so we must treat it + // as a byte array. + randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 | + uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24 } } diff --git a/src/runtime/os_linux_noauxv.go b/src/runtime/os_linux_noauxv.go new file mode 100644 index 0000000000..d26c85bbb6 --- /dev/null +++ b/src/runtime/os_linux_noauxv.go @@ -0,0 +1,10 @@ +// Copyright 2014 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. + +// +build !386,!amd64,!arm,!arm64 + +package runtime + +func archauxv(tag, val uintptr) { +} diff --git a/src/runtime/vdso_linux_amd64.go b/src/runtime/vdso_linux_amd64.go index 42571e063c..1aae9b6570 100644 --- a/src/runtime/vdso_linux_amd64.go +++ b/src/runtime/vdso_linux_amd64.go @@ -4,10 +4,7 @@ package runtime -import ( - "runtime/internal/sys" - "unsafe" -) +import "unsafe" // Look up symbols in the Linux vDSO. @@ -23,7 +20,6 @@ import ( const ( _AT_RANDOM = 25 _AT_SYSINFO_EHDR = 33 - _AT_NULL = 0 /* End of vector */ _PT_LOAD = 1 /* Loadable program segment */ _PT_DYNAMIC = 2 /* Dynamic linking information */ @@ -294,37 +290,21 @@ func vdso_parse_symbols(info *vdso_info, version int32) { } } -func sysargs(argc int32, argv **byte) { - n := argc + 1 - - // skip envp to get to ELF auxiliary vector. - for argv_index(argv, n) != nil { - n++ - } - - // skip NULL separator - n++ - - // now argv+n is auxv - auxv := (*[1 << 32]elf64Auxv)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) - - for i := 0; auxv[i].a_type != _AT_NULL; i++ { - av := &auxv[i] - switch av.a_type { - case _AT_SYSINFO_EHDR: - if av.a_val == 0 { - // Something went wrong - continue - } - var info vdso_info - // TODO(rsc): I don't understand why the compiler thinks info escapes - // when passed to the three functions below. - info1 := (*vdso_info)(noescape(unsafe.Pointer(&info))) - vdso_init_from_sysinfo_ehdr(info1, (*elf64Ehdr)(unsafe.Pointer(uintptr(av.a_val)))) - vdso_parse_symbols(info1, vdso_find_version(info1, &linux26)) - - case _AT_RANDOM: - startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(av.a_val)))[:] +func archauxv(tag, val uintptr) { + switch tag { + case _AT_SYSINFO_EHDR: + if val == 0 { + // Something went wrong + return } + var info vdso_info + // TODO(rsc): I don't understand why the compiler thinks info escapes + // when passed to the three functions below. + info1 := (*vdso_info)(noescape(unsafe.Pointer(&info))) + vdso_init_from_sysinfo_ehdr(info1, (*elf64Ehdr)(unsafe.Pointer(val))) + vdso_parse_symbols(info1, vdso_find_version(info1, &linux26)) + + case _AT_RANDOM: + startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:] } } diff --git a/src/runtime/vdso_none.go b/src/runtime/vdso_none.go index e14e1a4707..efae23f6ee 100644 --- a/src/runtime/vdso_none.go +++ b/src/runtime/vdso_none.go @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !linux !amd64 -// +build !linux !386 -// +build !linux !arm -// +build !linux !arm64 +// +build !linux package runtime -- 2.48.1