scripts: gdb: Added some useful GDB scripts to test.py --gdb
These just invoke the existing dbg*.py python scripts, but allow quick references to variables in the debugginged process: (gdb) dbgflags o file->b.o.flags LFS3_O_RDWR 0x00000002 Open a file as read and write LFS3_o_REG 0x10000000 Type = regular-file LFS3_o_UNSYNC 0x01000000 File's metadata does not match disk Quite neat and useful! This works by injecting dbg.gdb.py via gdb -x, which includes the necessary python hooks to add these commands to gdb. This can be overridden/extended with test.py/bench.py's --gdb-script flag. Currently limited to scripts that seem the most useful for process internals: - dbgerr - Decode littlefs error codes - dbgflags - Decode littlefs flags - dbgtag - Decode littlefs tags
This commit is contained in:
+17
-3
@@ -40,6 +40,7 @@ RUNNER_PATH = ['./runners/bench_runner']
|
||||
HEADER_PATH = 'runners/bench_runner.h'
|
||||
|
||||
GDB_PATH = ['gdb']
|
||||
GDB_SCRIPTS = ['./scripts/dbg.gdb.py']
|
||||
VALGRIND_PATH = ['valgrind']
|
||||
PERF_SCRIPT = ['./scripts/perf.py']
|
||||
|
||||
@@ -1469,12 +1470,16 @@ def run(runner, bench_ids=[], **args):
|
||||
or args.get('gdb_main')):
|
||||
failure = failures[0]
|
||||
cmd = find_runner(runner, failure.id, **args)
|
||||
gdb_path = args['gdb_path']
|
||||
gdb_scripts = (args.get('gdb_script') or GDB_SCRIPTS)
|
||||
|
||||
if args.get('gdb_main'):
|
||||
# we don't really need the case breakpoint here, but it
|
||||
# can be helpful
|
||||
path, lineno = find_path(runner, failure.id, **args)
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'break main',
|
||||
'-ex', 'break %s:%d' % (path, lineno),
|
||||
@@ -1482,13 +1487,17 @@ def run(runner, bench_ids=[], **args):
|
||||
'--args']
|
||||
elif args.get('gdb_perm'):
|
||||
path, lineno = find_path(runner, failure.id, **args)
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'break %s:%d' % (path, lineno),
|
||||
'-ex', 'run',
|
||||
'--args']
|
||||
else:
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'run',
|
||||
'--args']
|
||||
@@ -1693,6 +1702,11 @@ if __name__ == "__main__":
|
||||
default=GDB_PATH,
|
||||
help="Path to the gdb executable, may include flags. "
|
||||
"Defaults to %r." % GDB_PATH)
|
||||
bench_parser.add_argument(
|
||||
'--gdb-script',
|
||||
action='append',
|
||||
help="Paths to scripts to execute when dropping into gdb. "
|
||||
"Defaults to %r." % GDB_SCRIPTS)
|
||||
bench_parser.add_argument(
|
||||
'-e', '--exec',
|
||||
type=lambda e: e.split(),
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
#
|
||||
# hooks for gdb:
|
||||
# (gdb) source ./scripts/dbg.gdb.py
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
# dbgerr
|
||||
class DbgErr(gdb.Command):
|
||||
"""Decode littlefs error codes. See -h/--help for more info."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("dbgerr",
|
||||
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/dbgerr.py'] + args))
|
||||
|
||||
DbgErr()
|
||||
|
||||
|
||||
# dbgflags
|
||||
class DbgFlags(gdb.Command):
|
||||
"""Decode littlefs flags. See -h/--help for more info."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("dbgflags",
|
||||
gdb.COMMAND_DATA,
|
||||
gdb.COMPLETE_EXPRESSION)
|
||||
|
||||
def invoke(self, args, *_):
|
||||
args = args.split()
|
||||
# hack, but don't eval if -l or --list specified
|
||||
if '-l' not in args and '--list' not in args:
|
||||
# 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):
|
||||
# dbgflags is special in that first arg may be prefix
|
||||
if i > 0 or len(nonflags) <= 1:
|
||||
try:
|
||||
args[n] = '%d' % gdb.parse_and_eval(args[n])
|
||||
except gdb.error as e:
|
||||
raise gdb.GdbError(e)
|
||||
|
||||
# execute
|
||||
gdb.execute(' '.join(['!./scripts/dbgflags.py'] + args))
|
||||
|
||||
DbgFlags()
|
||||
|
||||
|
||||
# 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()
|
||||
|
||||
+26
-6
@@ -41,6 +41,7 @@ RUNNER_PATH = ['./runners/test_runner']
|
||||
HEADER_PATH = 'runners/test_runner.h'
|
||||
|
||||
GDB_PATH = ['gdb']
|
||||
GDB_SCRIPTS = ['./scripts/dbg.gdb.py']
|
||||
VALGRIND_PATH = ['valgrind']
|
||||
PERF_SCRIPT = ['./scripts/perf.py']
|
||||
|
||||
@@ -1444,12 +1445,16 @@ def run(runner, test_ids=[], **args):
|
||||
or args.get('gdb_pl_after')):
|
||||
failure = failures[0]
|
||||
cmd = find_runner(runner, failure.id, **args)
|
||||
gdb_path = args['gdb_path']
|
||||
gdb_scripts = (args.get('gdb_script') or GDB_SCRIPTS)
|
||||
|
||||
if args.get('gdb_main'):
|
||||
# we don't really need the case breakpoint here, but it
|
||||
# can be helpful
|
||||
path, lineno = find_path(runner, failure.id, **args)
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'break main',
|
||||
'-ex', 'break %s:%d' % (path, lineno),
|
||||
@@ -1457,14 +1462,18 @@ def run(runner, test_ids=[], **args):
|
||||
'--args']
|
||||
elif args.get('gdb_perm'):
|
||||
path, lineno = find_path(runner, failure.id, **args)
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'break %s:%d' % (path, lineno),
|
||||
'-ex', 'run',
|
||||
'--args']
|
||||
elif args.get('gdb_pl') is not None:
|
||||
path, lineno = find_path(runner, failure.id, **args)
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'break %s:%d' % (path, lineno),
|
||||
'-ex', 'ignore 1 %d' % args['gdb_pl'],
|
||||
@@ -1477,7 +1486,9 @@ def run(runner, test_ids=[], **args):
|
||||
failure.id.split(':', 2)[-1]))
|
||||
if failure.id.count(':') >= 2 else 0)
|
||||
path, lineno = find_path(runner, failure.id, **args)
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'break %s:%d' % (path, lineno),
|
||||
'-ex', 'ignore 1 %d' % max(powerlosses-1, 0),
|
||||
@@ -1490,14 +1501,18 @@ def run(runner, test_ids=[], **args):
|
||||
failure.id.split(':', 2)[-1]))
|
||||
if failure.id.count(':') >= 2 else 0)
|
||||
path, lineno = find_path(runner, failure.id, **args)
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'break %s:%d' % (path, lineno),
|
||||
'-ex', 'ignore 1 %d' % powerlosses,
|
||||
'-ex', 'run',
|
||||
'--args']
|
||||
else:
|
||||
cmd[:0] = args['gdb_path'] + [
|
||||
cmd[:0] = [
|
||||
*gdb_path,
|
||||
*it.chain.from_iterable(['-x', s] for s in gdb_scripts),
|
||||
'-q',
|
||||
'-ex', 'run',
|
||||
'--args']
|
||||
@@ -1722,6 +1737,11 @@ if __name__ == "__main__":
|
||||
default=GDB_PATH,
|
||||
help="Path to the gdb executable, may include flags. "
|
||||
"Defaults to %r." % GDB_PATH)
|
||||
test_parser.add_argument(
|
||||
'--gdb-script',
|
||||
action='append',
|
||||
help="Paths to scripts to execute when dropping into gdb. "
|
||||
"Defaults to %r." % GDB_SCRIPTS)
|
||||
test_parser.add_argument(
|
||||
'-e', '--exec',
|
||||
type=lambda e: e.split(),
|
||||
|
||||
Reference in New Issue
Block a user