From 68e78ff84182e9cf9f05dc7ab334ab1cb4e15b80 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 23 May 2015 16:12:43 -0400 Subject: [PATCH] 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. --- src/apps/debugger/Jamfile | 1 + src/apps/debugger/MessageCodes.h | 4 +- .../debugger/controllers/TeamDebugger.cpp | 52 ++++++++++++++++++- src/apps/debugger/controllers/TeamDebugger.h | 7 ++- .../debugger_interface/DebuggerInterface.cpp | 2 +- src/apps/debugger/jobs/Jobs.h | 24 ++++++++- src/apps/debugger/jobs/WriteMemoryJob.cpp | 50 ++++++++++++++++++ src/apps/debugger/model/Team.cpp | 32 +++++++++++- src/apps/debugger/model/Team.h | 27 +++++++++- .../debugger/user_interface/UserInterface.h | 4 ++ 10 files changed, 196 insertions(+), 7 deletions(-) create mode 100644 src/apps/debugger/jobs/WriteMemoryJob.cpp diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index d344ee3875..ed1ea0ffdb 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -162,6 +162,7 @@ Application Debugger : LoadSourceCodeJob.cpp ResolveValueNodeJob.cpp RetrieveMemoryBlockJob.cpp + WriteMemoryJob.cpp # model AreaInfo.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 648e8548be..fdd0e6d5e7 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013-2015, Rene Gollent, rene@gollent.com. * 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', diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 622ed90a3c..9f109a27f7 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2010-2014, Rene Gollent, rene@gollent.com. + * Copyright 2010-2015, Rene Gollent, rene@gollent.com. * 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) diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index 9b26c36939..59d8e94d5e 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -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, diff --git a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp index 79eb6651d1..3f78fb4379 100644 --- a/src/apps/debugger/debugger_interface/DebuggerInterface.cpp +++ b/src/apps/debugger/debugger_interface/DebuggerInterface.cpp @@ -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); } diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 65a0ab0ef8..9841fd57b2 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -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, diff --git a/src/apps/debugger/jobs/WriteMemoryJob.cpp b/src/apps/debugger/jobs/WriteMemoryJob.cpp new file mode 100644 index 0000000000..116b4438b1 --- /dev/null +++ b/src/apps/debugger/jobs/WriteMemoryJob.cpp @@ -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; +} diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index ca90e71e3f..d915a829f7 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -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) +{ +} diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 685dad2415..243fec0533 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -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); }; diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 92f71917ce..d95a09f716 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -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,