diff --git a/api/debuggerapi.h b/api/debuggerapi.h index 76b3f68e..dd6075b0 100644 --- a/api/debuggerapi.h +++ b/api/debuggerapi.h @@ -567,6 +567,8 @@ namespace BinaryNinjaDebuggerAPI { bool SetAdapterProperty(const std::string& name, const BinaryNinja::Ref& value); bool ActivateDebugAdapter(); + + void PostDebuggerEvent(const DebuggerEvent& event); }; diff --git a/api/debuggercontroller.cpp b/api/debuggercontroller.cpp index 747096ce..f97b9678 100644 --- a/api/debuggercontroller.cpp +++ b/api/debuggercontroller.cpp @@ -735,3 +735,36 @@ bool DebuggerController::ActivateDebugAdapter() { return BNDebuggerActivateDebugAdapter(m_object); } + + +void DebuggerController::PostDebuggerEvent(const DebuggerEvent &event) +{ + BNDebuggerEvent* evt = new BNDebuggerEvent; + + evt->type = event.type; + evt->data.targetStoppedData.reason = event.data.targetStoppedData.reason; + evt->data.targetStoppedData.exitCode = event.data.targetStoppedData.exitCode; + evt->data.targetStoppedData.lastActiveThread = event.data.targetStoppedData.lastActiveThread; + evt->data.targetStoppedData.data = event.data.targetStoppedData.data; + + evt->data.errorData.error = BNDebuggerAllocString(event.data.errorData.error.c_str()); + evt->data.errorData.shortError = BNDebuggerAllocString(event.data.errorData.shortError.c_str()); + evt->data.errorData.data = event.data.errorData.data; + + evt->data.exitData.exitCode = event.data.exitData.exitCode; + + evt->data.relativeAddress.module = BNDebuggerAllocString(event.data.relativeAddress.module.c_str()); + evt->data.relativeAddress.offset = event.data.relativeAddress.offset; + + evt->data.absoluteAddress = event.data.absoluteAddress; + + evt->data.messageData.message = BNDebuggerAllocString(event.data.messageData.message.c_str()); + + BNDebuggerPostDebuggerEvent(m_object, evt); + + BNDebuggerFreeString(evt->data.errorData.error); + BNDebuggerFreeString(evt->data.errorData.shortError); + BNDebuggerFreeString(evt->data.relativeAddress.module); + BNDebuggerFreeString(evt->data.messageData.message); + delete evt; +} diff --git a/api/ffi.h b/api/ffi.h index b60cff36..2bd3da28 100644 --- a/api/ffi.h +++ b/api/ffi.h @@ -235,6 +235,8 @@ extern "C" // in the register widget, etc.). It is not emitted when the target executes and then stops. RegisterChangedEvent, ThreadStateChangedEvent, + + ForceMemoryCacheUpdateEvent, }; @@ -431,6 +433,8 @@ extern "C" DEBUGGER_FFI_API bool BNDebuggerActivateDebugAdapter(BNDebuggerController* controller); + DEBUGGER_FFI_API void BNDebuggerPostDebuggerEvent(BNDebuggerController* controller, BNDebuggerEvent* event); + // DebugAdapterType DEBUGGER_FFI_API BNDebugAdapterType* BNGetDebugAdapterTypeByName(const char* name); DEBUGGER_FFI_API bool BNDebugAdapterTypeCanExecute(BNDebugAdapterType* adapter, BNBinaryView* data); diff --git a/core/ffi.cpp b/core/ffi.cpp index d9a6bb44..f7b1f08f 100644 --- a/core/ffi.cpp +++ b/core/ffi.cpp @@ -927,3 +927,29 @@ bool BNDebuggerActivateDebugAdapter(BNDebuggerController* controller) { return controller->object->ActivateDebugAdapter(); } + + +void BNDebuggerPostDebuggerEvent(BNDebuggerController* controller, BNDebuggerEvent* event) +{ + DebuggerEvent evt; + evt.type = event->type; + evt.data.targetStoppedData.reason = event->data.targetStoppedData.reason; + evt.data.targetStoppedData.exitCode = event->data.targetStoppedData.exitCode; + evt.data.targetStoppedData.lastActiveThread = event->data.targetStoppedData.lastActiveThread; + evt.data.targetStoppedData.data = event->data.targetStoppedData.data; + + evt.data.errorData.error = event->data.errorData.error; + evt.data.errorData.shortError = event->data.errorData.shortError; + evt.data.errorData.data = event->data.errorData.data; + + evt.data.exitData.exitCode = event->data.exitData.exitCode; + + evt.data.relativeAddress.module = event->data.relativeAddress.module; + evt.data.relativeAddress.offset = event->data.relativeAddress.offset; + + evt.data.absoluteAddress = event->data.absoluteAddress; + + evt.data.messageData.message = event->data.messageData.message; + + controller->object->PostDebuggerEvent(evt); +} diff --git a/core/processview.cpp b/core/processview.cpp index a120989e..adaf9faa 100644 --- a/core/processview.cpp +++ b/core/processview.cpp @@ -171,6 +171,12 @@ void DebugProcessView::MarkDirty() } +void DebugProcessView::ForceMemoryCacheUpdate() +{ + BinaryView::NotifyDataWritten(0, GetLength()); +} + + void DebugProcessView::eventHandler(const DebuggerEvent &event) { switch (event.type) @@ -180,6 +186,9 @@ void DebugProcessView::eventHandler(const DebuggerEvent &event) // deleted. And it can cause a crash in certain cases. MarkDirty(); break; + case ForceMemoryCacheUpdateEvent: + ForceMemoryCacheUpdate(); + break; default: break; } diff --git a/core/processview.h b/core/processview.h index da70db12..efc8dfda 100644 --- a/core/processview.h +++ b/core/processview.h @@ -59,6 +59,7 @@ namespace BinaryNinjaDebugger virtual bool Init() override; void MarkDirty(); + void ForceMemoryCacheUpdate(); void eventHandler(const DebuggerEvent& event); }; diff --git a/ui/ui.cpp b/ui/ui.cpp index a4041805..535e4877 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -725,6 +725,24 @@ void GlobalDebuggerUI::SetupMenu(UIContext* context) connectedAndStopped)); debuggerMenu->addAction("Create Stack View", "Misc"); + UIAction::registerAction("Force Update Memory Cache"); + context->globalActions()->bindAction("Force Update Memory Cache", + UIAction( + [=](const UIActionContext& ctxt) { + if (!ctxt.binaryView) + return; + + auto controller = DebuggerController::GetController(ctxt.binaryView); + if (!controller) + return; + + DebuggerEvent event; + event.type = ForceMemoryCacheUpdateEvent; + controller->PostDebuggerEvent(event); + }, + connectedAndStopped)); + debuggerMenu->addAction("Force Update Memory Cache", "Misc"); + #ifdef WIN32 UIAction::registerAction("Reinstall DbgEng Redistributable"); context->globalActions()->bindAction("Reinstall DbgEng Redistributable", UIAction([=](const UIActionContext& ctxt) {