Debugger: Add memory write support.
- Implements various support classes and functions that will be needed in order to marshal requests to write to memory in the target team.
This commit is contained in:
@@ -162,6 +162,7 @@ Application Debugger :
|
||||
LoadSourceCodeJob.cpp
|
||||
ResolveValueNodeJob.cpp
|
||||
RetrieveMemoryBlockJob.cpp
|
||||
WriteMemoryJob.cpp
|
||||
|
||||
# model
|
||||
AreaInfo.cpp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Copyright 2013, Rene Gollent, [email protected].
|
||||
* Copyright 2013-2015, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef MESSAGE_CODES_H
|
||||
@@ -41,6 +41,7 @@ enum {
|
||||
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
|
||||
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
||||
MSG_WATCHPOINT_CHANGED = 'wapc',
|
||||
MSG_MEMORY_DATA_CHANGED = 'mdac',
|
||||
MSG_DEBUGGER_EVENT = 'dbge',
|
||||
MSG_LOAD_SETTINGS = 'ldst',
|
||||
|
||||
@@ -77,6 +78,7 @@ enum {
|
||||
MSG_ADD_NEW_EXPRESSION = 'anex',
|
||||
MSG_EXPRESSION_PROMPT_WINDOW_CLOSED = 'epwc',
|
||||
MSG_INSPECT_ADDRESS = 'isad',
|
||||
MSG_WRITE_TARGET_MEMORY = 'wtam',
|
||||
MSG_EVALUATE_EXPRESSION = 'evex',
|
||||
MSG_EXPRESSION_EVALUATED = 'exev',
|
||||
MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||
* Copyright 2010-2014, Rene Gollent, [email protected].
|
||||
* Copyright 2010-2015, Rene Gollent, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -743,6 +743,24 @@ TeamDebugger::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_WRITE_TARGET_MEMORY:
|
||||
{
|
||||
target_addr_t address;
|
||||
if (message->FindUInt64("address", &address) != B_OK)
|
||||
break;
|
||||
|
||||
void* data;
|
||||
if (message->FindPointer("data", &data) != B_OK)
|
||||
break;
|
||||
|
||||
target_size_t size;
|
||||
if (message->FindUInt64("size", &size) != B_OK)
|
||||
break;
|
||||
|
||||
_HandleWriteMemory(address, data, size);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_EVALUATE_EXPRESSION:
|
||||
{
|
||||
SourceLanguage* language;
|
||||
@@ -1158,6 +1176,18 @@ TeamDebugger::InspectRequested(target_addr_t address,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::MemoryWriteRequested(target_addr_t address, const void* data,
|
||||
target_size_t size)
|
||||
{
|
||||
BMessage message(MSG_WRITE_TARGET_MEMORY);
|
||||
message.AddUInt64("address", address);
|
||||
message.AddPointer("data", data);
|
||||
message.AddUInt64("size", size);
|
||||
PostMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language,
|
||||
ExpressionInfo* info, StackFrame* frame, ::Thread* thread)
|
||||
@@ -2057,6 +2087,26 @@ TeamDebugger::_HandleInspectAddress(target_addr_t address,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::_HandleWriteMemory(target_addr_t address, void* data,
|
||||
target_size_t size)
|
||||
{
|
||||
TRACE_CONTROL("TeamDebugger::_HandleWriteTargetMemory(%" B_PRIx64 ", %p, "
|
||||
"%" B_PRIu64 ")\n", address, data, size);
|
||||
|
||||
AutoLocker< ::Team> teamLocker(fTeam);
|
||||
TeamMemory* memory = fTeam->GetTeamMemory();
|
||||
// schedule the job
|
||||
status_t result;
|
||||
if ((result = fWorker->ScheduleJob(
|
||||
new(std::nothrow) WriteMemoryJob(fTeam, memory, address, data, size),
|
||||
this)) != B_OK) {
|
||||
_NotifyUser("Write Memory", "Failed to write memory data: %s",
|
||||
strerror(result));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::_HandleEvaluateExpression(SourceLanguage* language,
|
||||
ExpressionInfo* info, StackFrame* frame, ::Thread* thread)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013-2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2013-2015, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TEAM_DEBUGGER_H
|
||||
@@ -107,6 +107,8 @@ private:
|
||||
|
||||
virtual void InspectRequested(target_addr_t address,
|
||||
TeamMemoryBlock::Listener* listener);
|
||||
virtual void MemoryWriteRequested(target_addr_t address,
|
||||
const void* data, target_size_t size);
|
||||
|
||||
virtual void ExpressionEvaluationRequested(
|
||||
SourceLanguage* language,
|
||||
@@ -194,6 +196,9 @@ private:
|
||||
void _HandleInspectAddress(
|
||||
target_addr_t address,
|
||||
TeamMemoryBlock::Listener* listener);
|
||||
void _HandleWriteMemory(
|
||||
target_addr_t address, void* data,
|
||||
target_size_t size);
|
||||
|
||||
void _HandleEvaluateExpression(
|
||||
SourceLanguage* language,
|
||||
|
||||
@@ -725,7 +725,7 @@ DebuggerInterface::WriteMemory(target_addr_t address, void* buffer,
|
||||
DebugContextGetter contextGetter(fDebugContextPool);
|
||||
|
||||
return debug_write_memory(contextGetter.Context(),
|
||||
(const void*)(addr_t)address, buffer, size);
|
||||
(const void*)address, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2011-2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2011-2015, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef JOBS_H
|
||||
@@ -52,6 +52,7 @@ enum {
|
||||
JOB_TYPE_GET_STACK_FRAME_VALUE,
|
||||
JOB_TYPE_RESOLVE_VALUE_NODE_VALUE,
|
||||
JOB_TYPE_GET_MEMORY_BLOCK,
|
||||
JOB_TYPE_WRITE_MEMORY,
|
||||
JOB_TYPE_EVALUATE_EXPRESSION
|
||||
};
|
||||
|
||||
@@ -233,6 +234,27 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class WriteMemoryJob : public Job {
|
||||
public:
|
||||
WriteMemoryJob(Team* team,
|
||||
TeamMemory* teamMemory,
|
||||
target_addr_t address, void* data,
|
||||
target_size_t size);
|
||||
virtual ~WriteMemoryJob();
|
||||
|
||||
virtual const JobKey& Key() const;
|
||||
virtual status_t Do();
|
||||
|
||||
private:
|
||||
SimpleJobKey fKey;
|
||||
Team* fTeam;
|
||||
TeamMemory* fTeamMemory;
|
||||
target_addr_t fTargetAddress;
|
||||
void* fData;
|
||||
target_size_t fSize;
|
||||
};
|
||||
|
||||
|
||||
class ExpressionEvaluationJob : public Job {
|
||||
public:
|
||||
ExpressionEvaluationJob(Team* team,
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2015, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "Jobs.h"
|
||||
|
||||
#include "Team.h"
|
||||
#include "TeamMemory.h"
|
||||
|
||||
|
||||
WriteMemoryJob::WriteMemoryJob(Team* team,
|
||||
TeamMemory* teamMemory, target_addr_t address, void* data,
|
||||
target_size_t size)
|
||||
:
|
||||
fKey(data, JOB_TYPE_WRITE_MEMORY),
|
||||
fTeam(team),
|
||||
fTeamMemory(teamMemory),
|
||||
fTargetAddress(address),
|
||||
fData(data),
|
||||
fSize(size)
|
||||
{
|
||||
fTeamMemory->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
WriteMemoryJob::~WriteMemoryJob()
|
||||
{
|
||||
fTeamMemory->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
const JobKey&
|
||||
WriteMemoryJob::Key() const
|
||||
{
|
||||
return fKey;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
WriteMemoryJob::Do()
|
||||
{
|
||||
ssize_t result = fTeamMemory->WriteMemory(fTargetAddress, fData, fSize);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
fTeam->NotifyMemoryChanged(fTargetAddress, fSize);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013-2014, Rene Gollent, rene@gollent.com.
|
||||
* Copyright 2013-2015, Rene Gollent, rene@gollent.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -732,6 +732,17 @@ Team::NotifyDebugReportChanged(const char* reportPath)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Team::NotifyMemoryChanged(target_addr_t address, target_size_t size)
|
||||
{
|
||||
for (ListenerList::Iterator it = fListeners.GetIterator();
|
||||
Listener* listener = it.Next();) {
|
||||
listener->MemoryChanged(MemoryChangedEvent(
|
||||
TEAM_EVENT_MEMORY_CHANGED, this, address, size));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Team::_NotifyThreadAdded(Thread* thread)
|
||||
{
|
||||
@@ -867,6 +878,19 @@ Team::DebugReportEvent::DebugReportEvent(uint32 type, Team* team,
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - MemoryChangedEvent
|
||||
|
||||
|
||||
Team::MemoryChangedEvent::MemoryChangedEvent(uint32 type, Team* team,
|
||||
target_addr_t address, target_size_t size)
|
||||
:
|
||||
Event(type, team),
|
||||
fTargetAddress(address),
|
||||
fSize(size)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - WatchpointEvent
|
||||
|
||||
|
||||
@@ -1013,3 +1037,9 @@ void
|
||||
Team::Listener::DebugReportChanged(const Team::DebugReportEvent& event)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Team::Listener::MemoryChanged(const Team::MemoryChangedEvent& event)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -48,7 +48,9 @@ enum {
|
||||
TEAM_EVENT_WATCHPOINT_REMOVED,
|
||||
TEAM_EVENT_WATCHPOINT_CHANGED,
|
||||
|
||||
TEAM_EVENT_DEBUG_REPORT_CHANGED
|
||||
TEAM_EVENT_DEBUG_REPORT_CHANGED,
|
||||
|
||||
TEAM_EVENT_MEMORY_CHANGED
|
||||
};
|
||||
|
||||
|
||||
@@ -75,6 +77,7 @@ public:
|
||||
class BreakpointEvent;
|
||||
class ConsoleOutputEvent;
|
||||
class DebugReportEvent;
|
||||
class MemoryChangedEvent;
|
||||
class ImageEvent;
|
||||
class ImageLoadEvent;
|
||||
class ImageLoadNameEvent;
|
||||
@@ -225,6 +228,10 @@ public:
|
||||
void NotifyDebugReportChanged(
|
||||
const char* reportPath);
|
||||
|
||||
// memory write related service methods
|
||||
void NotifyMemoryChanged(target_addr_t address,
|
||||
target_size_t size);
|
||||
|
||||
private:
|
||||
struct BreakpointByAddressPredicate;
|
||||
struct WatchpointByAddressPredicate;
|
||||
@@ -360,6 +367,21 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
class Team::MemoryChangedEvent : public Event {
|
||||
public:
|
||||
MemoryChangedEvent(uint32 type, Team* team,
|
||||
target_addr_t address, target_size_t size);
|
||||
|
||||
target_addr_t GetTargetAddress() const
|
||||
{ return fTargetAddress; }
|
||||
|
||||
target_size_t GetSize() const { return fSize; }
|
||||
protected:
|
||||
target_addr_t fTargetAddress;
|
||||
target_size_t fSize;
|
||||
};
|
||||
|
||||
|
||||
class Team::WatchpointEvent : public Event {
|
||||
public:
|
||||
WatchpointEvent(uint32 type, Team* team,
|
||||
@@ -430,6 +452,9 @@ public:
|
||||
|
||||
virtual void DebugReportChanged(
|
||||
const Team::DebugReportEvent& event);
|
||||
|
||||
virtual void MemoryChanged(
|
||||
const Team::MemoryChangedEvent& event);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -142,6 +142,10 @@ public:
|
||||
virtual void InspectRequested(
|
||||
target_addr_t address,
|
||||
TeamMemoryBlock::Listener* listener) = 0;
|
||||
virtual void MemoryWriteRequested(
|
||||
target_addr_t address,
|
||||
const void* data,
|
||||
target_size_t length) = 0;
|
||||
|
||||
virtual void ExpressionEvaluationRequested(
|
||||
SourceLanguage* language,
|
||||
|
||||
Reference in New Issue
Block a user