def _execute_callback(self, callback, data, t): '''Dont execute the callback right now, instead defer the execution of the event and move it to the gdb event loop to be executed in some point in the future. This method can be running in a separate thread (async)''' event = functools.partial(self._execute_callback_in_gdb_loop, callback, data, t) gdb.post_event(lambda: self._handle_event_in_gdb_event_loop(event))
def getNameReg(regName): """Returns the name of the symbol contained in a register, if any.""" # get information about what variables are being changed gdb.post_event(Executor("info symbol ${}".format(regName), p=True)) readVal = responseQueueHandle.get() memName = parseSymbolInfo(readVal) return memName
def stop_handler(self, event): try: self.callchains.append(dmdprof_get_stack()) except RuntimeError: pass gdb.post_event(Executor("continue"))
def post_interrupt_task(interrupt_arg): # Halt the target by interrupting it # This must only run on GDB's queue def interrupt_task(): if not interrupt_arg["aborted"]: gdb_execute("interrupt") gdb.post_event(interrupt_task)
def entry_append(self, name): addr = self.pc() outstr = ("*" * (self.depth + 1)) + " > " + name if self.sourceinfo: outstr += " [[%s]]" % addr2line(self.elf, addr) gdb.post_event(PrintEvent(self.depth, name, "entry", outstr, self.log)) self.depth += 1
def post_interrupt_task(interrupt_arg): # Halt the target by interrupting it # This must only run on GDB's queue def interrupt_task(): if not interrupt_arg["aborted"]: gdb.execute("interrupt") gdb.post_event(interrupt_task)
def longwrite_stophook(self, bp, ret): substagenum = bp.controller.current_substage gdb.post_event( CheckWrite(bp.stage, bp.controller.current_substage_name, substagenum, bp.writeinfo['pc'], bp.relocated, bp.writeinfo['start'], bp.writeinfo['end'])) return ret
def get_buffer(self, symtab, filename): if filename in self.buffers: return self.buffers[filename] if not self.lang_manager: self.lang_manager = GtkSource.LanguageManager.get_default() buff = GtkSource.Buffer() if filename: buff.set_language(self.lang_manager.guess_language(filename)) buff.set_style_scheme(gui.params.source_theme.get_scheme()) buff.begin_not_undoable_action() try: contents = open(filename).read() except: return None buff.set_text(contents) buff.end_not_undoable_action() buff.set_modified(False) buff.filename = filename if symtab is not None: gdb.post_event(lambda: self._get_lines_update(buff, symtab)) self.buffers[filename] = buff return buff
def stage_finish(self, now=False): fd = FlushDatabase(self.controller.current_stage) gdb.flush() if now: fd() else: gdb.post_event(fd)
def inner(self, *args, **kwargs): if self.use_post_event: # create ephemeral queue q = Queue() # create an invocation that calls the decorated function class Invocation(object): def __call__(killme): # when the invocation is called, we call the function and stick the result into the queue try: res = func(self, *args, **kwargs) except Exception as e: # if we got an exception, just queue that instead res = e q.put(res) # post this invocation to be called on the main thread at the next opportunity gdb.post_event(Invocation()) # now we wait until there's something in the queue, which indicates that the invocation has run and return # the result that was pushed onto the queue by the invocation res = q.get() # if we got an exception back from the posted event, raise it if isinstance(res, Exception): raise res return res else: return func(self, *args, **kwargs)
def dowriteinfo(self, writedst, size, pc, lr, cpsr, pid, origpc, stage, substage, name): global stepnum stepnum += 1 gdb.post_event(WriteDatabase(time.time(), pid, size, writedst, pc, lr, cpsr, stepnum, origpc, stage, substage, name))
def getNameMem(addr): """Returns the name of the symbol at the given memory address, if any.""" # return information about what variable(s) (if any) are being changed gdb.post_event(Executor("info symbol {}".format(addr), p=True)) readVal = responseQueueHandle.get() memName = parseSymbolInfo(readVal) return memName
def invoke (self, arg, from_tty): self.dont_repeat() if not self.state.input: print "no input file provided" return gdb.post_event(lambda: gdb.execute("run < %s" % (self.state.input), True) )
def disable_breakpoint(self, b, disable=True, delete=True): bp = b.breakpoint addr = self.spec_to_addr(bp.location) bp.enabled = not disable if disable and delete: if b in self.breakpoints: self.breakpoints.remove(b) gdb.post_event(lambda: self._delete_bp(bp, addr))
def getVariable(varname): """Read a variable using GDB interface""" gdb.post_event(Executor("p {}".format(varname), p=True)) try: readVal = responseQueueHandle.get(timeout=2) except Empty: return "error reading variable {}".format(varname) return readVal.split(" = ")[-1].rstrip()
def stop(self): if self.cnt > 0: self.cnt -= 1 return False self.enabled = False gdb.post_event(end_of_level) return True
def readMem(addr): """Returns the value at a given memory address.""" gdb.post_event(Executor("x/wx {}".format(addr), p=True)) readVal = responseQueueHandle.get() # hex string memVal = readVal.split(":")[-1].rstrip() return memVal
def stop(self): def erase(): self.delete_siblings() self.delete() gdb.post_event( erase ) if self.on_break: self.on_break() return True
def stop(self): try: values = self.get_values() except Exception as e: gdb.write("Exception at %s.get_values(): %s\n" % ( self.__class__.__name__, e), gdb.STDERR) return False if not values: gdb.write("%s.get_values() did not return values.\n" % ( self.__class__.__name__,), gdb.STDERR) return False def print_values(): gdb.write("Values:\n", gdb.STDERR) for k, v in values.items(): gdb.write(" %s: %s\n" % (k, v), gdb.STDERR) gdb.write("\n", gdb.STDERR) for k, match_func in self.matches.items(): try: v = values[k] except KeyError: gdb.write("%s.get_values() did not provide key '%s'.\n" % ( self.__class__.__name__, k), gdb.STDERR) self.print_matches(values) print_values() return False try: if not match_func(v): return False except Exception as e: gdb.write("Exception at %s.stop() while matching %s %s (%s): %s\n" % ( self.__class__.__name__, k, v, match_func.__doc__, e,), gdb.STDERR) self.print_matches(values) return False method = values.get("method") banner = values.get("banner") if not method: node = values.get("node") if node: gdb.write("NODE: %s\n" % (node,), gdb.STDERR) gdb.write("%s did not return the internal method to break at.\n" % ( self.__class__.__name__,), gdb.STDERR) self.print_matches(values) gdb.write("Breaking at the caller function %s\n" % (self.location,), gdb.STDERR) return True def add_breakpoint(): try: self.InternalBreak(method, banner, self.matches, values) except Exception as e: gdb.write("Could not add internal breakpoint: %s\n" % (e,), gdb.STDERR) self.print_matches(values) gdb.post_event(add_breakpoint) return False
def stop_handler(self, event=None): if isinstance(event, gdb.SignalEvent): pass elif isinstance(event, gdb.BreakpointEvent): pass elif self.is_target(): gdb.post_event(self.do_restore) else: gdb.post_event(self.do_continue)
def poll(self): msg = self.sync.tunnel.poll() if msg: batch = [cmd.strip() for cmd in msg.split('\n') if cmd] if batch: gdb.post_event(Runner(batch)) else: gdb.post_event(Runner(['syncoff'])) self.stop()
def poll(self): msg = self.sync.tunnel.poll() if msg: batch = [cmd.strip() for cmd in msg.split('\n') if cmd] if batch: gdb.post_event(Runner(batch)) else: print("[[sync]] Warning: going to syncoff??") gdb.post_event(Runner(['syncoff'])) self.stop()
def dowriteinfo(self, writedst, size, pc, lr, cpsr, pid, origpc, stage, substage, name): if hasattr(self.controller, "call_count"): ccount = self.controller.call_count else: ccount = 0 gdb.post_event( WriteDatabase(time.time(), pid, size, writedst, pc, lr, cpsr, origpc, stage, substage, name, ccount))
def profile(self): gdb.execute("set pagination off") gdb.execute("start") self.pid = gdb.selected_inferior().pid self.callchains = [] gdb.events.cont.connect(self.cont_handler) gdb.events.stop.connect(self.stop_handler) gdb.events.exited.connect(self.exit_handler) gdb.post_event(Executor("continue"))
def process_messages(): global isStopped while True: data = conn.recv(1024) sys.stdout.flush() # for now, ignore client data that was received when # we aren't stopped if isStopped != True: continue else: gdb.post_event(MessageParser(data))
def on_exit(self, event): result = { "success": len(self.__instances) == 0, "instances": list(map(lambda instance: instance.export(), self.__instances.values())), "instances-created": self.__instances_created } with open(self.__reportFile, "w") as f: json.dump(result, f, indent=4) logging.info("report written to " + self.__reportFile) gdb.post_event(gdb_quit)
def getSymAddr(name): """Returns the address of the symbol.""" gdb.post_event(Executor("info address {}".format(name), p=True)) readVal = responseQueueHandle.get() # if the name exists, the address will be the last thing, in hex lastElem = readVal.replace(".", "").split()[-1] try: memAddr = int(lastElem, 16) except ValueError: memAddr = None return memAddr
def stop(self): ret_data = gdb.execute("info arg", to_string=True) ret_code = int(ret_data.split(" = ")[1]) print("At program exit normal with status: {}".format(ret_code)) print("Instruction Count = {}".format(get_instr_count())) gdb.execute("when") # print "Instruction Count = {}".format(get_instr_count()) ATP_Breakpoint(atp_loc) # gdb.execute("set scheduler-locking on") gdb.post_event(lambda s: gdb.execute("reverse-continue")) gdb.post_event(lambda s: gdb.execute("reverse-continue"))
def readReg(regName): """Returns the value of a register.""" gdb.post_event(Executor("i r {}".format(regName), p=True)) readVal = responseQueueHandle.get() # returns the hex string if "raw" in readVal: # it's a floating point register and must be parsed differently regVal = readVal.split()[-1][:-1].strip() else: regVal = readVal.split()[-2].rstrip() return regVal
def work(self, dummy): while not self.gdb_exited and (self.timeout is None or self.timeout > datetime.datetime.now()): time.sleep(1) if self.gdb_exited or self.timeout is None: return if self.gdb_running: self.i_am_interrupting = True gdb.post_event(self.interrupt) else: gdb.post_event(self.quit)
def add(self, window): self.windows.insert(0, window) if len(self.windows) == 1: gdb.post_event(self._connect_events) # Show something. if self.work_location is not None: (frame, symtab, filename, lineno) = self.work_location self.work_location = None gui.startup.send_to_gtk(lambda: self.show_source(frame, symtab, filename, lineno))
def stop(self): self.enabled = False fct_stop = self.parent.prepare_after(self.fct_data) gdb.post_event(self.delete) while FunctionBreakpoint.stop_requests: print(FunctionBreakpoint.stop_requests.pop()) fct_stop = True return fct_stop
def stop(self): frame = gdb.selected_frame() args = [arg for arg in frame.block() if arg.is_argument] exit_code = None for arg in args: exit_code = str(arg.value(frame)) break gdb.post_event(lambda: self.exit(exit_code)) return True
def exit_append(self, name, fake=False): addr = self.pc() self.depth -= 1 outstr = ("*" * (self.depth + 1)) + " < " + name if not fake: if not self.minimal: outstr += "@0x%x" % addr if self.sourceinfo: outstr += " [[%s]]" % addr2line(self.elf, addr) else: outstr += " (return out of scope)" gdb.post_event(PrintEvent(self.depth, name, "exit", outstr, self.log))
def _stop(self, bp, ret): c = self.plugin gdb.post_event(WriteResults(c.depth, self.name, "entry", self.fnloc, self.line, c._minimal)) e = CallExitBreak(self.name, self.controller, self.stage, self, c.depth) c.depth += 1 if not e.valid: c.depth -= 1 if self.no_rec and self.breakpoint: self.controller.disable_breakpoint(self, delete=False) return False
def event_loop(self): while True: requests_to_process = [] with self._lock: requests_to_process = self._pending_requests self._pending_requests = [] while requests_to_process: callback = requests_to_process.pop(0) gdb.post_event(callback) time.sleep(0.1) pass
def _stop(self, bp, ret): c = self.plugin c.depth = self.depth #if not self.depth == c.depth: # return gdb.post_event(WriteResults(self.depth, self.name, "exit", c.pc(), "", c._minimal)) if self.entry.no_rec: self.controller.disable_breakpoint(self.entry, disable=False) return False
def watch_active_inferior(callback, initial_inferior, stop_event=None): """Watch for changes in the currently selected inferior and invoke callback This function is meant to be used on a background thread, since it would otherwise block the main thread. If no stop_event is provided, the function will simply run forever. This would work if you set the thread as a daemon. NOTE: More than one callback can be active at a time if rapid inferior switching occurs, so keep callbacks as short as possible. """ # A bit hackish, but we use a list here since it # is mutable and so it can be passed to the function # and still update the original value last_inferior = [initial_inferior] event_finished = [True] def check_for_change(): event_finished[0] = True try: current_inferior = selected_inferior() if current_inferior != last_inferior[0]: callback(current_inferior) last_inferior[0] = current_inferior except: pass def should_stop(): if stop_event is not None: return stop_event.is_set() else: return False while not should_stop(): # Very important to use post_event here. It is not safe # to use gdb functions from a thread that isn't the main # one, and it *will* lead to segmentation faults event_finished[0] = False gdb.post_event(check_for_change) # Wait for the event to finish before starting # another one. This doesn't wait for callbacks # to finish though, so there might be several # which fire in a row if inferiors are switching while not event_finished[0]: time.sleep(0.05) time.sleep(0.2)
def _install_hook(self): # Well this is super annoying and ugly gdb_hook_command_parts = [ 'define hook-{0}','if $argc == 0', '{1}["{0}"]()', 'end', 'if $argc == 1', '{1}["{0}"]("{2}0")', 'end', 'if $argc == 2', '{1}["{0}"]("{2}0","{2}1")', 'end', 'if $argc == 3', '{1}["{0}"]("{2}0","{2}1","{2}2")', 'end', 'if $argc == 4', '{1}["{0}"]("{2}0","{2}1","{2}2","{2}3")', 'end', 'if $argc == 5', '{1}["{0}"]("{2}0","{2}1","{2}2","{2}3","{2}4")', 'end', 'if $argc == 6', '{1}["{0}"]("{2}0","{2}1","{2}2","{2}3","{2}4","{2}5")', 'end', 'if $argc == 7', '{1}["{0}"]("{2}0","{2}1","{2}2","{2}3","{2}4","{2}5",{2}6)', 'end', 'if $argc == 8', '{1}["{0}"]("{2}0","{2}1","{2}2","{2}3","{2}4","{2}5","{2}6","{2}7")', 'end', 'if $argc == 9', '{1}["{0}"]("{2}0","{2}1","{2}2","{2}3","{2}4","{2}5","{2}6","{2}7","{2}8")', 'end', 'if $argc == 10', '{1}["{0}"]("{2}0","{2}1","{2}2","{2}3","{2}4","{2}5","{2}6","{2}7","{2}8","{2}9")', 'end' ] gdb_hook_command = '\n'.join(gdb_hook_command_parts) formatted_hook_command = gdb_hook_command.format(self.command, "python gdb._hooks", "$arg") # Write the command to file, then source it def write_and_source(): try: with tempfile.NamedTemporaryFile(delete=False) as f: f.write(formatted_hook_command) f.close() gdb.execute("source {0}".format(f.name)) # XXX - This is a hack. Apparently GDB isn't reading # the file right away on execute, and deleting it right # away causes the command not to be defined time.sleep(0.15) f.delete() except: pass # The use of post_event is important here. Without it, # the commands don't seem to actually get defined in GDB gdb.post_event(write_and_source) try: gdb._hooks[self.command] = self._on_call except AttributeError: gdb._hooks = {} gdb._hooks[self.command] = self._on_call _GDBHook._hook_registry[self.command] = self
def invoke (self, arg, from_tty): try: (src_lines, src_lineno, sir_lines, sir_lineno) = self.state.adjusted_linenos() except NoFrame: print "no selected frame" return except CodeOutsideScope as e: log("e: %s" % e) print "not currently executing pyc generated code" return def selector(src_ln, sir_ln): if src_ln == src_lineno: return False return True self.state.step_bps(selector) gdb.post_event(lambda: gdb.execute("continue", True, False) )
def stop(self): try: mozz.debug("mozz_gdb bp %d: hit_count=%r, visible=%r" % ( self.number, self.hit_count, self.visible )) self.host.on_break() if self.host.need_to_flush_inferior_procs(): gdb.post_event(lambda: self.host.flush_inferior_procs()) return True if self.host.drop_into_cli() \ or not self.host.should_continue() \ or self.host.inferior().is_in_step_mode(): return True except Exception as e: gdb_log("exception during breakpoint processing: %s\n%s" % (e, traceback.format_exc())) self.host.set_drop_into_cli() return True return False
def onEnqueue(self): gdb.post_event(self)
global interrupt_arg ignore_events = True if interrupt_timer is not None: interrupt_timer.cancel() interrupt_arg["aborted"] = True interrupt_arg = None stop_delay = 0 try: stop_delay = generator.send(event) except: print("Error") traceback.print_exc() interrupt_arg = {"aborted": False} interrupt_timer = Timer(stop_delay, post_interrupt_task, [interrupt_arg]) interrupt_timer.start() ignore_events = False # Runs on stop events and posts run_generator to the # main queue so it can continue execution def stop_handler(event): if ignore_events: return bound_run_generator = partial(run_generator, event) gdb.post_event(bound_run_generator) gdb.events.stop.connect(stop_handler) # Start testing bound_run_generator = partial(run_generator, None) gdb.post_event(bound_run_generator)
def process_IN_CLOSE_WRITE(self, event): def inner(): on_reload_event(event) gdb.post_event(inner)
def stop_handler(event): if ignore_events: return bound_run_generator = partial(run_generator, event) gdb.post_event(bound_run_generator)
def op_proxy(dec, op, param, *args): gdb.post_event(lambda: func(dec, op, param, *args))
def execCommands(clist): for c in clist: print('executing: ' + c) #gdb.flush() gdb.post_event(CommandEvent(c))
def stop(self): callback = lambda: self._callback(self._location, clean_remaining(self._remaining)) if self._go_on: callback = lambda: (callback(), gdb.execute("continue")) gdb.post_event(callback) return True
def hello (self, *args): gdb.post_event (printit)
def on_message(self, message): message = ObjectDict(escape.json_decode(message)) gdb.post_event(partial(on_message, self.get_handler(), message))
def stop(self): handler() gdb.post_event(gdb_continue)
def post_partial(f, *a, **kw): gdb.post_event(functools.partial(f, *a, **kw))