From 03796a0cefd2568ee7c7eb3f0a0164f7f48cc9b1 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 16 May 2015 17:35:58 -0400 Subject: [PATCH] Debugger: Add Inspector UI controls for edit mode. InspectorWindow: - Add buttons to control edit mode, and helper functions to maintain their state. - Implement listener hook for memory change events, to track when requested memory writes are completed, and update the view accordingly. Together with the previous batch of commits, this implements the first part of #9708. --- .../gui/inspector_window/InspectorWindow.cpp | 114 +++++++++++++++++- .../gui/inspector_window/InspectorWindow.h | 12 ++ 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp index 51bcae9fad..68efbeef8f 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp @@ -30,7 +30,10 @@ enum { MSG_NAVIGATE_PREVIOUS_BLOCK = 'npbl', MSG_NAVIGATE_NEXT_BLOCK = 'npnl', - MSG_MEMORY_BLOCK_RETRIEVED = 'mbre' + MSG_MEMORY_BLOCK_RETRIEVED = 'mbre', + MSG_EDIT_CURRENT_BLOCK = 'mecb', + MSG_COMMIT_MODIFIED_BLOCK = 'mcmb', + MSG_REVERT_MODIFIED_BLOCK = 'mrmb' }; @@ -169,6 +172,12 @@ InspectorWindow::_Init() .Add(fWritableBlockIndicator = new BStringView("writableIndicator", _GetCurrentWritableIndicator())) .AddGlue() + .Add(fEditBlockButton = new BButton("editBlock", "Edit", + new BMessage(MSG_EDIT_CURRENT_BLOCK))) + .Add(fCommitBlockButton = new BButton("commitBlock", "Commit", + new BMessage(MSG_COMMIT_MODIFIED_BLOCK))) + .Add(fRevertBlockButton = new BButton("revertBlock", "Revert", + new BMessage(MSG_REVERT_MODIFIED_BLOCK))) .End() .End(); @@ -187,6 +196,14 @@ InspectorWindow::_Init() fPreviousBlockButton->SetEnabled(false); fNextBlockButton->SetEnabled(false); + fEditBlockButton->SetTarget(this); + fCommitBlockButton->SetTarget(this); + fRevertBlockButton->SetTarget(this); + + fEditBlockButton->SetEnabled(false); + fCommitBlockButton->Hide(); + fRevertBlockButton->Hide(); + hexMenu->SetLabelFromMarked(true); hexMenu->SetTargetForItems(fMemoryView); endianMenu->SetLabelFromMarked(true); @@ -325,6 +342,43 @@ InspectorWindow::MessageReceived(BMessage* message) } break; } + case MSG_EDIT_CURRENT_BLOCK: + { + _SetEditMode(true); + break; + } + case MSG_MEMORY_DATA_CHANGED: + { + if (fCurrentBlock == NULL) + break; + + target_addr_t address; + if (message->FindUInt64("address", &address) == B_OK + && address >= fCurrentBlock->BaseAddress() + && address < fCurrentBlock->BaseAddress() + + fCurrentBlock->Size()) { + fCurrentBlock->Invalidate(); + _SetEditMode(false); + fListener->InspectRequested(address, this); + } + break; + } + case MSG_COMMIT_MODIFIED_BLOCK: + { + // TODO: this could conceivably be extended to detect the + // individual modified regions and only write those back. + // That would require potentially submitting multiple separate + // write requests, and thus require tracking all the writes being + // waited upon for completion. + fListener->MemoryWriteRequested(fCurrentBlock->BaseAddress(), + fMemoryView->GetEditedData(), fCurrentBlock->Size()); + break; + } + case MSG_REVERT_MODIFIED_BLOCK: + { + _SetEditMode(false); + break; + } default: { BWindow::MessageReceived(message); @@ -357,6 +411,17 @@ InspectorWindow::ThreadStateChanged(const Team::ThreadEvent& event) } +void +InspectorWindow::MemoryChanged(const Team::MemoryChangedEvent& event) +{ + BMessage message(MSG_MEMORY_DATA_CHANGED); + message.AddUInt64("address", event.GetTargetAddress()); + message.AddUInt64("size", event.GetSize()); + + PostMessage(&message); +} + + void InspectorWindow::MemoryBlockRetrieved(TeamMemoryBlock* block) { @@ -563,6 +628,53 @@ InspectorWindow::_SetCurrentBlock(TeamMemoryBlock* block) fCurrentBlock = block; fMemoryView->SetTargetAddress(fCurrentBlock, fCurrentAddress); + _UpdateWritableOptions(); +} + + +bool +InspectorWindow::_GetWritableState() const +{ + return fCurrentBlock != NULL ? fCurrentBlock->IsWritable() : false; +} + + +void +InspectorWindow::_SetEditMode(bool enabled) +{ + if (enabled == fMemoryView->GetEditMode()) + return; + + status_t error = fMemoryView->SetEditMode(enabled); + if (error != B_OK) + return; + + if (enabled) { + fEditBlockButton->Hide(); + fCommitBlockButton->Show(); + fRevertBlockButton->Show(); + } else { + fEditBlockButton->Show(); + fCommitBlockButton->Hide(); + fRevertBlockButton->Hide(); + } + + fHexMode->SetEnabled(!enabled); + fEndianMode->SetEnabled(!enabled); + + // while the block is being edited, disable block navigation controls. + fAddressInput->SetEnabled(!enabled); + fPreviousBlockButton->SetEnabled(!enabled); + fNextBlockButton->SetEnabled(!enabled); + + InvalidateLayout(); +} + + +void +InspectorWindow::_UpdateWritableOptions() +{ + fEditBlockButton->SetEnabled(_GetWritableState()); _UpdateWritableIndicator(); } diff --git a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h index 79265a1bef..0dafddbd70 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h @@ -46,6 +46,9 @@ public: virtual void ThreadStateChanged( const Team::ThreadEvent& event); + virtual void MemoryChanged( + const Team::MemoryChangedEvent& event); + // TeamMemoryBlock::Listener virtual void MemoryBlockRetrieved(TeamMemoryBlock* block); virtual void MemoryBlockRetrievalFailed( @@ -79,6 +82,12 @@ private: void _SetToAddress(target_addr_t address); void _SetCurrentBlock(TeamMemoryBlock* block); + void _SetEditMode(bool enabled); + + bool _GetWritableState() const; + + void _UpdateWritableOptions(); + void _UpdateWritableIndicator(); const char* _GetCurrentWritableIndicator() const; @@ -92,6 +101,9 @@ private: MemoryView* fMemoryView; BButton* fPreviousBlockButton; BButton* fNextBlockButton; + BButton* fEditBlockButton; + BButton* fCommitBlockButton; + BButton* fRevertBlockButton; TeamMemoryBlock* fCurrentBlock; target_addr_t fCurrentAddress; ::Team* fTeam;