Source code for mcgdb.model.task.environment.p2012.toolbox.gepop

import gdb

from mcgdb.toolbox import my_gdb

[docs]class state: def __init__(self): pass select_task = None sched_task = None stop_regs = None comp_thr = None
######################################################
[docs]def get_selected_task(): if state.select_task is None: state.select_task = do_get_selected_task() return state.select_task
warned = False
[docs]def do_get_selected_task(): locked = gdb.parameter("scheduler-locking") gdb.execute("set scheduler-locking on") try: current_ctx = gdb.parse_and_eval("get_current_context()") except gdb.error as e: global warned if not warned: my_gdb.log.warning("Could not compute the current "\ "thread context: %s", e) warned = True return None finally: gdb.execute("set scheduler-locking %s" % locked) if current_ctx == 0: return None return current_ctx
[docs]def set_stopped_task(evt, task=None): if isinstance(task, gdb.StopEvent): task = None if task is None: task = do_get_selected_task() state.select_task = task state.sched_task = task
#gdb.events.stop.connect(set_stopped_task) #my_gdb.events.bp_stop.connect(set_stopped_task)
[docs]def get_mark(task): if task is None: return "~" if is_host_task(task): if my_gdb.is_selected_task(task): return "*" else: return " " else: if (gdb.selected_thread() is not None and gdb.selected_thread().num == 2 and state.select_task == task): return "*" if state.sched_task is None: return "?" if task == state.sched_task: return ">" return "|"
[docs]def is_selected_task(task): if is_host_task(task): return my_gdb.is_selected_task(task) else: sel = (gdb.selected_thread().num == 2 and task == get_selected_task()) return sel
[docs]def switch_to(task, force=False): if is_host_task(task): return switch_host(task) else: thr = gdb.selected_thread() if thr is None: raise gdb.error("No thread currently selected") if thr.num != 2: for thr in gdb.selected_inferior().threads(): if thr.num == 2: thr.switch() if str(task["state"]) == "RUNNING": if state.stop_regs is not None: reload_current_thread(state.stop_regs) state.stop_regs = None state.select_task = task return True else: return switch_inactive_thread(task, force=force)
####
[docs]def get_selected_host_task(): return my_gdb.get_selected_task()
[docs]def is_host_task(task): return isinstance(task, tuple)
[docs]def switch_host(task): return my_gdb.switch_to(task)
######################################################
[docs]def restore_stop_registers(event): if state.stop_regs is None: return old_thr = gdb.selected_thread() if old_thr != state.comp_thr: state.comp_thr.switch() reload_current_thread(state.stop_regs) state.stop_regs = None if old_thr != state.comp_thr: old_thr.switch()
#gdb.events.cont.connect(restore_stop_registers)
[docs]def switch_inactive_thread(next_, master=False, force=False): alternative = False thr = gdb.selected_thread() if thr.num != 2: for thr in gdb.selected_inferior().threads(): if thr.num == 2: thr.switch() if state.stop_regs is None: state.stop_regs = save_current_thread() state.comp_thr = thr JB_BP = 3 if master: JB_SP = 1 else: JB_SP = 2 if str(next_["state"]) == "INACTIVE": my_gdb.log.warning("proc is inactive, use alternative method.") alternative = True if not master and str(next_["state"]) == "RUNNING": my_gdb.log.warning("proc is running, abort!!") if not force: return False jmbuf = next_["context"][0]["__jmpbuf"] if int(jmbuf[JB_SP]) == 0: my_gdb.log.warning("SP is null, use alternative method.") alternative = True diff = abs(jmbuf[JB_SP] - jmbuf[JB_BP]) if diff < 1500 or diff > 100000000 : my_gdb.log.warning("Frame not large enough/too large (%db), "\ "use alternative method." % diff) alternative = True my_gdb.print_and_execute("flushregs") my_gdb.print_and_execute("flushregs") my_gdb.print_and_execute("set $ebp=%s" % jmbuf[JB_BP]) if alternative: my_gdb.print_and_execute("set $esp=$ebp-0x2c") else: my_gdb.print_and_execute("set $esp=%s-0xd00" % jmbuf[JB_SP]) my_gdb.print_and_execute("set $eip=__longjmp") my_gdb.print_and_execute("up", to_string=True) my_gdb.print_and_execute("set $eip=contextSwitch+33") #my_gdb.print_and_execute("down", to_string=True) my_gdb.print_and_execute("flushregs") state.select_task = next_ return True
##################################################### REGISTERS_read = ("$esp", "$ebp", "(void *) $eip") REGISTERS_write = ("$esp", "$ebp", "$eip")
[docs]def save_current_thread(): return [gdb.parse_and_eval(reg) for reg in REGISTERS_read]
[docs]def reload_current_thread(stop_regs): for reg_name, reg_val in map(None, REGISTERS_write, stop_regs): command = "set %s=%s" % (reg_name, str(reg_val)) my_gdb.log.debug(command) gdb.execute(command)