"""
Module extending GDB's CLI with commands related to component handling.
"""
import gdb
from mcgdb.toolbox import my_gdb
from mcgdb import representation
[docs]class cmd_info_compo (gdb.Command):
"""
info components
List the components currently existing in the inferior.
The component currently selected in GDB will be denoted with a '*'.
Component[s] not bound to a processors will be denoted with a '~'.
Usage: info components [ID*|.] [interfaces|itf|endpoints|ep] [full|+]
Optional arguments are
- component IDs (all components if no argument) or '.' for the current component
- interfaces to list component interfaces
- 'full' or '+' for all of the above.
e.g.: info components 1
#1 CommHost[2591]
"""
def __init__ (self):
gdb.Command.__init__ (self, "info components", gdb.COMMAND_OBSCURE)
[docs] def invoke (self, arg, from_tty):
print_endpoints = False
print_work = False
print_cpp_obj = False
print_newline = False
print_name = False
print_state = False
current = False
selected = []
rest = str(arg)
while rest != "":
first, part, rest = rest.partition(" ")
if first in ("+name"):
print_name = True
if first in ("+work"):
print_work = True
elif first in ("+cpp_obj", "+cpp", "+this"):
print_cpp_obj = True
elif first in ("+interfaces", "+itf", "+ifaces"):
print_endpoints = True
elif first in ("+state"):
print_state = True
elif first in ("+nl"):
print_newline = True
elif first in ("full", "+"):
print_endpoints = True
print_cpp_obj = True
print_work = True
print_name = True
print_newline = True
elif first == '.':
current_compo = p2012_mon.CommComponent.get_selected_component(silent=True)
if current_compo:
selected.append(current_compo.numbers[p2012_mon.CommComponent])
elif first.isdigit():
selected.append(int(first))
else:
my_gdb.log.warning("argument '%s' not recognized", first)
i = 0
for comm_comp in p2012_mon.CommComponent.list_:
number = comm_comp.numbers[p2012_mon.CommComponent]
i += 1
if len(selected) != 0 and number not in selected:
continue
idx = -1
mark = comm_comp.get_mark()
print ("%s #%d %s " % (mark, number, comm_comp))
if print_endpoints and comm_comp.endpoints:
print ("\t%s" \
% "\n\t".join(["%s [> #%s]" % (str(ep), str(ep.get_other_side().comm_entity.numbers[p2012_mon.CommComponent])) for ep in comm_comp.endpoints]))
print ("\t--")
if print_work and not isinstance(comm_comp, pedf_mon.Module):
print ("\tWork method: %s" % comm_comp.work_method)
if comm_comp.work_breakpoint is not None:
if not comm_comp.work_breakpoint.enabled:
print ("\tWork breakpoint disabled")
print ("\tWork count: %d" % comm_comp.work_count)
#print ("\tFire tokens: %d (max: %d)" % (comm_comp.fire_tokens, comm_comp.max_tokens))
print ("\t--")
if print_cpp_obj:
print ("\tthis: (%s) %s" % (comm_comp.instance.type, comm_comp.instance))
print ("\t--")
if print_name:
print ("\tname: %s" % (comm_comp.name))
print ("\t--")
if print_state:
print ("\tstate: %s" % (comm_comp.state))
#print ("\thread: (RtThread *) %s" % (comm_comp.thread))
if print_newline:
print ("")
[docs]class cmd_compo (gdb.Command):
def __init__ (self):
gdb.Command.__init__ (self, "component", gdb.COMMAND_OBSCURE)
self.subcommands = {}
[docs] def get_cli_component(self, arg, silent=False):
str_id, part, rest = arg.partition(" ")
if str_id.isdigit():
arg = rest
int_id = int(str_id)
for comm_comp in p2012_mon.CommComponent.list_:
if comm_comp.numbers[p2012_mon.CommComponent] == int_id:
compo = comm_comp
break
else:
if not silent:
my_gdb.log.warning("Couldn't find a component " \
"with the ID #%d", int_id)
return None, arg
elif str_id == '.':
compo = p2012_mon.CommComponent.get_selected_component(silent=True)
else:
compo = None
ret = rest if compo is not None else arg
return compo, ret
[docs] def invoke (self, arg, from_tty):
compo, arg = self.get_cli_component(arg)
subcmd_name, part, rest = arg.partition(" ")
if subcmd_name in self.subcommands:
subcmd = self.subcommands[subcmd_name]
elif (None in self.subcommands
and (not self.subcommands[None].__class__.must_have
or compo is not None)):
subcmd = self.subcommands[None]
rest = arg
subcmd_name = self.default_name
else:
my_gdb.log.warning("No subcommand associated with keyword '%s'.", subcmd_name)
return
if compo is None and subcmd.__class__.must_have:
my_gdb.log.warning("Subcommand '%s' requires a valid component.", subcmd_name)
return
return subcmd.invoke(compo, rest, from_tty)
[docs] def complete(self, text, word):
compo, text = self.get_cli_component(text, silent=True)
subcmd_name, part, rest = text.partition(" ")
if subcmd_name in self.subcommands:
if (compo is None and
self.subcommands[subcmd_name].__class__.must_have):
return []
return self.subcommands[subcmd_name].complete(compo, rest, word)
return [name for (name, subcmd) in self.subcommands.items()
if name is not None and name.startswith(word)
and (not subcmd.__class__.must_have or compo is not None)]
[docs] def sub_command(self, subcmd, name, default=False):
self.subcommands[name] = subcmd
if default:
self.default_name = name
self.subcommands[None] = subcmd
cmd_component = None
[docs]class subcmd_compo_switch:
must_have = True
def __init__ (self):
cmd_component.sub_command(self, name="switch", default=True)
[docs] def invoke (self, compo, arg, from_tty):
force = False
rest = arg
while rest != "":
first, part, rest = rest.partition(" ")
if first in ("force"):
force = True
else:
my_gdb.log.warning("argument '%s' not recognized.", first)
try:
ret = compo.switch(force)
except Exception as e:
my_gdb.log.warning("Error: %s", e)
ret = False
if ret is None:
my_gdb.log.warning("No task associated with this component.")
elif not ret:
my_gdb.log.warning("An error occured during task switching ...")
else:
my_gdb.log.info("[Switching to component %s]", compo)
gdb.execute("where 1")
[docs]class subcmd_compo_catch:
must_have = False
def __init__ (self):
cmd_component.sub_command(self, "catch")
[docs] def invoke (self, compo, arg, from_tty):
if len(arg) == 0 or len(arg) == 1:
for name, state in p2012_mon.catchable_values():
if compo is None:
if p2012_mon.ALL_ENTITIES in state:
str_comp = "all"
else:
str_comp = ", ".join([str(comp) for comp in state])
print ("%s\t\t-->\t%s" % (name, str_comp))
return
first_arg, part, rest = arg.partition(" ")
if len(rest) == 0 or rest == "on":
enable = True
else:
enable = False
if first_arg in p2012_mon.catch.keys():
p2012_mon.catchable_addRemove(first_arg, compo, enable)
if compo is None:
str_comp = "all components."
else:
str_comp = "Component #%d." % (compo.numbers[p2012_mon.CommComponent])
if enable:
print ("Catching components' '%s' method for %s" % (first_arg, str_comp))
else:
print ("Catching components' '%s' " \
"method disabled" % first_arg)
else:
print ("Argument '%s' not recognized" % first_arg )
[docs] def complete(self, compo, text, word):
complete = []
for name in p2012_mon.catchable_keys():
if name.startswith(text):
complete.append(name)
return complete
[docs]class subcmd_compo_break:
must_have = True
def __init__ (self):
cmd_component.sub_command(self, name="break")
[docs] def invoke (self, compo, arg, from_tty):
assert compo is not None
if len(arg) == 0 or len(arg) == 1:
print ("Please specify a linespec.")
return
p2012_mon.UserComponentBreakpoint(compo, arg)
[docs] def complete(self, compo, text, word):
complete = []
for name in p2012_mon.breakable_keys():
if name.startswith(text):
complete.append(name)
return complete
[docs]class subcmd_compo_interface:
must_have = True
def __init__ (self):
cmd_component.sub_command(self, name="interface")
[docs] def invoke(self, compo, arg, from_tty):
itf_name, part, rest = arg.partition(" ")
if len(itf_name) == 0:
print ("Please provide an interface name." \
"Available interfaces: %s." \
% ", ".join([str(i) for i in compo.interfaces]))
return
itf = compo.get_interface(itf_name)
if itf is None:
#check if we can determine the interface name
compl = self.complete(compo, itf_name, None)
if len(compl) != 1:
if len(compl) == 0:
print ("No interface named '%s' in the selected component." % itf_name)
else:
print ("Please select one of the interfaces (%s)." % ",".join([str(c) for c in compl]))
return
itf = compo.get_interface(compl[0])
if itf.link is None:
print ("Interface '%s' is not connected." % itf_name)
return
action, part, rest = rest.partition(" ")
if action in self.__class__.actions:
self.__class__.actions[action](self, itf, rest)
else:
if len(action) != 0:
print ("Unknown action: '%s'" % action)
print ("Valid actions: %s" % ", ".join(self.__class__.actions.keys()))
[docs] def switch(self, itf, arg):
other_side = itf.link.get_other_endpoints(itf)
if len(other_side) == 0:
print ("No other endpoint connected to interface '%s'." % itf.name)
return
rmt_itf = None
if len(other_side) == 1:
rmt_itf = other_side[0]
else:
if len(arg) == 0:
idx = 1
print ("Multiple destinations possible for interface '%s':" % itf.name)
for rmtItf in other_side:
print ("\t[%d] %s" % (idx, rmt_itf) )
return
try:
rmt_itf_idx = int(arg)
except ValueError:
print ("Invalid interface index ('%s')" % arg)
return
try:
rmt_itf = other_side[rmt_itf_idx]
except KeyError:
print ("No such interface index ('%d')" % rmt_itf_idx)
return
ret = rmt_itf.comm_entity.switch()
if ret is None:
print ("No inferior associated with component %s." % rmt_itf)
elif not ret:
print ("Impossible to switch to component %s." % rmt_itf)
[docs] def tbreak(self, itf, arg, permanent=False):
string = "[New message%%s on %s/%s%s]" % (itf.comm_entity, itf.name,
" (%s)" % arg if arg else "")
def cb(msg):
return string % (" #"+str(msg.numbers[connection_mon.Message])
if msg is not None else "")
ret = itf.stop_next(permanent=permanent, cb=cb)
if permanent:
print ("Breakpoint set on %s/%s's events." % \
(itf.comm_entity, itf.name))
else:
print ("Temporary breakpoint set on %s/%s's next event." % \
(itf.comm_entity, itf.name))
return ret
[docs] def next_(self, itf, arg):
self.tbreak(itf, arg)
gdb.execute("cont")
[docs] def breakpoint(self, itf, arg):
if arg == "off":
if itf.breakpoint_rq is None:
my_gdb.log.warning("No breakpoint set on this interface.")
return
itf.undo_request(itf.breakpoint_rq)
itf.breakpoint_rq = None
print ("Breakpoint removed from %s/%s." % (itf.comm_entity, itf.name))
else:
if itf.breakpoint_rq is not None:
msg = itf.breakpoint_rq.str is not None and \
itf.breakpoint_rq.str or "No message"
my_gdb.log.warning("Breakpoint already set on this interface.")
return
itf.breakpoint_rq = self.tbreak(itf, arg, permanent=True)
actions = {"switch": switch,
"tbreak": tbreak,
"next": next_,
"break":breakpoint}
[docs] def complete(self, compo, text, word):
assert compo is not None
complete = []
itf, part, rest = text.partition(" ")
if itf not in compo.interfaces:
for name in compo.interfaces:
if name.startswith(itf):
complete.append(name)
return complete
act, part, rest = rest.partition(" ")
for action in self.__class__.actions.keys():
if action.startswith(act) and action != act:
complete.append(action)
return complete
[docs]class subcmd_compo_disable_work:
must_have = True
def __init__ (self):
cmd_component.sub_command(self, name="track-work", default=True)
[docs] def invoke (self, compo, arg, from_tty):
if compo is None:
print ("Error: no component selected")
return
if compo.work_breakpoint is None:
print ("Error: no work breakpoint for this component")
return
do_enable = arg in ("y", "yes", "o", "on")
compo.work_breakpoint.enabled = do_enable
print ("Tracking WORK method %s for component %s." % ("enabled" if do_enable else "disabled", str(compo)))
[docs]def initialize():
global cmd_component
cmd_component = cmd_compo()
subcmd_compo_switch()
subcmd_compo_catch()
subcmd_compo_break()
subcmd_compo_disable_work()
cmd_info_compo()
#subcmd_compo_interface()