diff options
| author | Russ Cox <rsc@golang.org> | 2014-11-19 15:25:33 -0500 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2014-11-19 15:25:33 -0500 |
| commit | 378c2515aeec0e23662631dc6ba63148594ad92b (patch) | |
| tree | 7f9bbc58d02f09548b8596ce94019d1dec54d023 /src/runtime/malloc.go | |
| parent | 2d53d6b5d5b5f10c072549607a221c13e5cdb7e3 (diff) | |
| download | go-378c2515aeec0e23662631dc6ba63148594ad92b.tar.xz | |
runtime: remove assumption that noptrdata data bss noptrbss are ordered and contiguous
The assumption can be violated by external linkers reordering them or
inserting non-Go sections in between them. I looked briefly at trying
to write out the _go_.o in external linking mode in a way that forced
the ordering, but no matter what there's no way to force Go's data
and Go's bss to be next to each other. If there is any data or bss from
non-Go objects, it's very likely to get stuck in between them.
Instead, rewrite the two places we know about that make the assumption.
I grepped for noptrdata to look for more and didn't find any.
The added race test (os/exec in external linking mode) fails without
the changes in the runtime. It crashes with an invalid pointer dereference.
Fixes #9133.
LGTM=dneil
R=dneil
CC=dvyukov, golang-codereviews, iant
https://golang.org/cl/179980043
Diffstat (limited to 'src/runtime/malloc.go')
| -rw-r--r-- | src/runtime/malloc.go | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 8cf1c3d342..1170449440 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -490,6 +490,8 @@ func GC() { // linker-provided var noptrdata struct{} +var enoptrdata struct{} +var noptrbss struct{} var enoptrbss struct{} // SetFinalizer sets the finalizer associated with x to f. @@ -566,8 +568,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) { // func main() { // runtime.SetFinalizer(Foo, nil) // } - // The segments are, in order: text, rodata, noptrdata, data, bss, noptrbss. - if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) { + // The relevant segments are: noptrdata, data, bss, noptrbss. + // We cannot assume they are in any order or even contiguous, + // due to external linking. + if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) || + uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) || + uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) || + uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) { return } gothrow("runtime.SetFinalizer: pointer not in allocated block") |
