scripts: gdb: Globbed all dbg scripts into dbg.gdb.py
This goes ahead and makes all dbg scripts available in dbg.gdb.py, via
the magic of globbing __file__ relative, and dynamic python class
generation.
Probably one of the more evil scripts I've written, but this means we
don't need to worry about dbg.gdb.py falling out-of-date when adding new
dbg scripts.
Not all of the dbg scripts are useful inside gdb, but most of them are.
After all, what's cooler than this!
(gdb) dbgrbyd -b4096 "disk" -t \
file->b.shrub.blocks[0] \
--trunk lfs3_rbyd_trunk(&file->b.shrub)
rbyd 0x46.23a w2048, rev 00000000, size 629, cksum 8f5169e1
00000004: .-> 0-334 data w335 0
00000009: .-+-> 335 data w1 1 71
0000000e: | .-> 336 data w1 1 67
00000013: .-+-+-> 337 data w1 1 66
...
00000144: | | | | .-> 350 data w1 1 74
0000019a: | | | | .-+-> 351 data w1 1 78
000001f5: | | | | | .-> 352-739 data w388 1 76
00000258: +-+-+-+-+-+-> 740-2047 data w1308 1 6c
Note some tricks to help interact with bash and gdb:
- Flags are passed as is (-b4096, -t, --trunk)
- All non-flags are parsed as expressions (file->b.shrub.blocks[0])
- String expressions may be useful for paths and stuff ("./disk")
This commit is contained in:
+115
-72
@@ -1,93 +1,136 @@
|
||||
#
|
||||
# hooks for gdb:
|
||||
# Hooks for gdb:
|
||||
# (gdb) source ./scripts/dbg.gdb.py
|
||||
#
|
||||
#
|
||||
|
||||
import shlex
|
||||
|
||||
# dbgerr
|
||||
class DbgErr(gdb.Command):
|
||||
"""Decode littlefs error codes. See -h/--help for more info."""
|
||||
|
||||
# split spaces but only outside of parens and quotes
|
||||
def gdbsplit(v):
|
||||
parens = 0
|
||||
quote = None
|
||||
escape = False
|
||||
i_ = 0
|
||||
for i in range(len(v)):
|
||||
if v[i].isspace() and not parens and not quote:
|
||||
v_ = v[i_:i].strip()
|
||||
if v_:
|
||||
yield v_
|
||||
i_ = i+1
|
||||
elif quote:
|
||||
if escape:
|
||||
escape = False
|
||||
elif v[i] == quote:
|
||||
quote = None
|
||||
elif v[i] == '\\':
|
||||
escape = True
|
||||
elif v[i] in '\'"':
|
||||
quote = v[i]
|
||||
elif v[i] in '([{':
|
||||
parens += 1
|
||||
elif v[i] in '}])':
|
||||
parens -= 1
|
||||
v_ = v[i_:].strip()
|
||||
if v_:
|
||||
yield v_
|
||||
|
||||
# common wrapper for dbg scripts
|
||||
#
|
||||
# Note some tricks to help interact with bash and gdb:
|
||||
#
|
||||
# - Flags are passed as is (-b4096, -t, --trunk)
|
||||
# - All non-flags are parsed as expressions (file->b.shrub.blocks[0])
|
||||
# - String expressions may be useful for paths and stuff ("./disk")
|
||||
#
|
||||
class DbgCommand(gdb.Command):
|
||||
"""A littlefs debug script. See -h/--help for more info."""
|
||||
name = None
|
||||
path = None
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("dbgerr",
|
||||
super().__init__(self.name,
|
||||
gdb.COMMAND_DATA,
|
||||
gdb.COMPLETE_EXPRESSION)
|
||||
|
||||
def invoke(self, args, *_):
|
||||
args = args.split()
|
||||
# find nonflags
|
||||
nonflags = []
|
||||
for i, a in enumerate(args):
|
||||
if not a.startswith('-'):
|
||||
nonflags.append(i)
|
||||
# parse and eval
|
||||
for i, n in enumerate(nonflags):
|
||||
try:
|
||||
args[n] = '%d' % gdb.parse_and_eval(args[n])
|
||||
except gdb.error as e:
|
||||
raise gdb.GdbError(e)
|
||||
# parse args
|
||||
args = list(gdbsplit(args))
|
||||
args_ = []
|
||||
for a in args:
|
||||
# pass flags as is
|
||||
if a.startswith('-'):
|
||||
args_.append(a)
|
||||
|
||||
# parse and eval
|
||||
else:
|
||||
try:
|
||||
v = gdb.parse_and_eval(a)
|
||||
t = v.type.strip_typedefs()
|
||||
if t.code in {
|
||||
gdb.TYPE_CODE_ENUM,
|
||||
gdb.TYPE_CODE_FLAGS,
|
||||
gdb.TYPE_CODE_INT,
|
||||
gdb.TYPE_CODE_RANGE,
|
||||
gdb.TYPE_CODE_CHAR,
|
||||
gdb.TYPE_CODE_BOOL}:
|
||||
v = str(int(v))
|
||||
elif t.code in {
|
||||
gdb.TYPE_CODE_FLT}:
|
||||
v = str(float(v))
|
||||
else:
|
||||
try:
|
||||
v = v.string('utf8')
|
||||
except gdb.error:
|
||||
raise gdb.GdbError('Unexpected type: %s' % v.type)
|
||||
except gdb.error as e:
|
||||
raise gdb.GdbError(e)
|
||||
|
||||
args_.append(shlex.quote(v))
|
||||
args = args_
|
||||
|
||||
# execute
|
||||
gdb.execute(' '.join(['!./scripts/dbgerr.py'] + args))
|
||||
|
||||
DbgErr()
|
||||
gdb.execute(' '.join(['!'+self.path, *args]))
|
||||
|
||||
|
||||
# dbgflags
|
||||
class DbgFlags(gdb.Command):
|
||||
"""Decode littlefs flags. See -h/--help for more info."""
|
||||
# at some point this was manual, then I realized I could just glob all
|
||||
# scripts with this prefix
|
||||
#
|
||||
# # dbgerr
|
||||
# class DbgErr(DbgCommand):
|
||||
# name = 'dbgerr'
|
||||
# path = './scripts/dbgerr.py'
|
||||
#
|
||||
# # dbgflags
|
||||
# class DbgFlags(DbgCommand):
|
||||
# name = 'dbgflags'
|
||||
# path = './scripts/dbgflags.py'
|
||||
#
|
||||
# # dbgtag
|
||||
# class DbgTag(DbgCommand):
|
||||
# name = 'dbgtag'
|
||||
# path = './scripts/dbgtag.py'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("dbgflags",
|
||||
gdb.COMMAND_DATA,
|
||||
gdb.COMPLETE_EXPRESSION)
|
||||
import os
|
||||
import glob
|
||||
|
||||
def invoke(self, args, *_):
|
||||
args = args.split()
|
||||
# find nonflags
|
||||
nonflags = []
|
||||
for i, a in enumerate(args):
|
||||
if not a.startswith('-'):
|
||||
nonflags.append(i)
|
||||
# parse and eval
|
||||
for i, n in enumerate(nonflags):
|
||||
try:
|
||||
args[n] = '%d' % gdb.parse_and_eval(args[n])
|
||||
except gdb.error as e:
|
||||
raise gdb.GdbError(e)
|
||||
for path in glob.glob(os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'dbg*.py')):
|
||||
if path == __file__:
|
||||
continue
|
||||
|
||||
# execute
|
||||
gdb.execute(' '.join(['!./scripts/dbgflags.py'] + args))
|
||||
|
||||
DbgFlags()
|
||||
# create dbg class
|
||||
name = os.path.splitext(os.path.basename(path))[0]
|
||||
type(name, (DbgCommand,), {
|
||||
'name': name,
|
||||
'path': path
|
||||
})
|
||||
|
||||
|
||||
# dbgtag
|
||||
class DbgTag(gdb.Command):
|
||||
"""Decode littlefs tags. See -h/--help for more info."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("dbgtag",
|
||||
gdb.COMMAND_DATA,
|
||||
gdb.COMPLETE_EXPRESSION)
|
||||
|
||||
def invoke(self, args, *_):
|
||||
args = args.split()
|
||||
# find nonflags
|
||||
nonflags = []
|
||||
for i, a in enumerate(args):
|
||||
if not a.startswith('-'):
|
||||
nonflags.append(i)
|
||||
# parse and eval
|
||||
for i, n in enumerate(nonflags):
|
||||
try:
|
||||
args[n] = '%d' % gdb.parse_and_eval(args[n])
|
||||
except gdb.error as e:
|
||||
raise gdb.GdbError(e)
|
||||
|
||||
# execute
|
||||
gdb.execute(' '.join(['!./scripts/dbgtag.py'] + args))
|
||||
|
||||
DbgTag()
|
||||
|
||||
# initialize gdb hooks
|
||||
for Dbg in DbgCommand.__subclasses__():
|
||||
if Dbg.__doc__ is None:
|
||||
Dbg.__doc__ = DbgCommand.__doc__
|
||||
Dbg()
|
||||
|
||||
Reference in New Issue
Block a user