summaryrefslogtreecommitdiff
path: root/libgo/go/runtime/os_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/os_linux.go')
-rw-r--r--libgo/go/runtime/os_linux.go65
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