"""
Module extending GDB's CLI with new general-purpose debugging commands.
"""
import gdb
import mcgdb
from mcgdb import toolbox
from mcgdb.toolbox import my_gdb, python_utils
import logging; log = logging.getLogger(__name__)
log_user = logging.getLogger("mcgdb.log.user.interaction")
@python_utils.refer_to(my_gdb.current_infthr)
[docs]class cmd_info_infthread (gdb.Command):
def __init__ (self):
gdb.Command.__init__ (self, "info infthreads", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
gdb.execute("info inferior %d" % gdb.selected_inferior().num)
info_thr = "info thread "
for thread in gdb.selected_inferior().threads():
info_thr += ("%d " % thread.num)
gdb.execute(info_thr)
[docs]class cmd_AllInfBreakpoint(gdb.Command):
def __init__(self):
gdb.Command.__init__ (self, "break_spread", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
my_gdb.AllInfBreakpoint.spread_to_other_inferiors()
[docs]class cmd_sn(gdb.Command):
def __init__(self):
gdb.Command.__init__ (self, "sn", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
if my_gdb.strong_next(args):
self.dont_repeat()
[docs]class cmd_strong_next(gdb.Command):
def __init__(self):
gdb.Command.__init__ (self, "strong_next", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
if my_gdb.strong_next(args):
self.dont_repeat()
##########################
start_time = []
[docs]class cmd_start_time(gdb.Command):
def __init__(self):
gdb.Command.__init__ (self, "start_time", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
start_time.append(time.time())
print ("Starting timer")
[docs]class cmd_stop_time(gdb.Command):
def __init__(self):
gdb.Command.__init__ (self, "stop_time", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
stop_time = time.time()
print ("Stopping timer after %f" % (stop_time - start_time.pop()))
##########################
[docs]class cmd_info_semantics_levels(gdb.Command):
""" List the semantic breakpoints currently activated.
e.g.:
* General
* Definition
---> NPM_init_v01 (1/0 hits)
'1/0 hits' means that the breakpoint has been hit once,
and 0 FinishBreakpoints were used.
See "communication semantics levels" to disable some of these breakpoints.
"""
def __init__(self):
gdb.Command.__init__ (self, "info semantics levels", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
mcgdb.capture.FunctionBreakpoint.check_breakpoint_validity()
current = mcgdb.capture.FunctionType.root
cmd_info_semantics_levels.browse(current, 0)
@staticmethod
[docs] def browse(func_type, depth):
print ("%s * %s%s" % ("\t"*depth, func_type,
" (disabled)" if not func_type.enabled else ""))
for bp in func_type.functions:
if not bp.is_valid(): continue
print ("%s %s %s (%d%s hits)" % ("\t"*depth,
bp.enabled and "--->" or " ",
bp.location,
bp.hit_internal,
"/%d" % bp.fhit_internal if bp.prepare_after.im_func is not mcgdb.capture.FunctionBreakpoint.prepare_after.im_func else ""
))
for child in func_type.children:
cmd_info_semantics_levels.browse(child, depth+1)
[docs]class cmd_comm_semantics_levels(gdb.Command):
"""
Enable or disable some of the programming-model breakpoint,
for instance to improve the performances.
Usage: communication semantics levels LEVEL {enable|disable}
See "info semantics levels" for more details about the breakpoints
related to each level.
"""
def __init__(self):
gdb.Command.__init__ (self, "communication semantics levels",
gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
current = model.capture.FunctionType.root
lst = [child for child in cmd_comm_semantics_levels.list(current)]
complete = []
type_str, part, rest = args.partition(" ")
if type_str not in [child.name for child in lst]:
for name in [child.name for child in lst]:
if name.startswith(type_str):
complete.append(name)
if len(complete) == 0:
print ("Cannot select a semantic level."\
"Please choose one among: %s" \
% ', '.join([child.name for child in lst]))
return
elif len(complete) != 1:
print ("Cannot select a semantic level."\
"Available levels are: %s" % ', '.join(complete))
return
else:
type_str = complete[0]
print ("Type completed to '%s'"% type_str)
type_ = [child for child in lst if child.name == type_str][0]
act, part, rest = rest.partition(" ")
if len(act) == 0:
print ("Please select 'enable' or 'disable'")
return
elif "enable".startswith(act):
do_enable = True
do_enable_str = "Enabling"
elif "disable".startswith(act):
do_enable = False
do_enable_str = "Disabling"
else:
print ("Please select 'enable' or 'disable'")
return
print ("%s function types '%s'" % (do_enable_str, type_str))
type_.to_enabled(do_enable)
[docs] def complete(self, text, word):
current = model.capture.FunctionType.root
lst = [elt for elt in cmd_comm_semantics_levels.list(current)]
complete = []
type_, part, rest = text.partition(" ")
if type_ not in [child.name for child in lst]:
for name in [child.name for child in lst]:
if name.startswith(type_):
complete.append(name)
return complete
act, part, rest = rest.partition(" ")
if act not in ["enable", "disable"]:
for action in ["enable", "disable"]:
if action.startswith(act):
complete.append(action)
return complete
@staticmethod
[docs] def list(func_type):
stack = [func_type]
while len(stack) != 0:
current = stack.pop()
yield current
for child in current.children:
stack.insert(0, child)
[docs]class cmd_cont(gdb.Command):
def __init__(self, name):
gdb.Command.__init__ (self, name, gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
my_gdb.events.cont.trigger()
try:
gdb.execute("continue")
except gdb.error as e:
print ("<>%s<>" % e)
except KeyboardInterrupt:
pass
###################
[docs]class cmd_mcgdb_load_by_name(gdb.Command):
def __init__(self):
gdb.Command.__init__ (self, "mcgdb load_model_by_name", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
toolbox.load_models_by_name(args)
[docs]class cmd_mcgdb_detect(gdb.Command):
def __init__(self):
gdb.Command.__init__ (self, "mcgdb detect_models", gdb.COMMAND_NONE)
[docs] def invoke (self, args, from_tty):
toolbox.detect_models()
[docs]class cmd_mcgdb_autodetect(gdb.Command):
autodetect_enabled = False
def __init__(self):
gdb.Command.__init__ (self, "mcgdb autodetect_models", gdb.COMMAND_NONE)
[docs] def invoke(self, args, from_tty):
if not cmd_mcgdb_autodetect.autodetect_enabled:
gdb.events.new_objfile.connect(toolbox.check_new_objfile_for_models)
log_user.info("Model auto detection enabled")
else:
gdb.events.new_objfile.disconnect(toolbox.check_new_objfile_for_models)
log_user.info("Model auto detection disabled")
cmd_mcgdb_detect.autodetect_enabled = False
###################
# disable start/run commands after first 'cont' event
[docs]class gdb_start_command (gdb.Command):
def __init__ (self, cmd):
super (gdb_start_command, self).__init__ (cmd, gdb.COMMAND_USER)
[docs] def invoke (self, arg, from_tty):
log_user.warn("Cannot restart/run with mcgdb enabled, sorry.")
[docs]def cont(evt):
#gdb_start_command("start")
#gdb_start_command("run")
gdb.events.cont.disconnect(cont)
###################
[docs]def postInitialize():
gdb.Command("info semantics", gdb.COMMAND_NONE, prefix=1)
gdb.Command("communication semantics", gdb.COMMAND_NONE, prefix=1)
cmd_cont("cont")
cmd_cont("c")
cmd_sn()
cmd_strong_next()
cmd_info_infthread()
cmd_AllInfBreakpoint()
cmd_info_semantics_levels()
cmd_comm_semantics_levels()
cmd_start_time()
cmd_stop_time()
cmd_mcgdb_autodetect()
cmd_mcgdb_detect()
cmd_mcgdb_load_by_name()
gdb.events.cont.connect(cont)
gdb.execute("py import mcgdb")