diff options
| author | Austin Clements <austin@google.com> | 2016-11-28 18:03:16 -0500 |
|---|---|---|
| committer | Austin Clements <austin@google.com> | 2016-11-29 15:27:53 +0000 |
| commit | 6f287fa2bb5b0b74506ecc586d036dcd11a761e2 (patch) | |
| tree | 696350e756d42d210b017dec100feb976257a4eb /src/runtime/os_linux.go | |
| parent | d39b7b5347a3e6cc9173224393e4cfaf874a272a (diff) | |
| download | go-6f287fa2bb5b0b74506ecc586d036dcd11a761e2.tar.xz | |
runtime: fall back to /proc/self/auxv in Android libs
Android's libc doesn't provide access to auxv, so currently the Go
runtime synthesizes a fake, minimal auxv when loaded as a library on
Android. This used to be sufficient, but now we depend on auxv to
retrieve the system physical page size and panic if we can't retrieve
it.
Fix this by falling back to reading auxv from /proc/self/auxv if the
loader-provided auxv is empty and removing the synthetic auxv vectors.
Fixes #18041.
Change-Id: Ia2ec2c764a6609331494a5d359032c56cbb83482
Reviewed-on: https://go-review.googlesource.com/33652
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Diffstat (limited to 'src/runtime/os_linux.go')
| -rw-r--r-- | src/runtime/os_linux.go | 28 |
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() { |
