diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 06c6240dd4..25c328634d 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -20,6 +20,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui inspector_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui model ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui teams_window ] ; @@ -54,6 +55,7 @@ Application Debugger : BreakpointManager.cpp Debugger.cpp Jobs.cpp + TeamMemoryBlockManager.cpp TeamDebugger.cpp ThreadHandler.cpp Worker.cpp @@ -127,6 +129,7 @@ Application Debugger : UserBreakpoint.cpp Team.cpp TeamMemory.cpp + TeamMemoryBlock.cpp Thread.cpp ThreadInfo.cpp Type.cpp @@ -167,6 +170,10 @@ Application Debugger : VariablesViewState.cpp VariablesViewStateHistory.cpp + # user_interface/gui/inspector_window + InspectorWindow.cpp + MemoryView.cpp + # user_interface/gui/teams_window TeamsWindow.cpp TeamsListView.cpp @@ -253,7 +260,7 @@ Application Debugger : libshared.a $(TARGET_LIBSTDC++) - be tracker libdebug.so + be tracker libdebug.so libshared.a libexpression_parser.a libmapm.a : Debugger.rdef ; diff --git a/src/apps/debugger/Jobs.cpp b/src/apps/debugger/Jobs.cpp index 0e04652307..9645be161f 100644 --- a/src/apps/debugger/Jobs.cpp +++ b/src/apps/debugger/Jobs.cpp @@ -24,6 +24,8 @@ #include "StackFrameValues.h" #include "StackTrace.h" #include "Team.h" +#include "TeamMemory.h" +#include "TeamMemoryBlock.h" #include "TeamDebugInfo.h" #include "Thread.h" #include "Tracing.h" @@ -633,3 +635,41 @@ ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode) return nodeResolutionState != VALUE_NODE_UNRESOLVED ? nodeResolutionState : B_ERROR; } + + +RetrieveMemoryBlockJob::RetrieveMemoryBlockJob(TeamMemory* teamMemory, + TeamMemoryBlock* memoryBlock) + : + fKey(memoryBlock, JOB_TYPE_GET_MEMORY_BLOCK), + fTeamMemory(teamMemory), + fMemoryBlock(memoryBlock) +{ + fMemoryBlock->AcquireReference(); +} + + +RetrieveMemoryBlockJob::~RetrieveMemoryBlockJob() +{ + fMemoryBlock->ReleaseReference(); +} + + +const JobKey& +RetrieveMemoryBlockJob::Key() const +{ + return fKey; +} + + +status_t +RetrieveMemoryBlockJob::Do() +{ + + ssize_t result = fTeamMemory->ReadMemory(fMemoryBlock->BaseAddress(), + fMemoryBlock->Data(), fMemoryBlock->Size()); + if (result < 0) + return result; + + fMemoryBlock->MarkValid(); + return B_OK; +} diff --git a/src/apps/debugger/Jobs.h b/src/apps/debugger/Jobs.h index 76cc2862c8..4c0a8b0309 100644 --- a/src/apps/debugger/Jobs.h +++ b/src/apps/debugger/Jobs.h @@ -1,5 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2011, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef JOBS_H @@ -7,6 +8,7 @@ #include "ImageDebugInfoProvider.h" +#include "Types.h" #include "Worker.h" @@ -20,6 +22,8 @@ class Image; class StackFrame; class StackFrameValues; class Team; +class TeamMemory; +class TeamMemoryBlock; class Thread; class Type; class TypeComponentPath; @@ -38,7 +42,8 @@ enum { JOB_TYPE_LOAD_IMAGE_DEBUG_INFO, JOB_TYPE_LOAD_SOURCE_CODE, JOB_TYPE_GET_STACK_FRAME_VALUE, - JOB_TYPE_RESOLVE_VALUE_NODE_VALUE + JOB_TYPE_RESOLVE_VALUE_NODE_VALUE, + JOB_TYPE_GET_MEMORY_BLOCK }; @@ -177,4 +182,21 @@ private: }; +class RetrieveMemoryBlockJob : public Job { +public: + RetrieveMemoryBlockJob( + TeamMemory* teamMemory, + TeamMemoryBlock* memoryBlock); + virtual ~RetrieveMemoryBlockJob(); + + virtual const JobKey& Key() const; + virtual status_t Do(); + +private: + SimpleJobKey fKey; + TeamMemory* fTeamMemory; + TeamMemoryBlock* fMemoryBlock; +}; + + #endif // JOBS_H diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 8b6915201f..176ee98d20 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -44,7 +44,9 @@ enum { MSG_TEAM_DEBUGGER_QUIT = 'dbqt', MSG_SHOW_TEAMS_WINDOW = 'stsw', MSG_TEAMS_WINDOW_CLOSED = 'tswc', - MSG_DEBUG_THIS_TEAM = 'dbtt' + MSG_DEBUG_THIS_TEAM = 'dbtt', + MSG_INSPECTOR_WINDOW_CLOSED = 'irwc', + MSG_INSPECT_ADDRESS = 'isad' }; diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index da3fca4bd6..3b5fdad37d 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -14,6 +14,7 @@ #include +#include #include #include "debug_utils.h" @@ -37,6 +38,8 @@ #include "Statement.h" #include "SymbolInfo.h" #include "TeamDebugInfo.h" +#include "TeamMemoryBlock.h" +#include "TeamMemoryBlockManager.h" #include "TeamSettings.h" #include "Tracing.h" #include "ValueNode.h" @@ -446,6 +449,26 @@ TeamDebugger::MessageReceived(BMessage* message) break; } + case MSG_INSPECT_ADDRESS: + { + TeamMemoryBlock::Listener* listener; + if (message->FindPointer("listener", + reinterpret_cast(&listener)) != B_OK) { + break; + } + + const char* addressExpression; + target_addr_t address; + if (message->FindString("addressExpression", + &addressExpression) == B_OK) { + _HandleInspectAddress(addressExpression, listener); + } else if (message->FindUInt64("address", + &address) == B_OK) { + _HandleInspectAddress(address, listener); + } + break; + } + case MSG_THREAD_STATE_CHANGED: { int32 threadID; @@ -661,6 +684,28 @@ TeamDebugger::ClearBreakpointRequested(UserBreakpoint* breakpoint) } +void +TeamDebugger::InspectRequested(const char* addressExpression, + TeamMemoryBlock::Listener *listener) +{ + BMessage message(MSG_INSPECT_ADDRESS); + message.AddString("addressExpression", addressExpression); + message.AddPointer("listener", listener); + PostMessage(&message); +} + + +void +TeamDebugger::InspectRequested(target_addr_t address, + TeamMemoryBlock::Listener *listener) +{ + BMessage message(MSG_INSPECT_ADDRESS); + message.AddUInt64("address", address); + message.AddPointer("listener", listener); + PostMessage(&message); +} + + bool TeamDebugger::UserInterfaceQuitRequested() { @@ -1243,6 +1288,68 @@ TeamDebugger::_HandleClearUserBreakpoint(UserBreakpoint* breakpoint) } +void +TeamDebugger::_HandleInspectAddress(const char* addressExpression, + TeamMemoryBlock::Listener* listener) +{ + TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(%s, %p)\n", + addressExpression, listener); + + ExpressionParser parser; + parser.SetSupportHexInput(true); + target_addr_t address = 0LL; + try { + address = parser.EvaluateToInt64(addressExpression); + } catch(ParseException parseError) { + _NotifyUser("Inspect Address", "Failed to parse address: %s", + parseError.message.String()); + return; + } catch(...) { + _NotifyUser("Inspect Address", "Unknown error while parsing address"); + return; + } + + _HandleInspectAddress(address, listener); +} + + +void +TeamDebugger::_HandleInspectAddress(target_addr_t address, + TeamMemoryBlock::Listener* listener) +{ + TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(" B_PRIx64 ", %p)\n", + addressExpression, listener); + + TeamMemoryBlock* memoryBlock = fMemoryBlockManager + ->GetMemoryBlock(address); + + if (memoryBlock == NULL) { + _NotifyUser("Inspect Address", "Failed to allocate memory block"); + return; + } + + if (!memoryBlock->HasListener(listener)) + memoryBlock->AddListener(listener); + + if (!memoryBlock->IsValid()) { + AutoLocker< ::Team> teamLocker(fTeam); + + TeamMemory* memory = fTeam->GetTeamMemory(); + // schedule the job + status_t result; + if ((result = fWorker->ScheduleJob( + new(std::nothrow) RetrieveMemoryBlockJob(memory, memoryBlock), + this)) != B_OK) { + memoryBlock->ReleaseReference(); + _NotifyUser("Inspect Address", "Failed to retrieve memory data: %s", + strerror(result)); + } + } else + memoryBlock->NotifyDataRetrieved(); + +} + + ThreadHandler* TeamDebugger::_GetThreadHandler(thread_id threadID) { diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/TeamDebugger.h index ab616c6b7c..6b19e06bd9 100644 --- a/src/apps/debugger/TeamDebugger.h +++ b/src/apps/debugger/TeamDebugger.h @@ -22,6 +22,7 @@ class DebuggerInterface; class FileManager; class SettingsManager; class TeamDebugInfo; +class TeamMemoryBlockManager; class TeamDebugger : public BLooper, private UserInterfaceListener, @@ -65,6 +66,10 @@ private: virtual void ClearBreakpointRequested(target_addr_t address); virtual void ClearBreakpointRequested( UserBreakpoint* breakpoint); + virtual void InspectRequested(target_addr_t address, + TeamMemoryBlock::Listener* listener); + virtual void InspectRequested(const char* addressExpression, + TeamMemoryBlock::Listener* listener); virtual bool UserInterfaceQuitRequested(); // JobListener @@ -118,6 +123,13 @@ private: void _HandleClearUserBreakpoint( UserBreakpoint* breakpoint); + void _HandleInspectAddress( + target_addr_t address, + TeamMemoryBlock::Listener* listener); + void _HandleInspectAddress( + const char* addressExpression, + TeamMemoryBlock::Listener* listener); + ThreadHandler* _GetThreadHandler(thread_id threadID); status_t _AddImage(const ImageInfo& imageInfo, @@ -142,6 +154,8 @@ private: FileManager* fFileManager; Worker* fWorker; BreakpointManager* fBreakpointManager; + TeamMemoryBlockManager* + fMemoryBlockManager; thread_id fDebugEventListener; UserInterface* fUserInterface; volatile bool fTerminating; diff --git a/src/apps/debugger/TeamMemoryBlockManager.cpp b/src/apps/debugger/TeamMemoryBlockManager.cpp new file mode 100644 index 0000000000..12ed410aa6 --- /dev/null +++ b/src/apps/debugger/TeamMemoryBlockManager.cpp @@ -0,0 +1,208 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "TeamMemoryBlockManager.h" + +#include + +#include +#include + +#include "TeamMemoryBlock.h" + + +struct TeamMemoryBlockManager::Key { + target_addr_t address; + + Key(target_addr_t address) + : + address(address) + { + } + + uint32 HashValue() const + { + return (uint32)address; + } + + bool operator==(const Key& other) const + { + return address == other.address; + } +}; + + +struct TeamMemoryBlockManager::MemoryBlockEntry : Key { + TeamMemoryBlock* block; + MemoryBlockEntry* next; + + MemoryBlockEntry(TeamMemoryBlock* block) + : + Key(block->BaseAddress()), + block(block) + { + block->AcquireReference(); + } + + ~MemoryBlockEntry() + { + block->ReleaseReference(); + } +}; + + +struct TeamMemoryBlockManager::MemoryBlockHashDefinition { + typedef Key KeyType; + typedef MemoryBlockEntry ValueType; + + size_t HashKey(const Key& key) const + { + return key.HashValue(); + } + + size_t Hash(const MemoryBlockEntry* value) const + { + return value->HashValue(); + } + + bool Compare(const Key& key, const MemoryBlockEntry* value) const + { + return key == *value; + } + + MemoryBlockEntry*& GetLink(MemoryBlockEntry* value) const + { + return value->next; + } +}; + + +TeamMemoryBlockManager::TeamMemoryBlockManager() + : + fActiveBlocks(NULL), + fDeadBlocks(NULL) +{ +} + + +TeamMemoryBlockManager::~TeamMemoryBlockManager() +{ + _Cleanup(); +} + + +status_t +TeamMemoryBlockManager::Init() +{ + status_t result = fLock.InitCheck(); + if (result != B_OK) + return result; + + fActiveBlocks = new(std::nothrow) MemoryBlockTable(); + if (fActiveBlocks == NULL) + return B_NO_MEMORY; + ObjectDeleter activeDeleter(fActiveBlocks); + result = fActiveBlocks->Init(); + if (result != B_OK) + return result; + + fDeadBlocks = new(std::nothrow) MemoryBlockTable(); + if (fDeadBlocks == NULL) + return B_NO_MEMORY; + ObjectDeleter deadDeleter(fDeadBlocks); + result = fDeadBlocks->Init(); + if (result != B_OK) + return result; + + activeDeleter.Detach(); + deadDeleter.Detach(); + + return B_OK; +} + + +TeamMemoryBlock* +TeamMemoryBlockManager::GetMemoryBlock(target_addr_t address) +{ + AutoLocker lock(fLock); + + address &= ~B_PAGE_SIZE - 1; + MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); + if (entry == NULL) { + TeamMemoryBlock* block = new(std::nothrow) TeamMemoryBlock(address, + this); + if (block == NULL) + return NULL; + + entry = new(std::nothrow) MemoryBlockEntry(block); + if (entry == NULL) { + delete block; + return NULL; + } + + fActiveBlocks->Insert(entry); + } + + int32 refCount = entry->block->AcquireReference(); + if (refCount == 0) { + // this block already had its last reference released, + // move it to the dead list and retrieve a new one instead. + _MarkDeadBlock(address); + return GetMemoryBlock(address); + } + + return entry->block; +} + + +void +TeamMemoryBlockManager::_Cleanup() +{ + if (fActiveBlocks != NULL) { + MemoryBlockEntry* entry = fActiveBlocks->Clear(true); + + while (entry != NULL) { + MemoryBlockEntry* next = entry->next; + delete entry; + entry = next; + } + + delete fActiveBlocks; + fActiveBlocks = NULL; + } +} + + +void +TeamMemoryBlockManager::_MarkDeadBlock(target_addr_t address) +{ + AutoLocker lock(fLock); + MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); + if (entry != NULL) { + fActiveBlocks->Remove(entry); + fDeadBlocks->Insert(entry); + } +} + + +void +TeamMemoryBlockManager::_RemoveBlock(target_addr_t address) +{ + AutoLocker lock(fLock); + MemoryBlockEntry* entry = fActiveBlocks->Lookup(address); + if (entry != NULL) { + fActiveBlocks->Remove(entry); + delete entry; + return; + } + + entry = fDeadBlocks->Lookup(address); + if (entry != NULL) { + fDeadBlocks->Remove(entry); + delete entry; + } +} + diff --git a/src/apps/debugger/TeamMemoryBlockManager.h b/src/apps/debugger/TeamMemoryBlockManager.h new file mode 100644 index 0000000000..c9ecb521e4 --- /dev/null +++ b/src/apps/debugger/TeamMemoryBlockManager.h @@ -0,0 +1,50 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef TEAM_MEMORY_BLOCK_MANAGER_H +#define TEAM_MEMORY_BLOCK_MANAGER_H + + +#include +#include +#include + +#include "Types.h" + +struct MemoryBlockHashDefinition; +class TeamMemoryBlock; + + +class TeamMemoryBlockManager +{ +public: + TeamMemoryBlockManager(); + ~TeamMemoryBlockManager(); + + status_t Init(); + + TeamMemoryBlock* GetMemoryBlock(target_addr_t address); + +private: + struct Key; + struct MemoryBlockEntry; + struct MemoryBlockHashDefinition; + typedef BOpenHashTable MemoryBlockTable; + +private: + void _Cleanup(); + void _MarkDeadBlock(target_addr_t address); + void _RemoveBlock(target_addr_t address); + +private: + friend class TeamMemoryBlock; + +private: + BLocker fLock; + MemoryBlockTable* fActiveBlocks; + MemoryBlockTable* fDeadBlocks; +}; + + +#endif // TEAM_MEMORY_BLOCK_MANAGER_H diff --git a/src/apps/debugger/model/TeamMemoryBlock.cpp b/src/apps/debugger/model/TeamMemoryBlock.cpp new file mode 100644 index 0000000000..b20ec90f8c --- /dev/null +++ b/src/apps/debugger/model/TeamMemoryBlock.cpp @@ -0,0 +1,108 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "TeamMemoryBlock.h" + + +#include + +#include "TeamMemoryBlockManager.h" + + +// #pragma mark - TeamMemoryBlock + + +TeamMemoryBlock::TeamMemoryBlock(target_addr_t baseAddress, + TeamMemoryBlockManager* manager) + : + fValid(false), + fBaseAddress(baseAddress), + fBlockManager(manager) +{ +} + + +TeamMemoryBlock::~TeamMemoryBlock() +{ +} + + +void +TeamMemoryBlock::AddListener(Listener* listener) +{ + AutoLocker lock(fLock); + fListeners.Add(listener); +} + + +bool +TeamMemoryBlock::HasListener(Listener* listener) +{ + AutoLocker lock(fLock); + ListenerList::Iterator iterator = fListeners.GetIterator(); + while (iterator.HasNext()) { + if (iterator.Next() == listener) + return true; + } + + return false; +} + + +void +TeamMemoryBlock::RemoveListener(Listener* listener) +{ + AutoLocker lock(fLock); + fListeners.Remove(listener); +} + + +void +TeamMemoryBlock::MarkValid() +{ + fValid = true; + NotifyDataRetrieved(); +} + + +void +TeamMemoryBlock::Invalidate() +{ + fValid = false; +} + + +void +TeamMemoryBlock::NotifyDataRetrieved() +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->MemoryBlockRetrieved(this); + } +} + + +void +TeamMemoryBlock::LastReferenceReleased() +{ + fBlockManager->_RemoveBlock(fBaseAddress); + + BReferenceable::LastReferenceReleased(); +} + + +// #pragma mark - TeamMemoryBlock + + +TeamMemoryBlock::Listener::~Listener() +{ +} + + +void +TeamMemoryBlock::Listener::MemoryBlockRetrieved(TeamMemoryBlock* block) +{ +} diff --git a/src/apps/debugger/model/TeamMemoryBlock.h b/src/apps/debugger/model/TeamMemoryBlock.h new file mode 100644 index 0000000000..ba82d4a718 --- /dev/null +++ b/src/apps/debugger/model/TeamMemoryBlock.h @@ -0,0 +1,70 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef TEAM_MEMORY_BLOCK_H +#define TEAM_MEMORY_BLOCK_H + + +#include + +#include +#include +#include + +#include "Types.h" + + +class TeamMemoryBlockManager; + + +class TeamMemoryBlock : public BReferenceable { +public: + class Listener; + +public: + TeamMemoryBlock(target_addr_t baseAddress, + TeamMemoryBlockManager* manager); + ~TeamMemoryBlock(); + + void AddListener(Listener* listener); + bool HasListener(Listener* listener); + void RemoveListener(Listener* listener); + + bool IsValid() const { return fValid; }; + void MarkValid(); + void Invalidate(); + + target_addr_t BaseAddress() const { return fBaseAddress; }; + uint8* Data() { return fData; }; + size_t Size() const { return sizeof(fData); }; + + void NotifyDataRetrieved(); + +protected: + virtual void LastReferenceReleased(); + +private: + typedef DoublyLinkedList ListenerList; + +private: + bool fValid; + target_addr_t fBaseAddress; + uint8 fData[B_PAGE_SIZE]; + ListenerList fListeners; + TeamMemoryBlockManager* + fBlockManager; + BLocker fLock; +}; + + +class TeamMemoryBlock::Listener : public DoublyLinkedListLinkImpl { +public: + virtual ~Listener(); + + virtual void MemoryBlockRetrieved(TeamMemoryBlock* block); +}; + + +#endif // TEAM_MEMORY_BLOCK_H + diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 1df091a544..ced05cce32 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -10,6 +10,7 @@ #include +#include "TeamMemoryBlock.h" #include "Types.h" @@ -82,6 +83,13 @@ public: UserBreakpoint* breakpoint) = 0; // TODO: Consolidate those! + virtual void InspectRequested( + target_addr_t address, + TeamMemoryBlock::Listener* listener) = 0; + virtual void InspectRequested( + const char* addressExpression, + TeamMemoryBlock::Listener* listener) = 0; + virtual bool UserInterfaceQuitRequested() = 0; }; diff --git a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp new file mode 100644 index 0000000000..292777acd3 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp @@ -0,0 +1,92 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "InspectorWindow.h" + +#include +#include +#include +#include +#include + +#include + +#include "MemoryView.h" +#include "MessageCodes.h" +#include "UserInterface.h" + + +InspectorWindow::InspectorWindow(UserInterfaceListener* listener) + : + BWindow(BRect(100, 100, 500, 250), "Inspector", B_DOCUMENT_WINDOW, + B_ASYNCHRONOUS_CONTROLS), + fListener(listener) +{ +} + + +InspectorWindow::~InspectorWindow() +{ +} + + +/* static */ InspectorWindow* +InspectorWindow::Create(UserInterfaceListener* listener) +{ + InspectorWindow* self = new InspectorWindow(listener); + + try { + self->_Init(); + } catch (...) { + delete self; + throw; + } + + return self; +} + + +void +InspectorWindow::_Init() +{ + BLayoutBuilder::Group<>(this, B_VERTICAL) + .Add(fAddressInput = new BTextControl("addrInput", + "Target Address:", "", + new BMessage(MSG_INSPECT_ADDRESS))) + .Add(fMemoryView = new MemoryView(NULL, NULL)) + .End(); + + fAddressInput->SetTarget(this); +} + + + +void +InspectorWindow::MessageReceived(BMessage* msg) +{ + switch (msg->what) { + case MSG_INSPECT_ADDRESS: + { + const char* addressExpression = fAddressInput->Text(); + fListener->InspectRequested(addressExpression, this); + break; + } + } +} + + +bool +InspectorWindow::QuitRequested() +{ + be_app_messenger.SendMessage(MSG_INSPECTOR_WINDOW_CLOSED); + return true; +} + + +void +InspectorWindow::MemoryBlockRetrieved(TeamMemoryBlock* block) +{ + // TODO: implement +} diff --git a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h new file mode 100644 index 0000000000..d4693b8011 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h @@ -0,0 +1,45 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef INSPECTOR_WINDOW_H +#define INSPECTOR_WINDOW_H + + +#include + +#include "TeamMemoryBlock.h" +#include "Types.h" + + +class BButton; +class BTextControl; +class MemoryView; +class UserInterfaceListener; + + +class InspectorWindow : public BWindow, + public TeamMemoryBlock::Listener { +public: + InspectorWindow( + UserInterfaceListener* listener); + virtual ~InspectorWindow(); + + static InspectorWindow* Create(UserInterfaceListener* listener); + // throws + + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); + + virtual void MemoryBlockRetrieved(TeamMemoryBlock* block); + +private: + void _Init(); + +private: + UserInterfaceListener* fListener; + BTextControl* fAddressInput; + MemoryView* fMemoryView; +}; + +#endif // INSPECTOR_WINDOW_H diff --git a/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp new file mode 100644 index 0000000000..8733732580 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "MemoryView.h" + + +MemoryView::MemoryView(Team* team, Listener* listener) + : + BView("memoryView", B_WILL_DRAW | B_SUBPIXEL_PRECISE), + fTeam(team), + fListener(listener) +{ +} + + +MemoryView::~MemoryView() +{ + UnsetListener(); +} + + +/*static */ MemoryView* +MemoryView::Create(Team* team, Listener* listener) +{ + MemoryView* self = new MemoryView(team, listener); + + try { + self->_Init(); + } catch(...) { + delete self; + throw; + } + + return self; +} + + +void +MemoryView::UnsetListener() +{ + fListener = NULL; +} + + +void +MemoryView::SetTargetAddress(target_addr_t address) +{ + fTargetAddress = address; + Invalidate(); +} + + +void +MemoryView::TargetAddressChanged(target_addr_t address) +{ + SetTargetAddress(address); +} + + +void +MemoryView::TargetedByScrollView(BScrollView* scrollView) +{ + BView::TargetedByScrollView(scrollView); +} + + +void +MemoryView::Draw(BRect rect) +{ + BView::Draw(rect); +} + + +void +MemoryView::MessageReceived(BMessage* message) +{ + switch(message->what) { + default: + BView::MessageReceived(message); + break; + } +} + +void +MemoryView::_Init() +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); +} + + +MemoryView::Listener::~Listener() +{ +} diff --git a/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.h b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.h new file mode 100644 index 0000000000..0fb150dd54 --- /dev/null +++ b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.h @@ -0,0 +1,57 @@ +/* + * Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef MEMORY_VIEW_H +#define MEMORY_VIEW_H + + +#include + +#include "Team.h" + + +class MemoryView : public BView { +public: + class Listener; + +public: + MemoryView( + Team* team, Listener* listener); + virtual ~MemoryView(); + + static MemoryView* Create(Team* team, Listener* listener); + // throws + + void UnsetListener(); + + void SetTargetAddress(target_addr_t address); + + void TargetAddressChanged(target_addr_t address); + + virtual void TargetedByScrollView(BScrollView* scrollView); + + virtual void Draw(BRect rect); + virtual void MessageReceived(BMessage* message); + +private: + void _Init(); + +private: + Team* fTeam; + target_addr_t fTargetAddress; + Listener* fListener; +}; + + +class MemoryView::Listener { +public: + virtual ~Listener(); + + virtual void SetTargetAddressRequested( + target_addr_t address) = 0; +}; + + +#endif // MEMORY_VIEW_H