Skip to content

Instantly share code, notes, and snippets.

@changkun
Forked from aclements/getg.py
Created April 13, 2020 16:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save changkun/fff7af8f7805f85f16d3185bf4487a33 to your computer and use it in GitHub Desktop.
Save changkun/fff7af8f7805f85f16d3185bf4487a33 to your computer and use it in GitHub Desktop.
$getg() function for gdb
import gdb
_Gdead = 6
class SliceValue:
"""Wrapper for slice values."""
def __init__(self, val):
self.val = val
@property
def len(self):
return int(self.val['len'])
@property
def cap(self):
return int(self.val['cap'])
def __getitem__(self, i):
if i < 0 or i >= self.len:
raise IndexError(i)
ptr = self.val["array"]
return (ptr + i).dereference()
def getg(sp=None, n=None):
if sp is None and n is None:
sp = gdb.parse_and_eval('$sp')
found = [None]
def checkg(gp):
if gp == 0:
return
if gp['atomicstatus'] == _Gdead:
return
if sp != None and gp['stack']['lo'] < sp and sp <= gp['stack']['hi']:
if found[0] is not None:
raise gdb.GdbError('multiple Gs with overlapping stacks!')
found[0] = gp
if n != None and gp['goid'] == n:
if found[0] is not None:
raise gdb.GdbError('multiple Gs with same goid!')
found[0] = gp
# Check allgs.
for gp in SliceValue(gdb.parse_and_eval("'runtime.allgs'")):
checkg(gp)
# Check g0s and gsignals, which aren't on allgs.
if sp is not None:
mp = gdb.parse_and_eval("'runtime.allm'")
while mp != 0:
checkg(mp['g0'])
checkg(mp['gsignal'])
mp = mp['alllink']
return found[0]
class GetG(gdb.Function):
"""Return the current *g."""
def __init__(self):
super(GetG, self).__init__("getg")
def invoke(self, n=None):
g = getg(n=n)
if g is None:
raise gdb.GdbError('G not found')
return g
GetG()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment