Repository: go
Issue: runtime: efence=1 and cgocheck=2 are not mutually compatible
Labels: NeedsInvestigation,compiler/runtime

Low priority, but I discovered that `GODEBUG=efence=1,cgocheck=2` together are not compatible.

A simple hello world using os/exec fails like:

```
write of Go pointer 0xc000113c00 to non-Go memory 0x2b36ee9f9a0
fatal error: Go pointer stored into non-Go memory

runtime stack:
runtime.throw(0x221c74, 0x24)
        /home/bradfitz/sdk/go1.15/src/runtime/panic.go:1116 +0x79
runtime.cgoCheckWriteBarrier.func1()
        /home/bradfitz/sdk/go1.15/src/runtime/cgocheck.go:55 +0xb0
runtime.systemstack(0x0)
        /home/bradfitz/sdk/go1.15/src/runtime/asm_amd64.s:370 +0x6b
runtime.mstart()
        /home/bradfitz/sdk/go1.15/src/runtime/proc.go:1116

goroutine 1 [running]:
runtime.systemstack_switch()
        /home/bradfitz/sdk/go1.15/src/runtime/asm_amd64.s:330 fp=0x2b36ee9f7b8 sp=0x2b36ee9f7b0 pc=0xc7220
runtime.cgoCheckWriteBarrier(0x2b36ee9f9a0, 0xc000113c00)
        /home/bradfitz/sdk/go1.15/src/runtime/cgocheck.go:53 +0xd6 fp=0x2b36ee9f7f0 sp=0x2b36ee9f7b8 pc=0x64c36
runtime.wbBufFlush(0x2b36ee9f9a0, 0xc000113c00)
        /home/bradfitz/sdk/go1.15/src/runtime/mwbbuf.go:196 +0x8a fp=0x2b36ee9f820 sp=0x2b36ee9f7f0 pc=0x90cca
runtime.gcWriteBarrier(0x6f115, 0x1e92e0, 0x2b36ee9f803, 0x0, 0xc000113c00, 0x0, 0x351501, 0xc000168580, 0x2b36ee9fa90, 0x1be5ee, ...)
        /home/bradfitz/sdk/go1.15/src/runtime/asm_amd64.s:1461 +0xb5 fp=0x2b36ee9f8a8 sp=0x2b36ee9f820 pc=0xc90b5
runtime.gcWriteBarrierCX(0x1e92e0, 0x2b36ee9f803, 0x0, 0xc000113c00, 0x0, 0x351501, 0xc000168580, 0x2b36ee9fa90, 0x1be5ee, 0x1e92e0, ...)
        /home/bradfitz/sdk/go1.15/src/runtime/asm_amd64.s:1481 +0x7 fp=0x2b36ee9f8b0 sp=0x2b36ee9f8a8 pc=0xc9107
runtime.makemap(0x1e92e0, 0x2c, 0x2b36ee9f990, 0xc000168580)
        /home/bradfitz/sdk/go1.15/src/runtime/map.go:328 +0x195 fp=0x2b36ee9f8f8 sp=0x2b36ee9f8b0 pc=0x6f115
os/exec.dedupEnvCase(0x1, 0xc000110e00, 0x2c, 0x32, 0x0, 0x0, 0x0)
        /home/bradfitz/sdk/go1.15/src/os/exec/exec.go:749 +0xee fp=0x2b36ee9faa0 sp=0x2b36ee9f8f8 pc=0x1be5ee
os/exec.dedupEnv(...)
        /home/bradfitz/sdk/go1.15/src/os/exec/exec.go:742
os/exec.(*Cmd).Start(0xc000166580, 0x0, 0x0)
        /home/bradfitz/sdk/go1.15/src/os/exec/exec.go:425 +0x499 fp=0x2b36ee9fbe8 sp=0x2b36ee9faa0 pc=0x1bd839
os/exec.(*Cmd).Run(0xc000166580, 0xc00017ac30, 0xc000166580)
        /home/bradfitz/sdk/go1.15/src/os/exec/exec.go:338 +0x32 fp=0x2b36ee9fc10 sp=0x2b36ee9fbe8 pc=0x1bced2
os/exec.(*Cmd).CombinedOutput(0xc000166580, 0x3, 0x2b36ee9fd30, 0x1, 0x1, 0xc000166580)
        /home/bradfitz/sdk/go1.15/src/os/exec/exec.go:567 +0x9b fp=0x2b36ee9fc40 sp=0x2b36ee9fc10 pc=0x1be3bb
main.killOldTailscale()
        /home/bradfitz/src/tailscale.io/cmd/tswin/tswin.go:65 +0xad fp=0x2b36ee9fd90 sp=0x2b36ee9fc40 pc=0x1c9b8d
main.main()
        /home/bradfitz/src/tailscale.io/cmd/tswin/tswin.go:129 +0xd0 fp=0x2b36ee9ff88 sp=0x2b36ee9fd90 pc=0x1ca370
runtime.main()
        /home/bradfitz/sdk/go1.15/src/runtime/proc.go:204 +0x209 fp=0x2b36ee9ffe0 sp=0x2b36ee9ff88 pc=0x9a149
runtime.goexit()
        /home/bradfitz/sdk/go1.15/src/runtime/asm_amd64.s:1374 +0x1 fp=0x2b36ee9ffe8 sp=0x2b36ee9ffe0 pc=0xc8fe1
```

@ianlancetaylor said elsewhere:

> Looks like with efence=1 stacks are allocated using sysAlloc.  That
> does not look like a Go pointer to the cgocheck code.  The effect is
> that when writing a Go pointer to the stack, it looks like writing a
> Go pointer to non-Go memory, which cgocheck crashes on.
>
> I don't see a simple fix, other than effectively disabling cgocheck
> when using efence.  You could open an issue, I guess, but I agree that
> it doesn't seem like a big concern.

Another fix is just having the runtime throw early with an error message if those options are used together.