* Introduce TeamMemoryBlock[Manager]. These provide an interface to raw memory
page data of the target team. * Jobs: Add RetrieveMemoryBlockJob which performs a background read of the target team's memory. Used by InspectRequested() to perform the actual work. * TeamDebugger: Added InspectRequested() hooks to allow clients to ask for a memory read to be performed. * Introduce InspectorWindow and MemoryView to form the basis of a memory inspector. As yet these are more or less stubs and not yet hooked in. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42080 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -20,6 +20,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
|
|||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
|
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 model ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui teams_window ] ;
|
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui teams_window ] ;
|
||||||
@@ -54,6 +55,7 @@ Application Debugger :
|
|||||||
BreakpointManager.cpp
|
BreakpointManager.cpp
|
||||||
Debugger.cpp
|
Debugger.cpp
|
||||||
Jobs.cpp
|
Jobs.cpp
|
||||||
|
TeamMemoryBlockManager.cpp
|
||||||
TeamDebugger.cpp
|
TeamDebugger.cpp
|
||||||
ThreadHandler.cpp
|
ThreadHandler.cpp
|
||||||
Worker.cpp
|
Worker.cpp
|
||||||
@@ -127,6 +129,7 @@ Application Debugger :
|
|||||||
UserBreakpoint.cpp
|
UserBreakpoint.cpp
|
||||||
Team.cpp
|
Team.cpp
|
||||||
TeamMemory.cpp
|
TeamMemory.cpp
|
||||||
|
TeamMemoryBlock.cpp
|
||||||
Thread.cpp
|
Thread.cpp
|
||||||
ThreadInfo.cpp
|
ThreadInfo.cpp
|
||||||
Type.cpp
|
Type.cpp
|
||||||
@@ -167,6 +170,10 @@ Application Debugger :
|
|||||||
VariablesViewState.cpp
|
VariablesViewState.cpp
|
||||||
VariablesViewStateHistory.cpp
|
VariablesViewStateHistory.cpp
|
||||||
|
|
||||||
|
# user_interface/gui/inspector_window
|
||||||
|
InspectorWindow.cpp
|
||||||
|
MemoryView.cpp
|
||||||
|
|
||||||
# user_interface/gui/teams_window
|
# user_interface/gui/teams_window
|
||||||
TeamsWindow.cpp
|
TeamsWindow.cpp
|
||||||
TeamsListView.cpp
|
TeamsListView.cpp
|
||||||
@@ -253,7 +260,7 @@ Application Debugger :
|
|||||||
libshared.a
|
libshared.a
|
||||||
|
|
||||||
$(TARGET_LIBSTDC++)
|
$(TARGET_LIBSTDC++)
|
||||||
be tracker libdebug.so
|
be tracker libdebug.so libshared.a libexpression_parser.a libmapm.a
|
||||||
|
|
||||||
: Debugger.rdef
|
: Debugger.rdef
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#include "StackFrameValues.h"
|
#include "StackFrameValues.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
|
#include "TeamMemory.h"
|
||||||
|
#include "TeamMemoryBlock.h"
|
||||||
#include "TeamDebugInfo.h"
|
#include "TeamDebugInfo.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "Tracing.h"
|
#include "Tracing.h"
|
||||||
@@ -633,3 +635,41 @@ ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
|
|||||||
return nodeResolutionState != VALUE_NODE_UNRESOLVED
|
return nodeResolutionState != VALUE_NODE_UNRESOLVED
|
||||||
? nodeResolutionState : B_ERROR;
|
? 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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Copyright 2011, Rene Gollent, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef JOBS_H
|
#ifndef JOBS_H
|
||||||
@@ -7,6 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "ImageDebugInfoProvider.h"
|
#include "ImageDebugInfoProvider.h"
|
||||||
|
#include "Types.h"
|
||||||
#include "Worker.h"
|
#include "Worker.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -20,6 +22,8 @@ class Image;
|
|||||||
class StackFrame;
|
class StackFrame;
|
||||||
class StackFrameValues;
|
class StackFrameValues;
|
||||||
class Team;
|
class Team;
|
||||||
|
class TeamMemory;
|
||||||
|
class TeamMemoryBlock;
|
||||||
class Thread;
|
class Thread;
|
||||||
class Type;
|
class Type;
|
||||||
class TypeComponentPath;
|
class TypeComponentPath;
|
||||||
@@ -38,7 +42,8 @@ enum {
|
|||||||
JOB_TYPE_LOAD_IMAGE_DEBUG_INFO,
|
JOB_TYPE_LOAD_IMAGE_DEBUG_INFO,
|
||||||
JOB_TYPE_LOAD_SOURCE_CODE,
|
JOB_TYPE_LOAD_SOURCE_CODE,
|
||||||
JOB_TYPE_GET_STACK_FRAME_VALUE,
|
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
|
#endif // JOBS_H
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ enum {
|
|||||||
MSG_TEAM_DEBUGGER_QUIT = 'dbqt',
|
MSG_TEAM_DEBUGGER_QUIT = 'dbqt',
|
||||||
MSG_SHOW_TEAMS_WINDOW = 'stsw',
|
MSG_SHOW_TEAMS_WINDOW = 'stsw',
|
||||||
MSG_TEAMS_WINDOW_CLOSED = 'tswc',
|
MSG_TEAMS_WINDOW_CLOSED = 'tswc',
|
||||||
MSG_DEBUG_THIS_TEAM = 'dbtt'
|
MSG_DEBUG_THIS_TEAM = 'dbtt',
|
||||||
|
MSG_INSPECTOR_WINDOW_CLOSED = 'irwc',
|
||||||
|
MSG_INSPECT_ADDRESS = 'isad'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
|
||||||
|
#include <ExpressionParser.h>
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
#include "debug_utils.h"
|
#include "debug_utils.h"
|
||||||
@@ -37,6 +38,8 @@
|
|||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
#include "SymbolInfo.h"
|
#include "SymbolInfo.h"
|
||||||
#include "TeamDebugInfo.h"
|
#include "TeamDebugInfo.h"
|
||||||
|
#include "TeamMemoryBlock.h"
|
||||||
|
#include "TeamMemoryBlockManager.h"
|
||||||
#include "TeamSettings.h"
|
#include "TeamSettings.h"
|
||||||
#include "Tracing.h"
|
#include "Tracing.h"
|
||||||
#include "ValueNode.h"
|
#include "ValueNode.h"
|
||||||
@@ -446,6 +449,26 @@ TeamDebugger::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MSG_INSPECT_ADDRESS:
|
||||||
|
{
|
||||||
|
TeamMemoryBlock::Listener* listener;
|
||||||
|
if (message->FindPointer("listener",
|
||||||
|
reinterpret_cast<void **>(&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:
|
case MSG_THREAD_STATE_CHANGED:
|
||||||
{
|
{
|
||||||
int32 threadID;
|
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
|
bool
|
||||||
TeamDebugger::UserInterfaceQuitRequested()
|
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*
|
ThreadHandler*
|
||||||
TeamDebugger::_GetThreadHandler(thread_id threadID)
|
TeamDebugger::_GetThreadHandler(thread_id threadID)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class DebuggerInterface;
|
|||||||
class FileManager;
|
class FileManager;
|
||||||
class SettingsManager;
|
class SettingsManager;
|
||||||
class TeamDebugInfo;
|
class TeamDebugInfo;
|
||||||
|
class TeamMemoryBlockManager;
|
||||||
|
|
||||||
|
|
||||||
class TeamDebugger : public BLooper, private UserInterfaceListener,
|
class TeamDebugger : public BLooper, private UserInterfaceListener,
|
||||||
@@ -65,6 +66,10 @@ private:
|
|||||||
virtual void ClearBreakpointRequested(target_addr_t address);
|
virtual void ClearBreakpointRequested(target_addr_t address);
|
||||||
virtual void ClearBreakpointRequested(
|
virtual void ClearBreakpointRequested(
|
||||||
UserBreakpoint* breakpoint);
|
UserBreakpoint* breakpoint);
|
||||||
|
virtual void InspectRequested(target_addr_t address,
|
||||||
|
TeamMemoryBlock::Listener* listener);
|
||||||
|
virtual void InspectRequested(const char* addressExpression,
|
||||||
|
TeamMemoryBlock::Listener* listener);
|
||||||
virtual bool UserInterfaceQuitRequested();
|
virtual bool UserInterfaceQuitRequested();
|
||||||
|
|
||||||
// JobListener
|
// JobListener
|
||||||
@@ -118,6 +123,13 @@ private:
|
|||||||
void _HandleClearUserBreakpoint(
|
void _HandleClearUserBreakpoint(
|
||||||
UserBreakpoint* breakpoint);
|
UserBreakpoint* breakpoint);
|
||||||
|
|
||||||
|
void _HandleInspectAddress(
|
||||||
|
target_addr_t address,
|
||||||
|
TeamMemoryBlock::Listener* listener);
|
||||||
|
void _HandleInspectAddress(
|
||||||
|
const char* addressExpression,
|
||||||
|
TeamMemoryBlock::Listener* listener);
|
||||||
|
|
||||||
ThreadHandler* _GetThreadHandler(thread_id threadID);
|
ThreadHandler* _GetThreadHandler(thread_id threadID);
|
||||||
|
|
||||||
status_t _AddImage(const ImageInfo& imageInfo,
|
status_t _AddImage(const ImageInfo& imageInfo,
|
||||||
@@ -142,6 +154,8 @@ private:
|
|||||||
FileManager* fFileManager;
|
FileManager* fFileManager;
|
||||||
Worker* fWorker;
|
Worker* fWorker;
|
||||||
BreakpointManager* fBreakpointManager;
|
BreakpointManager* fBreakpointManager;
|
||||||
|
TeamMemoryBlockManager*
|
||||||
|
fMemoryBlockManager;
|
||||||
thread_id fDebugEventListener;
|
thread_id fDebugEventListener;
|
||||||
UserInterface* fUserInterface;
|
UserInterface* fUserInterface;
|
||||||
volatile bool fTerminating;
|
volatile bool fTerminating;
|
||||||
|
|||||||
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Rene Gollent, rene@gollent.com.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "TeamMemoryBlockManager.h"
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#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<MemoryBlockTable> activeDeleter(fActiveBlocks);
|
||||||
|
result = fActiveBlocks->Init();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fDeadBlocks = new(std::nothrow) MemoryBlockTable();
|
||||||
|
if (fDeadBlocks == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<MemoryBlockTable> 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<BLocker> 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<BLocker> lock(fLock);
|
||||||
|
MemoryBlockEntry* entry = fActiveBlocks->Lookup(address);
|
||||||
|
if (entry != NULL) {
|
||||||
|
fActiveBlocks->Remove(entry);
|
||||||
|
fDeadBlocks->Insert(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamMemoryBlockManager::_RemoveBlock(target_addr_t address)
|
||||||
|
{
|
||||||
|
AutoLocker<BLocker> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 <Locker.h>
|
||||||
|
#include <Referenceable.h>
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#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<MemoryBlockHashDefinition> 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
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Rene Gollent, rene@gollent.com.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "TeamMemoryBlock.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
|
#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<BLocker> lock(fLock);
|
||||||
|
fListeners.Add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
TeamMemoryBlock::HasListener(Listener* listener)
|
||||||
|
{
|
||||||
|
AutoLocker<BLocker> lock(fLock);
|
||||||
|
ListenerList::Iterator iterator = fListeners.GetIterator();
|
||||||
|
while (iterator.HasNext()) {
|
||||||
|
if (iterator.Next() == listener)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TeamMemoryBlock::RemoveListener(Listener* listener)
|
||||||
|
{
|
||||||
|
AutoLocker<BLocker> 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -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 <OS.h>
|
||||||
|
|
||||||
|
#include <Locker.h>
|
||||||
|
#include <Referenceable.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
#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<Listener> ListenerList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool fValid;
|
||||||
|
target_addr_t fBaseAddress;
|
||||||
|
uint8 fData[B_PAGE_SIZE];
|
||||||
|
ListenerList fListeners;
|
||||||
|
TeamMemoryBlockManager*
|
||||||
|
fBlockManager;
|
||||||
|
BLocker fLock;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class TeamMemoryBlock::Listener : public DoublyLinkedListLinkImpl<Listener> {
|
||||||
|
public:
|
||||||
|
virtual ~Listener();
|
||||||
|
|
||||||
|
virtual void MemoryBlockRetrieved(TeamMemoryBlock* block);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TEAM_MEMORY_BLOCK_H
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include "TeamMemoryBlock.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -82,6 +83,13 @@ public:
|
|||||||
UserBreakpoint* breakpoint) = 0;
|
UserBreakpoint* breakpoint) = 0;
|
||||||
// TODO: Consolidate those!
|
// 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;
|
virtual bool UserInterfaceQuitRequested() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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 <Application.h>
|
||||||
|
#include <Button.h>
|
||||||
|
#include <LayoutBuilder.h>
|
||||||
|
#include <ScrollView.h>
|
||||||
|
#include <TextControl.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
}
|
||||||
@@ -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 <Window.h>
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -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 <View.h>
|
||||||
|
|
||||||
|
#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
|
||||||
Reference in New Issue
Block a user