diff options
author | Austin Clements <austin@google.com> | 2017-06-07 10:30:49 -0400 |
---|---|---|
committer | Austin Clements <austin@google.com> | 2017-06-08 13:18:26 +0000 |
commit | 24659717811075fb3b3bf012670229be1636c089 (patch) | |
tree | fe64e2559cbc8777f42323d3267238398ef98717 /src/runtime/runtime-gdb.py | |
parent | 631cdec676a1f92284b54297ca8ce4c209e2fc9d (diff) | |
download | go-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.py | 33 |
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): |