From 3855fe7254cbce964a53efdf6d8c9fdde9b4419c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Cl=C3=A9ment=20Chigot?= Date: Tue, 18 Dec 2018 13:00:26 +0100 Subject: [PATCH] runtime: fix backtrace during C syscalls for aix/ppc64 This commit fixes backtrace if a crash or an exit signal is received during a C syscall on aix/ppc64. This is similar to Solaris, Darwin or Windows implementation. Change-Id: I6040c0b1577a9f5b298f58bd4ee6556258a135ef Reviewed-on: https://go-review.googlesource.com/c/154718 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/runtime/os2_aix.go | 147 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 7 deletions(-) diff --git a/src/runtime/os2_aix.go b/src/runtime/os2_aix.go index c478d4b0d8..d0349191c6 100644 --- a/src/runtime/os2_aix.go +++ b/src/runtime/os2_aix.go @@ -151,91 +151,224 @@ var asmsyscall6 libFunc //go:nowritebarrier //go:nosplit func syscall0(fn *libFunc) (r, err uintptr) { - c := &getg().m.libcall + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + c := &gp.m.libcall c.fn = uintptr(unsafe.Pointer(fn)) c.n = 0 c.args = uintptr(noescape(unsafe.Pointer(&fn))) // it's unused but must be non-nil, otherwise crashes asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) + if mp != nil { + mp.libcallsp = 0 + } + return c.r1, c.err } //go:nowritebarrier //go:nosplit func syscall1(fn *libFunc, a0 uintptr) (r, err uintptr) { - c := &getg().m.libcall + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + c := &gp.m.libcall c.fn = uintptr(unsafe.Pointer(fn)) c.n = 1 c.args = uintptr(noescape(unsafe.Pointer(&a0))) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) + if mp != nil { + mp.libcallsp = 0 + } + return c.r1, c.err } //go:nowritebarrier //go:nosplit func syscall2(fn *libFunc, a0, a1 uintptr) (r, err uintptr) { - c := &getg().m.libcall + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + c := &gp.m.libcall c.fn = uintptr(unsafe.Pointer(fn)) c.n = 2 c.args = uintptr(noescape(unsafe.Pointer(&a0))) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) + if mp != nil { + mp.libcallsp = 0 + } + return c.r1, c.err } //go:nowritebarrier //go:nosplit func syscall3(fn *libFunc, a0, a1, a2 uintptr) (r, err uintptr) { - c := &getg().m.libcall + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + c := &gp.m.libcall c.fn = uintptr(unsafe.Pointer(fn)) c.n = 3 c.args = uintptr(noescape(unsafe.Pointer(&a0))) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) + if mp != nil { + mp.libcallsp = 0 + } + return c.r1, c.err } //go:nowritebarrier //go:nosplit func syscall4(fn *libFunc, a0, a1, a2, a3 uintptr) (r, err uintptr) { - c := &getg().m.libcall + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + c := &gp.m.libcall c.fn = uintptr(unsafe.Pointer(fn)) c.n = 4 c.args = uintptr(noescape(unsafe.Pointer(&a0))) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) + if mp != nil { + mp.libcallsp = 0 + } + return c.r1, c.err } //go:nowritebarrier //go:nosplit func syscall5(fn *libFunc, a0, a1, a2, a3, a4 uintptr) (r, err uintptr) { - c := &getg().m.libcall + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + c := &gp.m.libcall c.fn = uintptr(unsafe.Pointer(fn)) c.n = 5 c.args = uintptr(noescape(unsafe.Pointer(&a0))) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) + if mp != nil { + mp.libcallsp = 0 + } + return c.r1, c.err } //go:nowritebarrier //go:nosplit func syscall6(fn *libFunc, a0, a1, a2, a3, a4, a5 uintptr) (r, err uintptr) { - c := &getg().m.libcall + gp := getg() + var mp *m + if gp != nil { + mp = gp.m + } + if mp != nil && mp.libcallsp == 0 { + mp.libcallg.set(gp) + mp.libcallpc = getcallerpc() + // sp must be the last, because once async cpu profiler finds + // all three values to be non-zero, it will use them + mp.libcallsp = getcallersp() + } else { + mp = nil // See comment in sys_darwin.go:libcCall + } + + c := &gp.m.libcall c.fn = uintptr(unsafe.Pointer(fn)) c.n = 6 c.args = uintptr(noescape(unsafe.Pointer(&a0))) asmcgocall(unsafe.Pointer(&asmsyscall6), unsafe.Pointer(c)) + if mp != nil { + mp.libcallsp = 0 + } + return c.r1, c.err } -- 2.50.0