]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: print instruction bytes when reporting a SIGILL
authorKeith Randall <khr@golang.org>
Fri, 28 Feb 2020 20:59:38 +0000 (12:59 -0800)
committerKeith Randall <khr@golang.org>
Mon, 2 Mar 2020 18:46:06 +0000 (18:46 +0000)
Print the bytes of the instruction that generated a SIGILL.
This should help us respond to bug reports without having to
go back-and-forth with the reporter to get the instruction involved.
Might also help with SIGILL problems that are difficult to reproduce.

Update #37513

Change-Id: I33059b1dbfc97bce16142a843f32a88a6547e280
Reviewed-on: https://go-review.googlesource.com/c/go/+/221431
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/signal_unix.go
test/fixedbugs/issue37513.dir/main.go [new file with mode: 0644]
test/fixedbugs/issue37513.dir/sigill_amd64.s [new file with mode: 0644]
test/fixedbugs/issue37513.go [new file with mode: 0644]

index d2e669380510cc3ed487f7378f5e1e5545dd4011..32b192c97770e7801c19b3e1151fcf0813b172ec 100644 (file)
@@ -607,6 +607,30 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
                print("signal arrived during cgo execution\n")
                gp = _g_.m.lockedg.ptr()
        }
+       if sig == _SIGILL {
+               // It would be nice to know how long the instruction is.
+               // Unfortunately, that's complicated to do in general (mostly for x86
+               // and s930x, but other archs have non-standard instruction lengths also).
+               // Opt to print 16 bytes, which covers most instructions.
+               const maxN = 16
+               n := uintptr(maxN)
+               // We have to be careful, though. If we're near the end of
+               // a page and the following page isn't mapped, we could
+               // segfault. So make sure we don't straddle a page (even though
+               // that could lead to printing an incomplete instruction).
+               // We're assuming here we can read at least the page containing the PC.
+               // I suppose it is possible that the page is mapped executable but not readable?
+               pc := c.sigpc()
+               if n > physPageSize-pc%physPageSize {
+                       n = physPageSize - pc%physPageSize
+               }
+               print("instruction bytes:")
+               b := (*[maxN]byte)(unsafe.Pointer(pc))
+               for i := uintptr(0); i < n; i++ {
+                       print(" ", hex(b[i]))
+               }
+               println()
+       }
        print("\n")
 
        level, _, docrash := gotraceback()
diff --git a/test/fixedbugs/issue37513.dir/main.go b/test/fixedbugs/issue37513.dir/main.go
new file mode 100644 (file)
index 0000000..7510652
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "os"
+       "os/exec"
+)
+
+func main() {
+       if len(os.Args) > 1 {
+               // Generate a SIGILL.
+               sigill()
+               return
+       }
+       // Run ourselves with an extra argument. That process should SIGILL.
+       out, _ := exec.Command(os.Args[0], "foo").CombinedOutput()
+       want := "instruction bytes: 0xf 0xb 0xc3"
+       if !bytes.Contains(out, []byte(want)) {
+               fmt.Printf("got:\n%s\nwant:\n%s\n", string(out), want)
+       }
+}
+func sigill()
diff --git a/test/fixedbugs/issue37513.dir/sigill_amd64.s b/test/fixedbugs/issue37513.dir/sigill_amd64.s
new file mode 100644 (file)
index 0000000..43260c2
--- /dev/null
@@ -0,0 +1,7 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+TEXT ·sigill(SB),0,$0-0
+       UD2     // generates a SIGILL
+       RET
diff --git a/test/fixedbugs/issue37513.go b/test/fixedbugs/issue37513.go
new file mode 100644 (file)
index 0000000..e05b2d8
--- /dev/null
@@ -0,0 +1,9 @@
+// buildrundir
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,amd64 darwin,amd64 linux,386
+
+package ignored