aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/os_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/os_linux.go')
-rw-r--r--src/runtime/os_linux.go28
1 files changed, 25 insertions, 3 deletions
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index 67c62bc18e..320c1281c2 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -187,6 +187,8 @@ const (
_AT_HWCAP2 = 26 // hardware capability bit vector 2
)
+var procAuxv = []byte("/proc/self/auxv\x00")
+
func sysargs(argc int32, argv **byte) {
n := argc + 1
@@ -200,11 +202,30 @@ func sysargs(argc int32, argv **byte) {
// now argv+n is auxv
auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
- sysauxv(auxv[:])
+ if sysauxv(auxv[:]) == 0 {
+ // In some situations we don't get a loader-provided
+ // auxv, such as when loaded as a library on Android.
+ // Fall back to /proc/self/auxv.
+ fd := open(&procAuxv[0], 0 /* O_RDONLY */, 0)
+ if fd < 0 {
+ return
+ }
+ var buf [128]uintptr
+ n := read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
+ closefd(fd)
+ if n < 0 {
+ return
+ }
+ // Make sure buf is terminated, even if we didn't read
+ // the whole file.
+ buf[len(buf)-2] = _AT_NULL
+ sysauxv(buf[:])
+ }
}
-func sysauxv(auxv []uintptr) {
- for i := 0; auxv[i] != _AT_NULL; i += 2 {
+func sysauxv(auxv []uintptr) int {
+ var i int
+ for ; auxv[i] != _AT_NULL; i += 2 {
tag, val := auxv[i], auxv[i+1]
switch tag {
case _AT_RANDOM:
@@ -218,6 +239,7 @@ func sysauxv(auxv []uintptr) {
archauxv(tag, val)
}
+ return i / 2
}
func osinit() {