Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/AnonR/anonr.TX.../lib/golang/src/runtime
File: runtime-gdb.py
# Copyright 2010 The Go Authors. All rights reserved.
[0] Fix | Delete
# Use of this source code is governed by a BSD-style
[1] Fix | Delete
# license that can be found in the LICENSE file.
[2] Fix | Delete
[3] Fix | Delete
"""GDB Pretty printers and convenience functions for Go's runtime structures.
[4] Fix | Delete
[5] Fix | Delete
This script is loaded by GDB when it finds a .debug_gdb_scripts
[6] Fix | Delete
section in the compiled binary. The [68]l linkers emit this with a
[7] Fix | Delete
path to this file based on the path to the runtime package.
[8] Fix | Delete
"""
[9] Fix | Delete
[10] Fix | Delete
# Known issues:
[11] Fix | Delete
# - pretty printing only works for the 'native' strings. E.g. 'type
[12] Fix | Delete
# foo string' will make foo a plain struct in the eyes of gdb,
[13] Fix | Delete
# circumventing the pretty print triggering.
[14] Fix | Delete
[15] Fix | Delete
[16] Fix | Delete
from __future__ import print_function
[17] Fix | Delete
import re
[18] Fix | Delete
import sys
[19] Fix | Delete
import gdb
[20] Fix | Delete
[21] Fix | Delete
print("Loading Go Runtime support.", file=sys.stderr)
[22] Fix | Delete
#http://python3porting.com/differences.html
[23] Fix | Delete
if sys.version > '3':
[24] Fix | Delete
xrange = range
[25] Fix | Delete
# allow to manually reload while developing
[26] Fix | Delete
goobjfile = gdb.current_objfile() or gdb.objfiles()[0]
[27] Fix | Delete
goobjfile.pretty_printers = []
[28] Fix | Delete
[29] Fix | Delete
# G state (runtime2.go)
[30] Fix | Delete
[31] Fix | Delete
def read_runtime_const(varname, default):
[32] Fix | Delete
try:
[33] Fix | Delete
return int(gdb.parse_and_eval(varname))
[34] Fix | Delete
except Exception:
[35] Fix | Delete
return int(default)
[36] Fix | Delete
[37] Fix | Delete
[38] Fix | Delete
G_IDLE = read_runtime_const("'runtime._Gidle'", 0)
[39] Fix | Delete
G_RUNNABLE = read_runtime_const("'runtime._Grunnable'", 1)
[40] Fix | Delete
G_RUNNING = read_runtime_const("'runtime._Grunning'", 2)
[41] Fix | Delete
G_SYSCALL = read_runtime_const("'runtime._Gsyscall'", 3)
[42] Fix | Delete
G_WAITING = read_runtime_const("'runtime._Gwaiting'", 4)
[43] Fix | Delete
G_MORIBUND_UNUSED = read_runtime_const("'runtime._Gmoribund_unused'", 5)
[44] Fix | Delete
G_DEAD = read_runtime_const("'runtime._Gdead'", 6)
[45] Fix | Delete
G_ENQUEUE_UNUSED = read_runtime_const("'runtime._Genqueue_unused'", 7)
[46] Fix | Delete
G_COPYSTACK = read_runtime_const("'runtime._Gcopystack'", 8)
[47] Fix | Delete
G_SCAN = read_runtime_const("'runtime._Gscan'", 0x1000)
[48] Fix | Delete
G_SCANRUNNABLE = G_SCAN+G_RUNNABLE
[49] Fix | Delete
G_SCANRUNNING = G_SCAN+G_RUNNING
[50] Fix | Delete
G_SCANSYSCALL = G_SCAN+G_SYSCALL
[51] Fix | Delete
G_SCANWAITING = G_SCAN+G_WAITING
[52] Fix | Delete
[53] Fix | Delete
sts = {
[54] Fix | Delete
G_IDLE: 'idle',
[55] Fix | Delete
G_RUNNABLE: 'runnable',
[56] Fix | Delete
G_RUNNING: 'running',
[57] Fix | Delete
G_SYSCALL: 'syscall',
[58] Fix | Delete
G_WAITING: 'waiting',
[59] Fix | Delete
G_MORIBUND_UNUSED: 'moribund',
[60] Fix | Delete
G_DEAD: 'dead',
[61] Fix | Delete
G_ENQUEUE_UNUSED: 'enqueue',
[62] Fix | Delete
G_COPYSTACK: 'copystack',
[63] Fix | Delete
G_SCAN: 'scan',
[64] Fix | Delete
G_SCANRUNNABLE: 'runnable+s',
[65] Fix | Delete
G_SCANRUNNING: 'running+s',
[66] Fix | Delete
G_SCANSYSCALL: 'syscall+s',
[67] Fix | Delete
G_SCANWAITING: 'waiting+s',
[68] Fix | Delete
}
[69] Fix | Delete
[70] Fix | Delete
[71] Fix | Delete
#
[72] Fix | Delete
# Value wrappers
[73] Fix | Delete
#
[74] Fix | Delete
[75] Fix | Delete
class SliceValue:
[76] Fix | Delete
"Wrapper for slice values."
[77] Fix | Delete
[78] Fix | Delete
def __init__(self, val):
[79] Fix | Delete
self.val = val
[80] Fix | Delete
[81] Fix | Delete
@property
[82] Fix | Delete
def len(self):
[83] Fix | Delete
return int(self.val['len'])
[84] Fix | Delete
[85] Fix | Delete
@property
[86] Fix | Delete
def cap(self):
[87] Fix | Delete
return int(self.val['cap'])
[88] Fix | Delete
[89] Fix | Delete
def __getitem__(self, i):
[90] Fix | Delete
if i < 0 or i >= self.len:
[91] Fix | Delete
raise IndexError(i)
[92] Fix | Delete
ptr = self.val["array"]
[93] Fix | Delete
return (ptr + i).dereference()
[94] Fix | Delete
[95] Fix | Delete
[96] Fix | Delete
#
[97] Fix | Delete
# Pretty Printers
[98] Fix | Delete
#
[99] Fix | Delete
[100] Fix | Delete
# The patterns for matching types are permissive because gdb 8.2 switched to matching on (we think) typedef names instead of C syntax names.
[101] Fix | Delete
class StringTypePrinter:
[102] Fix | Delete
"Pretty print Go strings."
[103] Fix | Delete
[104] Fix | Delete
pattern = re.compile(r'^(struct string( \*)?|string)$')
[105] Fix | Delete
[106] Fix | Delete
def __init__(self, val):
[107] Fix | Delete
self.val = val
[108] Fix | Delete
[109] Fix | Delete
def display_hint(self):
[110] Fix | Delete
return 'string'
[111] Fix | Delete
[112] Fix | Delete
def to_string(self):
[113] Fix | Delete
l = int(self.val['len'])
[114] Fix | Delete
return self.val['str'].string("utf-8", "ignore", l)
[115] Fix | Delete
[116] Fix | Delete
[117] Fix | Delete
class SliceTypePrinter:
[118] Fix | Delete
"Pretty print slices."
[119] Fix | Delete
[120] Fix | Delete
pattern = re.compile(r'^(struct \[\]|\[\])')
[121] Fix | Delete
[122] Fix | Delete
def __init__(self, val):
[123] Fix | Delete
self.val = val
[124] Fix | Delete
[125] Fix | Delete
def display_hint(self):
[126] Fix | Delete
return 'array'
[127] Fix | Delete
[128] Fix | Delete
def to_string(self):
[129] Fix | Delete
t = str(self.val.type)
[130] Fix | Delete
if (t.startswith("struct ")):
[131] Fix | Delete
return t[len("struct "):]
[132] Fix | Delete
return t
[133] Fix | Delete
[134] Fix | Delete
def children(self):
[135] Fix | Delete
sval = SliceValue(self.val)
[136] Fix | Delete
if sval.len > sval.cap:
[137] Fix | Delete
return
[138] Fix | Delete
for idx, item in enumerate(sval):
[139] Fix | Delete
yield ('[{0}]'.format(idx), item)
[140] Fix | Delete
[141] Fix | Delete
[142] Fix | Delete
class MapTypePrinter:
[143] Fix | Delete
"""Pretty print map[K]V types.
[144] Fix | Delete
[145] Fix | Delete
Map-typed go variables are really pointers. dereference them in gdb
[146] Fix | Delete
to inspect their contents with this pretty printer.
[147] Fix | Delete
"""
[148] Fix | Delete
[149] Fix | Delete
pattern = re.compile(r'^map\[.*\].*$')
[150] Fix | Delete
[151] Fix | Delete
def __init__(self, val):
[152] Fix | Delete
self.val = val
[153] Fix | Delete
[154] Fix | Delete
def display_hint(self):
[155] Fix | Delete
return 'map'
[156] Fix | Delete
[157] Fix | Delete
def to_string(self):
[158] Fix | Delete
return str(self.val.type)
[159] Fix | Delete
[160] Fix | Delete
def children(self):
[161] Fix | Delete
MapBucketCount = 8 # see internal/abi.go:MapBucketCount
[162] Fix | Delete
B = self.val['B']
[163] Fix | Delete
buckets = self.val['buckets']
[164] Fix | Delete
oldbuckets = self.val['oldbuckets']
[165] Fix | Delete
flags = self.val['flags']
[166] Fix | Delete
inttype = self.val['hash0'].type
[167] Fix | Delete
cnt = 0
[168] Fix | Delete
for bucket in xrange(2 ** int(B)):
[169] Fix | Delete
bp = buckets + bucket
[170] Fix | Delete
if oldbuckets:
[171] Fix | Delete
oldbucket = bucket & (2 ** (B - 1) - 1)
[172] Fix | Delete
oldbp = oldbuckets + oldbucket
[173] Fix | Delete
oldb = oldbp.dereference()
[174] Fix | Delete
if (oldb['overflow'].cast(inttype) & 1) == 0: # old bucket not evacuated yet
[175] Fix | Delete
if bucket >= 2 ** (B - 1):
[176] Fix | Delete
continue # already did old bucket
[177] Fix | Delete
bp = oldbp
[178] Fix | Delete
while bp:
[179] Fix | Delete
b = bp.dereference()
[180] Fix | Delete
for i in xrange(MapBucketCount):
[181] Fix | Delete
if b['tophash'][i] != 0:
[182] Fix | Delete
k = b['keys'][i]
[183] Fix | Delete
v = b['values'][i]
[184] Fix | Delete
if flags & 1:
[185] Fix | Delete
k = k.dereference()
[186] Fix | Delete
if flags & 2:
[187] Fix | Delete
v = v.dereference()
[188] Fix | Delete
yield str(cnt), k
[189] Fix | Delete
yield str(cnt + 1), v
[190] Fix | Delete
cnt += 2
[191] Fix | Delete
bp = b['overflow']
[192] Fix | Delete
[193] Fix | Delete
[194] Fix | Delete
class ChanTypePrinter:
[195] Fix | Delete
"""Pretty print chan[T] types.
[196] Fix | Delete
[197] Fix | Delete
Chan-typed go variables are really pointers. dereference them in gdb
[198] Fix | Delete
to inspect their contents with this pretty printer.
[199] Fix | Delete
"""
[200] Fix | Delete
[201] Fix | Delete
pattern = re.compile(r'^chan ')
[202] Fix | Delete
[203] Fix | Delete
def __init__(self, val):
[204] Fix | Delete
self.val = val
[205] Fix | Delete
[206] Fix | Delete
def display_hint(self):
[207] Fix | Delete
return 'array'
[208] Fix | Delete
[209] Fix | Delete
def to_string(self):
[210] Fix | Delete
return str(self.val.type)
[211] Fix | Delete
[212] Fix | Delete
def children(self):
[213] Fix | Delete
# see chan.c chanbuf(). et is the type stolen from hchan<T>::recvq->first->elem
[214] Fix | Delete
et = [x.type for x in self.val['recvq']['first'].type.target().fields() if x.name == 'elem'][0]
[215] Fix | Delete
ptr = (self.val.address["buf"]).cast(et)
[216] Fix | Delete
for i in range(self.val["qcount"]):
[217] Fix | Delete
j = (self.val["recvx"] + i) % self.val["dataqsiz"]
[218] Fix | Delete
yield ('[{0}]'.format(i), (ptr + j).dereference())
[219] Fix | Delete
[220] Fix | Delete
[221] Fix | Delete
def paramtypematch(t, pattern):
[222] Fix | Delete
return t.code == gdb.TYPE_CODE_TYPEDEF and str(t).startswith(".param") and pattern.match(str(t.target()))
[223] Fix | Delete
[224] Fix | Delete
#
[225] Fix | Delete
# Register all the *Printer classes above.
[226] Fix | Delete
#
[227] Fix | Delete
[228] Fix | Delete
def makematcher(klass):
[229] Fix | Delete
def matcher(val):
[230] Fix | Delete
try:
[231] Fix | Delete
if klass.pattern.match(str(val.type)):
[232] Fix | Delete
return klass(val)
[233] Fix | Delete
elif paramtypematch(val.type, klass.pattern):
[234] Fix | Delete
return klass(val.cast(val.type.target()))
[235] Fix | Delete
except Exception:
[236] Fix | Delete
pass
[237] Fix | Delete
return matcher
[238] Fix | Delete
[239] Fix | Delete
goobjfile.pretty_printers.extend([makematcher(var) for var in vars().values() if hasattr(var, 'pattern')])
[240] Fix | Delete
#
[241] Fix | Delete
# Utilities
[242] Fix | Delete
#
[243] Fix | Delete
[244] Fix | Delete
def pc_to_int(pc):
[245] Fix | Delete
# python2 will not cast pc (type void*) to an int cleanly
[246] Fix | Delete
# instead python2 and python3 work with the hex string representation
[247] Fix | Delete
# of the void pointer which we can parse back into an int.
[248] Fix | Delete
# int(pc) will not work.
[249] Fix | Delete
try:
[250] Fix | Delete
# python3 / newer versions of gdb
[251] Fix | Delete
pc = int(pc)
[252] Fix | Delete
except gdb.error:
[253] Fix | Delete
# str(pc) can return things like
[254] Fix | Delete
# "0x429d6c <runtime.gopark+284>", so
[255] Fix | Delete
# chop at first space.
[256] Fix | Delete
pc = int(str(pc).split(None, 1)[0], 16)
[257] Fix | Delete
return pc
[258] Fix | Delete
[259] Fix | Delete
[260] Fix | Delete
#
[261] Fix | Delete
# For reference, this is what we're trying to do:
[262] Fix | Delete
# eface: p *(*(struct 'runtime.rtype'*)'main.e'->type_->data)->string
[263] Fix | Delete
# iface: p *(*(struct 'runtime.rtype'*)'main.s'->tab->Type->data)->string
[264] Fix | Delete
#
[265] Fix | Delete
# interface types can't be recognized by their name, instead we check
[266] Fix | Delete
# if they have the expected fields. Unfortunately the mapping of
[267] Fix | Delete
# fields to python attributes in gdb.py isn't complete: you can't test
[268] Fix | Delete
# for presence other than by trapping.
[269] Fix | Delete
[270] Fix | Delete
[271] Fix | Delete
def is_iface(val):
[272] Fix | Delete
try:
[273] Fix | Delete
return str(val['tab'].type) == "struct runtime.itab *" and str(val['data'].type) == "void *"
[274] Fix | Delete
except gdb.error:
[275] Fix | Delete
pass
[276] Fix | Delete
[277] Fix | Delete
[278] Fix | Delete
def is_eface(val):
[279] Fix | Delete
try:
[280] Fix | Delete
return str(val['_type'].type) == "struct runtime._type *" and str(val['data'].type) == "void *"
[281] Fix | Delete
except gdb.error:
[282] Fix | Delete
pass
[283] Fix | Delete
[284] Fix | Delete
[285] Fix | Delete
def lookup_type(name):
[286] Fix | Delete
try:
[287] Fix | Delete
return gdb.lookup_type(name)
[288] Fix | Delete
except gdb.error:
[289] Fix | Delete
pass
[290] Fix | Delete
try:
[291] Fix | Delete
return gdb.lookup_type('struct ' + name)
[292] Fix | Delete
except gdb.error:
[293] Fix | Delete
pass
[294] Fix | Delete
try:
[295] Fix | Delete
return gdb.lookup_type('struct ' + name[1:]).pointer()
[296] Fix | Delete
except gdb.error:
[297] Fix | Delete
pass
[298] Fix | Delete
[299] Fix | Delete
[300] Fix | Delete
def iface_commontype(obj):
[301] Fix | Delete
if is_iface(obj):
[302] Fix | Delete
go_type_ptr = obj['tab']['_type']
[303] Fix | Delete
elif is_eface(obj):
[304] Fix | Delete
go_type_ptr = obj['_type']
[305] Fix | Delete
else:
[306] Fix | Delete
return
[307] Fix | Delete
[308] Fix | Delete
return go_type_ptr.cast(gdb.lookup_type("struct reflect.rtype").pointer()).dereference()
[309] Fix | Delete
[310] Fix | Delete
[311] Fix | Delete
def iface_dtype(obj):
[312] Fix | Delete
"Decode type of the data field of an eface or iface struct."
[313] Fix | Delete
# known issue: dtype_name decoded from runtime.rtype is "nested.Foo"
[314] Fix | Delete
# but the dwarf table lists it as "full/path/to/nested.Foo"
[315] Fix | Delete
[316] Fix | Delete
dynamic_go_type = iface_commontype(obj)
[317] Fix | Delete
if dynamic_go_type is None:
[318] Fix | Delete
return
[319] Fix | Delete
dtype_name = dynamic_go_type['string'].dereference()['str'].string()
[320] Fix | Delete
[321] Fix | Delete
dynamic_gdb_type = lookup_type(dtype_name)
[322] Fix | Delete
if dynamic_gdb_type is None:
[323] Fix | Delete
return
[324] Fix | Delete
[325] Fix | Delete
type_size = int(dynamic_go_type['size'])
[326] Fix | Delete
uintptr_size = int(dynamic_go_type['size'].type.sizeof) # size is itself a uintptr
[327] Fix | Delete
if type_size > uintptr_size:
[328] Fix | Delete
dynamic_gdb_type = dynamic_gdb_type.pointer()
[329] Fix | Delete
[330] Fix | Delete
return dynamic_gdb_type
[331] Fix | Delete
[332] Fix | Delete
[333] Fix | Delete
def iface_dtype_name(obj):
[334] Fix | Delete
"Decode type name of the data field of an eface or iface struct."
[335] Fix | Delete
[336] Fix | Delete
dynamic_go_type = iface_commontype(obj)
[337] Fix | Delete
if dynamic_go_type is None:
[338] Fix | Delete
return
[339] Fix | Delete
return dynamic_go_type['string'].dereference()['str'].string()
[340] Fix | Delete
[341] Fix | Delete
[342] Fix | Delete
class IfacePrinter:
[343] Fix | Delete
"""Pretty print interface values
[344] Fix | Delete
[345] Fix | Delete
Casts the data field to the appropriate dynamic type."""
[346] Fix | Delete
[347] Fix | Delete
def __init__(self, val):
[348] Fix | Delete
self.val = val
[349] Fix | Delete
[350] Fix | Delete
def display_hint(self):
[351] Fix | Delete
return 'string'
[352] Fix | Delete
[353] Fix | Delete
def to_string(self):
[354] Fix | Delete
if self.val['data'] == 0:
[355] Fix | Delete
return 0x0
[356] Fix | Delete
try:
[357] Fix | Delete
dtype = iface_dtype(self.val)
[358] Fix | Delete
except Exception:
[359] Fix | Delete
return "<bad dynamic type>"
[360] Fix | Delete
[361] Fix | Delete
if dtype is None: # trouble looking up, print something reasonable
[362] Fix | Delete
return "({typename}){data}".format(
[363] Fix | Delete
typename=iface_dtype_name(self.val), data=self.val['data'])
[364] Fix | Delete
[365] Fix | Delete
try:
[366] Fix | Delete
return self.val['data'].cast(dtype).dereference()
[367] Fix | Delete
except Exception:
[368] Fix | Delete
pass
[369] Fix | Delete
return self.val['data'].cast(dtype)
[370] Fix | Delete
[371] Fix | Delete
[372] Fix | Delete
def ifacematcher(val):
[373] Fix | Delete
if is_iface(val) or is_eface(val):
[374] Fix | Delete
return IfacePrinter(val)
[375] Fix | Delete
[376] Fix | Delete
goobjfile.pretty_printers.append(ifacematcher)
[377] Fix | Delete
[378] Fix | Delete
#
[379] Fix | Delete
# Convenience Functions
[380] Fix | Delete
#
[381] Fix | Delete
[382] Fix | Delete
[383] Fix | Delete
class GoLenFunc(gdb.Function):
[384] Fix | Delete
"Length of strings, slices, maps or channels"
[385] Fix | Delete
[386] Fix | Delete
how = ((StringTypePrinter, 'len'), (SliceTypePrinter, 'len'), (MapTypePrinter, 'count'), (ChanTypePrinter, 'qcount'))
[387] Fix | Delete
[388] Fix | Delete
def __init__(self):
[389] Fix | Delete
gdb.Function.__init__(self, "len")
[390] Fix | Delete
[391] Fix | Delete
def invoke(self, obj):
[392] Fix | Delete
typename = str(obj.type)
[393] Fix | Delete
for klass, fld in self.how:
[394] Fix | Delete
if klass.pattern.match(typename) or paramtypematch(obj.type, klass.pattern):
[395] Fix | Delete
return obj[fld]
[396] Fix | Delete
[397] Fix | Delete
[398] Fix | Delete
class GoCapFunc(gdb.Function):
[399] Fix | Delete
"Capacity of slices or channels"
[400] Fix | Delete
[401] Fix | Delete
how = ((SliceTypePrinter, 'cap'), (ChanTypePrinter, 'dataqsiz'))
[402] Fix | Delete
[403] Fix | Delete
def __init__(self):
[404] Fix | Delete
gdb.Function.__init__(self, "cap")
[405] Fix | Delete
[406] Fix | Delete
def invoke(self, obj):
[407] Fix | Delete
typename = str(obj.type)
[408] Fix | Delete
for klass, fld in self.how:
[409] Fix | Delete
if klass.pattern.match(typename) or paramtypematch(obj.type, klass.pattern):
[410] Fix | Delete
return obj[fld]
[411] Fix | Delete
[412] Fix | Delete
[413] Fix | Delete
class DTypeFunc(gdb.Function):
[414] Fix | Delete
"""Cast Interface values to their dynamic type.
[415] Fix | Delete
[416] Fix | Delete
For non-interface types this behaves as the identity operation.
[417] Fix | Delete
"""
[418] Fix | Delete
[419] Fix | Delete
def __init__(self):
[420] Fix | Delete
gdb.Function.__init__(self, "dtype")
[421] Fix | Delete
[422] Fix | Delete
def invoke(self, obj):
[423] Fix | Delete
try:
[424] Fix | Delete
return obj['data'].cast(iface_dtype(obj))
[425] Fix | Delete
except gdb.error:
[426] Fix | Delete
pass
[427] Fix | Delete
return obj
[428] Fix | Delete
[429] Fix | Delete
#
[430] Fix | Delete
# Commands
[431] Fix | Delete
#
[432] Fix | Delete
[433] Fix | Delete
def linked_list(ptr, linkfield):
[434] Fix | Delete
while ptr:
[435] Fix | Delete
yield ptr
[436] Fix | Delete
ptr = ptr[linkfield]
[437] Fix | Delete
[438] Fix | Delete
[439] Fix | Delete
class GoroutinesCmd(gdb.Command):
[440] Fix | Delete
"List all goroutines."
[441] Fix | Delete
[442] Fix | Delete
def __init__(self):
[443] Fix | Delete
gdb.Command.__init__(self, "info goroutines", gdb.COMMAND_STACK, gdb.COMPLETE_NONE)
[444] Fix | Delete
[445] Fix | Delete
def invoke(self, _arg, _from_tty):
[446] Fix | Delete
# args = gdb.string_to_argv(arg)
[447] Fix | Delete
vp = gdb.lookup_type('void').pointer()
[448] Fix | Delete
for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
[449] Fix | Delete
if ptr['atomicstatus']['value'] == G_DEAD:
[450] Fix | Delete
continue
[451] Fix | Delete
s = ' '
[452] Fix | Delete
if ptr['m']:
[453] Fix | Delete
s = '*'
[454] Fix | Delete
pc = ptr['sched']['pc'].cast(vp)
[455] Fix | Delete
pc = pc_to_int(pc)
[456] Fix | Delete
blk = gdb.block_for_pc(pc)
[457] Fix | Delete
status = int(ptr['atomicstatus']['value'])
[458] Fix | Delete
st = sts.get(status, "unknown(%d)" % status)
[459] Fix | Delete
print(s, ptr['goid'], "{0:8s}".format(st), blk.function)
[460] Fix | Delete
[461] Fix | Delete
[462] Fix | Delete
def find_goroutine(goid):
[463] Fix | Delete
"""
[464] Fix | Delete
find_goroutine attempts to find the goroutine identified by goid.
[465] Fix | Delete
It returns a tuple of gdb.Value's representing the stack pointer
[466] Fix | Delete
and program counter pointer for the goroutine.
[467] Fix | Delete
[468] Fix | Delete
@param int goid
[469] Fix | Delete
[470] Fix | Delete
@return tuple (gdb.Value, gdb.Value)
[471] Fix | Delete
"""
[472] Fix | Delete
vp = gdb.lookup_type('void').pointer()
[473] Fix | Delete
for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
[474] Fix | Delete
if ptr['atomicstatus']['value'] == G_DEAD:
[475] Fix | Delete
continue
[476] Fix | Delete
if ptr['goid'] == goid:
[477] Fix | Delete
break
[478] Fix | Delete
else:
[479] Fix | Delete
return None, None
[480] Fix | Delete
# Get the goroutine's saved state.
[481] Fix | Delete
pc, sp = ptr['sched']['pc'], ptr['sched']['sp']
[482] Fix | Delete
status = ptr['atomicstatus']['value']&~G_SCAN
[483] Fix | Delete
# Goroutine is not running nor in syscall, so use the info in goroutine
[484] Fix | Delete
if status != G_RUNNING and status != G_SYSCALL:
[485] Fix | Delete
return pc.cast(vp), sp.cast(vp)
[486] Fix | Delete
[487] Fix | Delete
# If the goroutine is in a syscall, use syscallpc/sp.
[488] Fix | Delete
pc, sp = ptr['syscallpc'], ptr['syscallsp']
[489] Fix | Delete
if sp != 0:
[490] Fix | Delete
return pc.cast(vp), sp.cast(vp)
[491] Fix | Delete
# Otherwise, the goroutine is running, so it doesn't have
[492] Fix | Delete
# saved scheduler state. Find G's OS thread.
[493] Fix | Delete
m = ptr['m']
[494] Fix | Delete
if m == 0:
[495] Fix | Delete
return None, None
[496] Fix | Delete
for thr in gdb.selected_inferior().threads():
[497] Fix | Delete
if thr.ptid[1] == m['procid']:
[498] Fix | Delete
break
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function