Source code for mcgdb.toolbox

import gdb

import mcgdb.interaction
from .python_utils import *
import traceback

import logging;
log = logging.getLogger(__name__)
log_user = logging.getLogger("mcgdb.log.user")

###################

[docs]class Catchable: catch = {} ALL_ENTITIES = object() @staticmethod
[docs] def register(name): Catchable.catch[name] = []
@staticmethod
[docs] def values(): return Catchable.catch.items()
@staticmethod
[docs] def keys(): return Catchable.catch.keys()
@staticmethod
[docs] def addRemove(name, entity, do_add): if do_add: Catchable.catchable_add(name, entity) else: Catchable.catchable_remove(name, entity)
@staticmethod
[docs] def activate(name, entity): lst = Catchable.catch[name] if entity is None: entity = ALL_ENTITIES while len(lst) != 0: lst.pop() lst.append(entity)
@staticmethod
[docs] def remove(name, entity): lst = catch[name] if entity is None: while len(lst) != 0: lst.pop() else: Catchable.catch[name].remove(entity)
@staticmethod
[docs] def is_set(name, entity=None): return (ALL_ENTITIES in Catchable.catch[name] or entity in Catchable.catch[name])
catchable = Catchable() ################################################ models = {} def register_model(name, key, toggle_activate, objfile=False, binname=False): """ Registers a new model in mcGDB. :param name: name of the model :param key: name of a function that should be looked for to decide to activate the model. :param toggle_activate: called once with param `do_activate=True` when mcGDB wants to active the model; called once with `do_activate=False` when mcGDB wants to desactive the model. :type toggle_activate: Callable(do_activate=<Boolean>) """ models[key] = SimpleClass({"name": name, "key": key, "toggle_activate": toggle_activate, "is_enabled": False, "is_failed": False, "by_binname": binname, "objfile": objfile}) @internal def inferior_has_model(key, objfile=None): """ :returns: True if symbol `key` if defined in GDB's inferior. """ if objfile: return objfile.filename.find(key) != -1 elif gdb.lookup_global_symbol(key) is not None: return True try: gdb.parse_and_eval(key) return True except gdb.error: pass return False def callback_crash(location=None, ex=""): if False: return if location is None: location = 'not provided' log_user.warning("Callback for '{}' failed ({})".format(location, ex)) log_user.warning("Starting post mortem debugger...") type, value, tb = sys.exc_info() traceback.print_exc() import pdb; pdb.post_mortem(tb) @internal def check_new_objfile_for_models(evt): log_event = logging.getLogger("mcgdb.log.event.new_objfile") log_event.info("checking models on {}".format(evt.new_objfile.filename)) detect_models(evt.new_objfile) @internal def enable_model(model): if model.is_enabled or model.is_failed: return log_user.info("Enable model {}".format(model.name)) try: model.toggle_activate(do_activate=True, include_self=True) model.is_enabled = True except Exception as e: log.error("Could not active model {}.".format(model.name)) log.warning(e) log.warning(traceback.format_exc()) model.is_failed = True @internal def load_models_by_name(binname): lst = list(models.items()) for key, model in lst: if not model.by_binname: continue if model.key in binname: enable_model(model) # if new models were inserted if len(lst) != len(list(models.items())): load_models_by_name(binname) @internal def detect_models(new_objfile=None): """ Goes through all the registed models and activate the relevant one(s). """ copy = dict(models.items()) for key, model in copy.items(): if not inferior_has_model(key, new_objfile): continue enable_model(model) @internal def toggle_activate_submodules(name): def do_toggle(do_activate, include_self=False): mod_list = inspect.getmembers(sys.modules[name]) if include_self: mod_list = itertools.chain([(name, sys.modules[name])], mod_list) for mod_name, mod in mod_list: if not inspect.ismodule(mod): continue if do_activate and hasattr(mod, "activate"): if hasattr(mod, "activated") and getattr(mod, "activated"): continue try: getattr(mod, "activate")() setattr(mod, "activated", True) except Exception as e: log.error("Activation of module {} ({}) failed: {}".format(name, mod_name, e)) log.warn(e) if not do_activate and hasattr(mod, "deactivate"): if hasattr(mod, "deactivated") and getattr(mod, "deactivated"): continue try: getattr(mod, "deactivate")() setattr(mod, "deactivated", True) except Exception as e: log.error("Deactivation of module {} ({}) failed: {}".format(name, mod_name, e)) log.warn(e) return do_toggle class BugFixFrame(gdb.frames.FrameDecorator): def function(self): return self.inferior_frame().name() class BugFixFrameFilter: def __init__(self): self.enabled = True self.priority = 99999 def filter(self, frames): for frame in frames: yield BugFixFrame(frame) log.info("FrameDecorator bug fixer frame filter registered.") gdb.frame_filters["Bug fix frame filter"] = BugFixFrameFilter()