diff --git a/debuggers/gdb/gdb_mi_driver.py b/debuggers/gdb/gdb_mi_driver.py index 6059c35..b476ce3 100755 --- a/debuggers/gdb/gdb_mi_driver.py +++ b/debuggers/gdb/gdb_mi_driver.py @@ -16,14 +16,22 @@ class GDBMiDebugger(Driver): gdb_instances = None - def __init__(self, base_args, base_script_file_path, regression_args, regression_script_file_path): + def __init__(self, base_args, base_script_file_path, regression_args, regression_script_file_path, + base_pid=None, regression_pid=None): self.base_gdb_instance = create_IDDGdbController(base_script_file_path) self.regressed_gdb_instance = create_IDDGdbController(regression_script_file_path) self.gdb_instances = { 'base': self.base_gdb_instance, 'regressed': self.regressed_gdb_instance } - self.run_single_raw_command('file ' + base_args, 'base') - self.run_single_raw_command('file ' + regression_args, 'regressed') + if base_pid is None: + self.run_single_raw_command('file ' + base_args, 'base') + else: + self.run_single_raw_command('attach ' + base_pid, 'base') + + if regression_pid is None: + self.run_single_raw_command('file ' + regression_args, 'regressed') + else: + self.run_single_raw_command('attach ' + regression_pid, 'regressed') dirname = os.path.dirname(__file__) self.run_parallel_raw_command("source " + os.path.join(dirname, "gdb_commands.py")) @@ -35,23 +43,11 @@ def run_parallel_command(self, command): # wait till base is done raw_result = self.base_gdb_instance.recv() - - # make sure all output is flushed - # time.sleep(.005) - self.base_gdb_instance.send((("",), {"timeout_sec": 60})) - raw_result += self.base_gdb_instance.recv() - # parse output (base) base_response = self.parse_command_output(raw_result) # wait till regression is done raw_result = self.regressed_gdb_instance.recv() - - # make sure all output is flushed - # time.sleep(.005) - self.regressed_gdb_instance.send((("",), {"timeout_sec": 60})) - raw_result += self.regressed_gdb_instance.recv() - # parse output regression regressed_response = self.parse_command_output(raw_result) @@ -72,12 +68,7 @@ def run_single_command(self, command, version): self.gdb_instances[version].send(((" {command}\n".format(command = command),), {"timeout_sec": 60})) raw_result = self.gdb_instances[version].recv() - - # make sure all output is flushed - # time.sleep(.005) - self.gdb_instances[version].send((("",), {"timeout_sec": 60})) - raw_result += self.gdb_instances[version].recv() - + return self.parse_command_output(raw_result) def run_single_special_command(self, command, version): @@ -87,10 +78,6 @@ def run_single_special_command(self, command, version): self.gdb_instances[version].send(((" {command}\n".format(command = command),), {"timeout_sec": 60})) raw_result = self.gdb_instances[version].recv() - # flush output - self.gdb_instances[version].send((("",), {"timeout_sec": 60})) - raw_result += self.gdb_instances[version].recv() - return self.parse_special_command_output(raw_result) def parse_special_command_output(self, raw_result): @@ -155,20 +142,26 @@ def get_current_registers(self): return { "base" : base_stack_frame, "regressed" : regression_stack_frame } def run_parallel_raw_command(self, command): - base_result = str(self.run_single_raw_command(command, "base")) - regression_result = str(self.run_single_raw_command(command, "regressed")) + self.base_gdb_instance.send((("{command}\n".format(command = command),), {"timeout_sec": 60})) + self.regressed_gdb_instance.send((("{command}\n".format(command = command),), {"timeout_sec": 60})) + + raw_result = self.base_gdb_instance.recv() + base_result = str(self.parse_raw_command_output(raw_result)) + raw_result = self.regressed_gdb_instance.recv() + regression_result = str(self.parse_raw_command_output(raw_result)) return { "base": base_result, "regressed": regression_result } - def run_single_raw_command(self, command, version): + def parse_raw_command_output(self, raw_result): result = [] - self.gdb_instances[version].send((("{command}\n".format(command = command),), {"timeout_sec": 60})) - raw_result = self.gdb_instances[version].recv() - for item in raw_result: result.append(str(item)) - return result + def run_single_raw_command(self, command, version): + self.gdb_instances[version].send((("{command}\n".format(command = command),), {"timeout_sec": 60})) + raw_result = self.gdb_instances[version].recv() + return self.parse_raw_command_output(raw_result) + def terminate(self): terminate_all_IDDGdbController() diff --git a/idd.py b/idd.py index 994f053..b75ad76 100755 --- a/idd.py +++ b/idd.py @@ -311,9 +311,11 @@ async def execute_debugger_command(self, event: Input.Changed) -> None: parser = argparse.ArgumentParser(description='Diff Debug for simple debugging!') parser.add_argument('-c','--comparator', help='Choose a comparator', default='gdb') - parser.add_argument('-ba','--base-args', help='Base executable args', default='[]', nargs='+') + parser.add_argument('-ba','--base-args', help='Base executable args', default="", nargs='+') + parser.add_argument('-bpid','--base-processid', help='Base process ID', default=None) parser.add_argument('-bs','--base-script-path', help='Base preliminary script file path', default=None, nargs='+') - parser.add_argument('-ra','--regression-args', help='Regression executable args', default='[]', nargs='+') + parser.add_argument('-ra','--regression-args', help='Regression executable args', default="", nargs='+') + parser.add_argument('-rpid','--regression-processid', help='Regression process ID', default=None) parser.add_argument('-rs','--regression-script-path', help='Regression preliminary script file path', default=None, nargs='+') parser.add_argument('-r','--remote_host', help='The host of the remote server', default='localhost') parser.add_argument('-p','--platform', help='The platform of the remote server: macosx, linux', default='linux') @@ -325,17 +327,36 @@ async def execute_debugger_command(self, event: Input.Changed) -> None: comparator = args['comparator'] ba = ' '.join(args['base_args']) + bpid = args['base_processid'] bs = ' '.join(args['base_script_path']) if args['base_script_path'] is not None else None ra = ' '.join(args['regression_args']) + rpid = args['regression_processid'] rs = ' '.join(args['regression_script_path']) if args["regression_script_path"] is not None else None if comparator == 'gdb': from debuggers.gdb.gdb_mi_driver import GDBMiDebugger - Debugger = GDBMiDebugger(ba, bs, ra, rs) + if ba != "" and bpid is not None: + raise Exception("Both executable and process ID given for base. This is not possible") + if ra != "" and rpid is not None: + raise Exception("Both executable and process ID given for regression. This is not possible") + + if ba == "": + if ra == "": + Debugger = GDBMiDebugger(ba, bs, ra, rs, base_pid=bpid, regression_pid=rpid) + else: + Debugger = GDBMiDebugger(ba, bs, ra, rs, base_pid=bpid) + else: + if ra == "": + Debugger = GDBMiDebugger(ba, bs, ra, rs, regression_pid=rpid) + else: + Debugger = GDBMiDebugger(ba, bs, ra, rs) + elif comparator == 'lldb': from debuggers.lldb.lldb_driver import LLDBDebugger + if ba == "" or ra == "": + raise Exception("LLDB can only be used by launching executable and executable is not provided") Debugger = LLDBDebugger(ba, ra) else: sys.exit("Invalid comparator set") @@ -343,4 +364,4 @@ async def execute_debugger_command(self, event: Input.Changed) -> None: disable_registers = args["disable_registers"] disable_assembly = args["disable_assembly"] dd = DiffDebug(disable_assembly, disable_registers) - dd.run() \ No newline at end of file + dd.run()