diff --git a/api/debuggerapi.h b/api/debuggerapi.h index 734de8cd..19cb926c 100644 --- a/api/debuggerapi.h +++ b/api/debuggerapi.h @@ -485,6 +485,7 @@ namespace BinaryNinjaDebuggerAPI { // target control bool Launch(); + bool LaunchAndWait(); bool Execute(); void Restart(); void Quit(); diff --git a/api/debuggercontroller.cpp b/api/debuggercontroller.cpp index 2ed7ef37..5794498c 100644 --- a/api/debuggercontroller.cpp +++ b/api/debuggercontroller.cpp @@ -284,6 +284,12 @@ bool DebuggerController::Launch() } +bool DebuggerController::LaunchAndWait() +{ + return BNDebuggerLaunchAndWait(m_object); +} + + bool DebuggerController::Execute() { return BNDebuggerExecute(m_object); diff --git a/api/ffi.h b/api/ffi.h index ad090366..68e6d289 100644 --- a/api/ffi.h +++ b/api/ffi.h @@ -351,6 +351,7 @@ extern "C" // target control DEBUGGER_FFI_API bool BNDebuggerLaunch(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerLaunchAndWait(BNDebuggerController* controller); DEBUGGER_FFI_API bool BNDebuggerExecute(BNDebuggerController* controller); DEBUGGER_FFI_API void BNDebuggerRestart(BNDebuggerController* controller); DEBUGGER_FFI_API void BNDebuggerQuit(BNDebuggerController* controller); diff --git a/api/python/debuggercontroller.py b/api/python/debuggercontroller.py index 1c8266d6..f3e9887a 100644 --- a/api/python/debuggercontroller.py +++ b/api/python/debuggercontroller.py @@ -731,6 +731,12 @@ def launch(self) -> bool: """ return dbgcore.BNDebuggerLaunch(self.handle) + def launch_and_wait(self) -> bool: + """ + Launch the target and wait for all debugger events to be processed + """ + return dbgcore.BNDebuggerLaunchAndWait(self.handle) + def restart(self) -> None: """ Restart the target diff --git a/core/ffi.cpp b/core/ffi.cpp index 41e4088d..0cff6a5f 100644 --- a/core/ffi.cpp +++ b/core/ffi.cpp @@ -398,6 +398,12 @@ bool BNDebuggerLaunch(BNDebuggerController* controller) } +bool BNDebuggerLaunchAndWait(BNDebuggerController* controller) +{ + return controller->object->LaunchAndWait(); +} + + bool BNDebuggerExecute(BNDebuggerController* controller) { return controller->object->Execute(); diff --git a/test/debugger_test.py b/test/debugger_test.py index 0bf57f70..c322373f 100644 --- a/test/debugger_test.py +++ b/test/debugger_test.py @@ -57,7 +57,7 @@ def test_repeated_use(self): def run_once(): dbg = DebuggerController(bv) dbg.cmd_line = 'foobar' - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) # continue execution to the entry point, and check the stop reason reason = dbg.step_into_and_wait() @@ -93,7 +93,7 @@ def test_return_code(self): dbg = DebuggerController(bv) dbg.cmd_line = arg - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) reason = dbg.go_and_wait() self.assertEqual(reason, DebugStopReason.ProcessExited) exit_code = dbg.exit_code @@ -111,7 +111,7 @@ def test_exception_segfault(self): dbg = DebuggerController(bv) dbg.cmd_line = 'segfault' - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) # time.sleep(1) reason = dbg.go_and_wait() self.expect_segfault(reason) @@ -123,7 +123,7 @@ def test_exception_segfault(self): # bv = BinaryViewType.get_view_of_file(fpath) # dbg = DebuggerController(bv) # dbg.cmd_line = 'illegalinstr' - # self.assertTrue(dbg.launch()) + # self.assertTrue(dbg.launch_and_wait()) # dbg.go() # reason = dbg.go() # if platform.system() in ['Windows', 'Linux']: @@ -146,7 +146,7 @@ def test_exception_divzero(self): dbg = DebuggerController(bv) if not self.arch == 'arm64': dbg.cmd_line = 'divzero' - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) reason = dbg.go_and_wait() self.expect_divide_by_zero(reason) dbg.quit_and_wait() @@ -156,7 +156,7 @@ def test_step_into(self): bv = BinaryViewType.get_view_of_file(fpath) dbg = DebuggerController(bv) dbg.cmd_line = 'foobar' - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) reason = dbg.step_into_and_wait() self.assertEqual(reason, DebugStopReason.SingleStep) reason = dbg.step_into_and_wait() @@ -168,7 +168,7 @@ def test_breakpoint(self): fpath = name_to_fpath('helloworld', self.arch) bv = BinaryViewType.get_view_of_file(fpath) dbg = DebuggerController(bv) - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) # TODO: right now we are not returning whether the operation succeeds, so we cannot use assertTrue/assertFalse # breakpoint set/clear should fail at 0 self.assertIsNone(dbg.add_breakpoint(0)) @@ -186,7 +186,7 @@ def test_register_read_write(self): fpath = name_to_fpath('helloworld', self.arch) bv = BinaryViewType.get_view_of_file(fpath) dbg = DebuggerController(bv) - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) arch_name = bv.arch.name if arch_name == 'x86': @@ -218,7 +218,7 @@ def test_memory_read_write(self): fpath = name_to_fpath('helloworld', self.arch) bv = BinaryViewType.get_view_of_file(fpath) dbg = DebuggerController(bv) - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) # Due to https://github.com/Vector35/debugger/issues/124, we have to skip the bytes at the entry point addr = dbg.ip + 10 @@ -239,7 +239,7 @@ def test_thread(self): fpath = name_to_fpath('helloworld_thread', self.arch) bv = BinaryViewType.get_view_of_file(fpath) dbg = DebuggerController(bv) - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) dbg.go() time.sleep(1) @@ -264,7 +264,7 @@ def test_assembly_code(self): fpath = name_to_fpath('asmtest', 'x86_64') bv = BinaryViewType.get_view_of_file(fpath) dbg = DebuggerController(bv) - self.assertTrue(dbg.launch()) + self.assertTrue(dbg.launch_and_wait()) entry = dbg.live_view.entry_point self.assertEqual(dbg.ip, entry)