aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/runtime-gdb.py
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2017-06-07 10:30:49 -0400
committerAustin Clements <austin@google.com>2017-06-08 13:18:26 +0000
commit24659717811075fb3b3bf012670229be1636c089 (patch)
treefe64e2559cbc8777f42323d3267238398ef98717 /src/runtime/runtime-gdb.py
parent631cdec676a1f92284b54297ca8ce4c209e2fc9d (diff)
downloadgo-24659717811075fb3b3bf012670229be1636c089.tar.gz
go-24659717811075fb3b3bf012670229be1636c089.zip
runtime: fix GDB goroutine N command when N is running
The current implementation of "goroutine N cmd" assumes it can get goroutine N's state from the goroutine's sched buffer. But this only works if the goroutine is blocked. Extend find_goroutine so that, if there is no saved scheduler state for a goorutine, it tries to find the thread the goroutine is running on and use the thread's current register state. We also extend find_goroutine to understand saved syscall register state. Fixes #13887. Change-Id: I739008a8987471deaa4a9da918655e4042cf969b Reviewed-on: https://go-review.googlesource.com/45031 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/runtime-gdb.py')
-rw-r--r--src/runtime/runtime-gdb.py33
1 files changed, 31 insertions, 2 deletions
diff --git a/src/runtime/runtime-gdb.py b/src/runtime/runtime-gdb.py
index 5c9b2a08e8..26f36b5119 100644
--- a/src/runtime/runtime-gdb.py
+++ b/src/runtime/runtime-gdb.py
@@ -416,8 +416,37 @@ def find_goroutine(goid):
if ptr['atomicstatus'] == 6: # 'gdead'
continue
if ptr['goid'] == goid:
- return (ptr['sched'][x].cast(vp) for x in ('pc', 'sp'))
- return None, None
+ break
+ else:
+ return None, None
+ # Get the goroutine's saved state.
+ pc, sp = ptr['sched']['pc'], ptr['sched']['sp']
+ # If the goroutine is stopped, sched.sp will be non-0.
+ if sp != 0:
+ return pc.cast(vp), sp.cast(vp)
+ # If the goroutine is in a syscall, use syscallpc/sp.
+ pc, sp = ptr['syscallpc'], ptr['syscallsp']
+ if sp != 0:
+ return pc.cast(vp), sp.cast(vp)
+ # Otherwise, the goroutine is running, so it doesn't have
+ # saved scheduler state. Find G's OS thread.
+ m = ptr['m']
+ if m == 0:
+ return None, None
+ for thr in gdb.selected_inferior().threads():
+ if thr.ptid[1] == m['procid']:
+ break
+ else:
+ return None, None
+ # Get scheduler state from the G's OS thread state.
+ curthr = gdb.selected_thread()
+ try:
+ thr.switch()
+ pc = gdb.parse_and_eval('$pc')
+ sp = gdb.parse_and_eval('$sp')
+ finally:
+ curthr.switch()
+ return pc.cast(vp), sp.cast(vp)
class GoroutineCmd(gdb.Command):