diff options
Diffstat (limited to 'libgo/go/runtime/os_linux.go')
-rw-r--r-- | libgo/go/runtime/os_linux.go | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go index 04c690bd42f..ad334869ed1 100644 --- a/libgo/go/runtime/os_linux.go +++ b/libgo/go/runtime/os_linux.go @@ -86,9 +86,13 @@ func futexwakeup(addr *uint32, cnt uint32) { const ( _AT_NULL = 0 // End of vector _AT_PAGESZ = 6 // System physical page size + _AT_HWCAP = 16 // hardware capability bit vector _AT_RANDOM = 25 // introduced in 2.6.29 + _AT_HWCAP2 = 26 // hardware capability bit vector 2 ) +var procAuxv = []byte("/proc/self/auxv\x00") + func sysargs(argc int32, argv **byte) { n := argc + 1 @@ -102,7 +106,50 @@ func sysargs(argc int32, argv **byte) { // 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 { + 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 { + // On Android, /proc/self/auxv might be unreadable (issue 9229), so we fallback to + // try using mincore to detect the physical page size. + // mincore should return EINVAL when address is not a multiple of system page size. + const size = 256 << 10 // size of memory region to allocate + p := mmap(nil, size, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0) + if uintptr(p) < 4096 { + return + } + var n uintptr + for n = 4 << 10; n < size; n <<= 1 { + err := mincore(unsafe.Pointer(uintptr(p)+n), 1, &addrspace_vec[0]) + if err == 0 { + physPageSize = n + break + } + } + if physPageSize == 0 { + physPageSize = size + } + munmap(p, size) + 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) int { + var i int + for ; auxv[i] != _AT_NULL; i += 2 { tag, val := auxv[i], auxv[i+1] switch tag { case _AT_RANDOM: @@ -111,20 +158,14 @@ func sysargs(argc int32, argv **byte) { startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:] case _AT_PAGESZ: - // Check that the true physical page size is - // compatible with the runtime's assumed - // physical page size. - if sys.PhysPageSize < val { - print("runtime: kernel page size (", val, ") is larger than runtime page size (", sys.PhysPageSize, ")\n") - exit(1) - } - if sys.PhysPageSize%val != 0 { - print("runtime: runtime page size (", sys.PhysPageSize, ") is not a multiple of kernel page size (", val, ")\n") - exit(1) - } + physPageSize = val } // Commented out for gccgo for now. // archauxv(tag, val) } + return i / 2 } + +// Temporary for gccgo until we port mem_GOOS.go. +var addrspace_vec [1]byte |