diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2016-06-27 10:40:13 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2016-06-27 11:04:45 +0000 |
commit | d9a924f2e457e76b4a6a3eba2a03e8dc8203340a (patch) | |
tree | 70931dee3313cb7c509d3b6806b02a9f2bbea5c8 /community | |
parent | 52de4ff080025f1148416070b14c75c334583277 (diff) | |
download | aports-d9a924f2e457e76b4a6a3eba2a03e8dc8203340a.tar.bz2 aports-d9a924f2e457e76b4a6a3eba2a03e8dc8203340a.tar.xz |
community/go: fix paxmark for arm
we also need to disable RANDEXEC
Diffstat (limited to 'community')
-rw-r--r-- | community/go/0001-runtime-use-entire-address-space-on-32-bit.patch | 303 | ||||
-rw-r--r-- | community/go/APKBUILD | 4 | ||||
-rw-r--r-- | community/go/stacksize.patch | 120 |
3 files changed, 425 insertions, 2 deletions
diff --git a/community/go/0001-runtime-use-entire-address-space-on-32-bit.patch b/community/go/0001-runtime-use-entire-address-space-on-32-bit.patch new file mode 100644 index 0000000000..20ccd45d41 --- /dev/null +++ b/community/go/0001-runtime-use-entire-address-space-on-32-bit.patch @@ -0,0 +1,303 @@ +From 2017cb5f865afa822b2d2355eeb4d5555395143c Mon Sep 17 00:00:00 2001 +From: Elias Naur <elias.naur@gmail.com> +Date: Wed, 9 Mar 2016 10:00:12 +0100 +Subject: [PATCH] runtime: use entire address space on 32 bit + +In issue #13992, Russ mentioned that the heap bitmap footprint was +halved but that the bitmap size calculation hadn't been updated. This +presents the opportunity to either halve the bitmap size or double +the addressable virtual space. This CL doubles the addressable virtual +space. On 32 bit this can be tweaked further to allow the bitmap to +cover the entire 4GB virtual address space, removing a failure mode +if the kernel hands out memory with a too low address. + +First, fix the calculation and double _MaxArena32 to cover 4GB virtual +memory space with the same bitmap size (256 MB). + +Then, allow the fallback mode for the initial memory reservation +on 32 bit (or 64 bit with too little available virtual memory) to not +include space for the arena. mheap.sysAlloc will automatically reserve +additional space when the existing arena is full. + +Finally, set arena_start to 0 in 32 bit mode, so that any address is +acceptable for subsequent (additional) reservations. + +Before, the bitmap was always located just before arena_start, so +fix the two places relying on that assumption: Point the otherwise unused +mheap.bitmap to one byte after the end of the bitmap, and use it for +bitmap addressing instead of arena_start. + +With arena_start set to 0 on 32 bit, the cgoInRange check is no longer a +sufficient check for Go pointers. Introduce and call inHeapOrStack to +check whether a pointer is to the Go heap or stack. + +While we're here, remove sysReserveHigh which seems to be unused. + +Fixes #13992 + +Change-Id: I592b513148a50b9d3967b5c5d94b86b3ec39acc2 +Reviewed-on: https://go-review.googlesource.com/20471 +Reviewed-by: Austin Clements <austin@google.com> +Run-TryBot: Austin Clements <austin@google.com> +TryBot-Result: Gobot Gobot <gobot@golang.org> +(cherry picked from commit e6ec82067a9068c93db6e7041017060a1c863452) +--- + src/runtime/cgocall.go | 2 +- + src/runtime/malloc.go | 82 +++++++++++++++++++------------------------------- + src/runtime/mbitmap.go | 4 +-- + src/runtime/mheap.go | 24 ++++++++++++++- + 4 files changed, 57 insertions(+), 55 deletions(-) + +diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go +index fef8add..30c3a67 100644 +--- a/src/runtime/cgocall.go ++++ b/src/runtime/cgocall.go +@@ -568,7 +568,7 @@ func cgoIsGoPointer(p unsafe.Pointer) bool { + return false + } + +- if cgoInRange(p, mheap_.arena_start, mheap_.arena_used) { ++ if inHeapOrStack(uintptr(p)) { + return true + } + +diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go +index b520c68..f3c6e88 100644 +--- a/src/runtime/malloc.go ++++ b/src/runtime/malloc.go +@@ -173,7 +173,7 @@ const ( + // Page number (address>>pageShift) + type pageID uintptr + +-const _MaxArena32 = 2 << 30 ++const _MaxArena32 = 1<<32 - 1 + + // OS-defined helpers: + // +@@ -229,8 +229,8 @@ func mallocinit() { + limit = 0 + + // Set up the allocation arena, a contiguous area of memory where +- // allocated data will be found. The arena begins with a bitmap large +- // enough to hold 4 bits per allocated word. ++ // allocated data will be found. The arena begins with a bitmap large ++ // enough to hold 2 bits per allocated word. + if sys.PtrSize == 8 && (limit == 0 || limit > 1<<30) { + // On a 64-bit machine, allocate from a single contiguous reservation. + // 512 GB (MaxMem) should be big enough for now. +@@ -262,7 +262,7 @@ func mallocinit() { + // translation buffers, the user address space is limited to 39 bits + // On darwin/arm64, the address space is even smaller. + arenaSize := round(_MaxMem, _PageSize) +- bitmapSize = arenaSize / (sys.PtrSize * 8 / 4) ++ bitmapSize = arenaSize / (sys.PtrSize * 8 / 2) + spansSize = arenaSize / _PageSize * sys.PtrSize + spansSize = round(spansSize, _PageSize) + for i := 0; i <= 0x7f; i++ { +@@ -287,32 +287,26 @@ func mallocinit() { + // with a giant virtual address space reservation. + // Instead we map the memory information bitmap + // immediately after the data segment, large enough +- // to handle another 2GB of mappings (256 MB), ++ // to handle the entire 4GB address space (256 MB), + // along with a reservation for an initial arena. + // When that gets used up, we'll start asking the kernel +- // for any memory anywhere and hope it's in the 2GB +- // following the bitmap (presumably the executable begins +- // near the bottom of memory, so we'll have to use up +- // most of memory before the kernel resorts to giving out +- // memory before the beginning of the text segment). +- // +- // Alternatively we could reserve 512 MB bitmap, enough +- // for 4GB of mappings, and then accept any memory the +- // kernel threw at us, but normally that's a waste of 512 MB +- // of address space, which is probably too much in a 32-bit world. ++ // for any memory anywhere. + + // If we fail to allocate, try again with a smaller arena. + // This is necessary on Android L where we share a process + // with ART, which reserves virtual memory aggressively. ++ // In the worst case, fall back to a 0-sized initial arena, ++ // in the hope that subsequent reservations will succeed. + arenaSizes := []uintptr{ + 512 << 20, + 256 << 20, + 128 << 20, ++ 0, + } + + for _, arenaSize := range arenaSizes { +- bitmapSize = _MaxArena32 / (sys.PtrSize * 8 / 4) +- spansSize = _MaxArena32 / _PageSize * sys.PtrSize ++ bitmapSize = (_MaxArena32 + 1) / (sys.PtrSize * 8 / 2) ++ spansSize = (_MaxArena32 + 1) / _PageSize * sys.PtrSize + if limit > 0 && arenaSize+bitmapSize+spansSize > limit { + bitmapSize = (limit / 9) &^ ((1 << _PageShift) - 1) + arenaSize = bitmapSize * 8 +@@ -347,10 +341,16 @@ func mallocinit() { + p1 := round(p, _PageSize) + + mheap_.spans = (**mspan)(unsafe.Pointer(p1)) +- mheap_.bitmap = p1 + spansSize +- mheap_.arena_start = p1 + (spansSize + bitmapSize) +- mheap_.arena_used = mheap_.arena_start ++ mheap_.bitmap = p1 + spansSize + bitmapSize ++ if sys.PtrSize == 4 { ++ // Set arena_start such that we can accept memory ++ // reservations located anywhere in the 4GB virtual space. ++ mheap_.arena_start = 0 ++ } else { ++ mheap_.arena_start = p1 + (spansSize + bitmapSize) ++ } + mheap_.arena_end = p + pSize ++ mheap_.arena_used = p1 + (spansSize + bitmapSize) + mheap_.arena_reserved = reserved + + if mheap_.arena_start&(_PageSize-1) != 0 { +@@ -364,36 +364,17 @@ func mallocinit() { + _g_.m.mcache = allocmcache() + } + +-// sysReserveHigh reserves space somewhere high in the address space. +-// sysReserve doesn't actually reserve the full amount requested on +-// 64-bit systems, because of problems with ulimit. Instead it checks +-// that it can get the first 64 kB and assumes it can grab the rest as +-// needed. This doesn't work well with the "let the kernel pick an address" +-// mode, so don't do that. Pick a high address instead. +-func sysReserveHigh(n uintptr, reserved *bool) unsafe.Pointer { +- if sys.PtrSize == 4 { +- return sysReserve(nil, n, reserved) +- } +- +- for i := 0; i <= 0x7f; i++ { +- p := uintptr(i)<<40 | uintptrMask&(0x00c0<<32) +- *reserved = false +- p = uintptr(sysReserve(unsafe.Pointer(p), n, reserved)) +- if p != 0 { +- return unsafe.Pointer(p) +- } +- } +- +- return sysReserve(nil, n, reserved) +-} +- ++// sysAlloc allocates the next n bytes from the heap arena. The ++// returned pointer is always _PageSize aligned and between ++// h.arena_start and h.arena_end. sysAlloc returns nil on failure. ++// There is no corresponding free function. + func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer { + if n > h.arena_end-h.arena_used { + // We are in 32-bit mode, maybe we didn't use all possible address space yet. + // Reserve some more space. + p_size := round(n+_PageSize, 256<<20) + new_end := h.arena_end + p_size // Careful: can overflow +- if h.arena_end <= new_end && new_end <= h.arena_start+_MaxArena32 { ++ if h.arena_end <= new_end && new_end-h.arena_start-1 <= _MaxArena32 { + // TODO: It would be bad if part of the arena + // is reserved and part is not. + var reserved bool +@@ -404,7 +385,7 @@ func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer { + if p == h.arena_end { + h.arena_end = new_end + h.arena_reserved = reserved +- } else if h.arena_start <= p && p+p_size <= h.arena_start+_MaxArena32 { ++ } else if h.arena_start <= p && p+p_size-h.arena_start-1 <= _MaxArena32 { + // Keep everything page-aligned. + // Our pages are bigger than hardware pages. + h.arena_end = p + p_size +@@ -441,23 +422,22 @@ func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer { + } + + // If using 64-bit, our reservation is all we have. +- if h.arena_end-h.arena_start >= _MaxArena32 { ++ if h.arena_end-h.arena_start > _MaxArena32 { + return nil + } + + // On 32-bit, once the reservation is gone we can +- // try to get memory at a location chosen by the OS +- // and hope that it is in the range we allocated bitmap for. ++ // try to get memory at a location chosen by the OS. + p_size := round(n, _PageSize) + _PageSize + p := uintptr(sysAlloc(p_size, &memstats.heap_sys)) + if p == 0 { + return nil + } + +- if p < h.arena_start || uintptr(p)+p_size-h.arena_start >= _MaxArena32 { ++ if p < h.arena_start || uintptr(p)+p_size-h.arena_start > _MaxArena32 { + top := ^uintptr(0) +- if top-h.arena_start > _MaxArena32 { +- top = h.arena_start + _MaxArena32 ++ if top-h.arena_start-1 > _MaxArena32 { ++ top = h.arena_start + _MaxArena32 + 1 + } + print("runtime: memory allocated by OS (", hex(p), ") not in usable range [", hex(h.arena_start), ",", hex(top), ")\n") + sysFree(unsafe.Pointer(p), p_size, &memstats.heap_sys) +diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go +index 336d4d8..9a5d83b 100644 +--- a/src/runtime/mbitmap.go ++++ b/src/runtime/mbitmap.go +@@ -145,7 +145,7 @@ func (h *mheap) mapBits(arena_used uintptr) { + return + } + +- sysMap(unsafe.Pointer(h.arena_start-n), n-h.bitmap_mapped, h.arena_reserved, &memstats.gc_sys) ++ sysMap(unsafe.Pointer(h.bitmap-n), n-h.bitmap_mapped, h.arena_reserved, &memstats.gc_sys) + h.bitmap_mapped = n + } + +@@ -166,7 +166,7 @@ type heapBits struct { + func heapBitsForAddr(addr uintptr) heapBits { + // 2 bits per work, 4 pairs per byte, and a mask is hard coded. + off := (addr - mheap_.arena_start) / sys.PtrSize +- return heapBits{(*uint8)(unsafe.Pointer(mheap_.arena_start - off/4 - 1)), uint32(off & 3)} ++ return heapBits{(*uint8)(unsafe.Pointer(mheap_.bitmap - off/4 - 1)), uint32(off & 3)} + } + + // heapBitsForSpan returns the heapBits for the span base address base. +diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go +index a153df0..1db6a49 100644 +--- a/src/runtime/mheap.go ++++ b/src/runtime/mheap.go +@@ -46,7 +46,7 @@ type mheap struct { + nsmallfree [_NumSizeClasses]uint64 // number of frees for small objects (<=maxsmallsize) + + // range of addresses we might see in the heap +- bitmap uintptr ++ bitmap uintptr // Points to one byte past the end of the bitmap + bitmap_mapped uintptr + arena_start uintptr + arena_used uintptr // always mHeap_Map{Bits,Spans} before updating +@@ -217,6 +217,28 @@ func inheap(b uintptr) bool { + return true + } + ++// inHeapOrStack is a variant of inheap that returns true for pointers into stack spans. ++//go:nowritebarrier ++//go:nosplit ++func inHeapOrStack(b uintptr) bool { ++ if b == 0 || b < mheap_.arena_start || b >= mheap_.arena_used { ++ return false ++ } ++ // Not a beginning of a block, consult span table to find the block beginning. ++ s := h_spans[(b-mheap_.arena_start)>>_PageShift] ++ if s == nil || b < s.base() { ++ return false ++ } ++ switch s.state { ++ case mSpanInUse: ++ return b < s.limit ++ case _MSpanStack: ++ return b < s.base()+s.npages<<_PageShift ++ default: ++ return false ++ } ++} ++ + // TODO: spanOf and spanOfUnchecked are open-coded in a lot of places. + // Use the functions instead. + +-- +2.8.2 + diff --git a/community/go/APKBUILD b/community/go/APKBUILD index 0882d920ed..5328c448de 100644 --- a/community/go/APKBUILD +++ b/community/go/APKBUILD @@ -4,7 +4,7 @@ pkgname=go pkgver=1.6.2 # This should be the latest commit on the corresponding release branch _toolsver="c887be1b2ebd11663d4bf2fbca508c449172339e" -pkgrel=3 +pkgrel=4 pkgdesc="Go programming language compiler" url="http://www.golang.org/" arch="all" @@ -81,7 +81,7 @@ package() { # go before 1.7 has issues with randmmap on arm # https://github.com/golang/go/issues/16081 if [ "$GOARCH" = "arm" ]; then - paxmark -r bin/go || attr -s pax.flags -V "r" bin/go \ + paxmark -r bin/go || attr -s pax.flags -V "rx" bin/go \ || return 1 fi diff --git a/community/go/stacksize.patch b/community/go/stacksize.patch new file mode 100644 index 0000000000..33119ad670 --- /dev/null +++ b/community/go/stacksize.patch @@ -0,0 +1,120 @@ +diff --git a/src/runtime/cgo/gcc_linux_386.c b/src/runtime/cgo/gcc_linux_386.c +index 30fe92b..7a6b846 100644 +--- a/src/runtime/cgo/gcc_linux_386.c ++++ b/src/runtime/cgo/gcc_linux_386.c +@@ -14,6 +14,8 @@ static void (*setg_gcc)(void*); + void (*x_cgo_inittls)(void); + void* (*x_cgo_threadentry)(void*); + ++#define MIN_STACKSIZE (256 * 1024) ++ + void + x_cgo_init(G *g, void (*setg)(void*)) + { +@@ -51,6 +53,10 @@ _cgo_sys_thread_start(ThreadStart *ts) + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); ++ // musl libc set default stack size to 80k which is a bit small ++ if (size < MIN_STACKSIZE) ++ if (pthread_attr_setstacksize(&attr, MIN_STACKSIZE) == 0) ++ size = MIN_STACKSIZE; + // Leave stacklo=0 and set stackhi=size; mstack will do the rest. + ts->g->stackhi = size; + err = pthread_create(&p, &attr, threadentry, ts); +diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c +index 0c34c66..6c090b7 100644 +--- a/src/runtime/cgo/gcc_linux_amd64.c ++++ b/src/runtime/cgo/gcc_linux_amd64.c +@@ -16,6 +16,8 @@ static void (*setg_gcc)(void*); + void (*x_cgo_inittls)(void); + void* (*x_cgo_threadentry)(void*); + ++#define MIN_STACKSIZE (512 * 1024) ++ + void + x_cgo_init(G* g, void (*setg)(void*)) + { +@@ -68,6 +70,10 @@ _cgo_sys_thread_start(ThreadStart *ts) + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); ++ // musl libc set default stack size to 80k which is a bit small ++ if (size < MIN_STACKSIZE) ++ if (pthread_attr_setstacksize(&attr, MIN_STACKSIZE) == 0) ++ size = MIN_STACKSIZE; + // Leave stacklo=0 and set stackhi=size; mstack will do the rest. + ts->g->stackhi = size; + err = pthread_create(&p, &attr, threadentry, ts); +diff --git a/src/runtime/cgo/gcc_linux_arm.c b/src/runtime/cgo/gcc_linux_arm.c +index 945c3f1..7abe781 100644 +--- a/src/runtime/cgo/gcc_linux_arm.c ++++ b/src/runtime/cgo/gcc_linux_arm.c +@@ -12,6 +12,8 @@ static void *threadentry(void*); + void (*x_cgo_inittls)(void **tlsg, void **tlsbase); + void (*setg_gcc)(void*); + ++#define MIN_STACKSIZE (256*1024) ++ + void + _cgo_sys_thread_start(ThreadStart *ts) + { +@@ -31,6 +33,10 @@ _cgo_sys_thread_start(ThreadStart *ts) + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); ++ // musl libc set default stack size to 80k which is a bit small ++ if (size < MIN_STACKSIZE) ++ if (pthread_attr_setstacksize(&attr, MIN_STACKSIZE) == 0) ++ size = MIN_STACKSIZE; + // Leave stacklo=0 and set stackhi=size; mstack will do the rest. + ts->g->stackhi = size; + err = pthread_create(&p, &attr, threadentry, ts); +diff --git a/src/runtime/cgo/gcc_linux_arm64.c b/src/runtime/cgo/gcc_linux_arm64.c +index ca9ba0b..8e0ff14 100644 +--- a/src/runtime/cgo/gcc_linux_arm64.c ++++ b/src/runtime/cgo/gcc_linux_arm64.c +@@ -12,6 +12,8 @@ static void *threadentry(void*); + void (*x_cgo_inittls)(void **tlsg, void **tlsbase); + void (*setg_gcc)(void*); + ++#define MIN_STACKSIZE (512*1024) ++ + void + _cgo_sys_thread_start(ThreadStart *ts) + { +@@ -31,6 +33,10 @@ _cgo_sys_thread_start(ThreadStart *ts) + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); ++ // musl libc set default stack size to 80k which is a bit small ++ if (size < MIN_STACKSIZE) ++ if (pthread_attr_setstacksize(&attr, MIN_STACKSIZE) == 0) ++ size = MIN_STACKSIZE; + // Leave stacklo=0 and set stackhi=size; mstack will do the rest. + ts->g->stackhi = size; + err = pthread_create(&p, &attr, threadentry, ts); +diff --git a/src/runtime/cgo/gcc_linux_ppc64x.c b/src/runtime/cgo/gcc_linux_ppc64x.c +index fb19805..88911c6 100644 +--- a/src/runtime/cgo/gcc_linux_ppc64x.c ++++ b/src/runtime/cgo/gcc_linux_ppc64x.c +@@ -14,6 +14,8 @@ static void *threadentry(void*); + void (*x_cgo_inittls)(void **tlsg, void **tlsbase); + static void (*setg_gcc)(void*); + ++#define MIN_STACKSIZE (512*1024) ++ + void + x_cgo_init(G *g, void (*setg)(void*), void **tlsbase) + { +@@ -41,6 +43,10 @@ _cgo_sys_thread_start(ThreadStart *ts) + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); ++ // musl libc set default stack size to 80k which is a bit small ++ if (size < MIN_STACKSIZE) ++ if (pthread_attr_setstacksize(&attr, MIN_STACKSIZE) == 0) ++ size = MIN_STACKSIZE; + // Leave stacklo=0 and set stackhi=size; mstack will do the rest. + ts->g->stackhi = size; + err = pthread_create(&p, &attr, threadentry, ts); |