diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 9b3c91a56b..43ad3133db 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -150,6 +150,7 @@ Application Debugger : ReturnValueID.cpp # jobs + ExpressionEvaluationJob.cpp GetCPUStateJob.cpp GetStackTraceJob.cpp GetThreadStateJob.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index ca68f7ac88..63dcd001e7 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -68,6 +68,7 @@ enum { MSG_SHOW_EXPRESSION_WINDOW = 'seww', MSG_EXPRESSION_WINDOW_CLOSED = 'ewwc', MSG_INSPECT_ADDRESS = 'isad', + MSG_EVALUATE_EXPRESSION = 'evex', MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp', MSG_TYPECAST_TO_ARRAY = 'stta', MSG_TYPECAST_NODE = 'tyno', diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index d551bd0859..5485e67ef6 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -40,6 +40,7 @@ #include "MessageCodes.h" #include "SettingsManager.h" #include "SourceCode.h" +#include "SourceLanguage.h" #include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfoLoadingState.h" #include "StackFrame.h" @@ -701,6 +702,40 @@ TeamDebugger::MessageReceived(BMessage* message) break; } + case MSG_EVALUATE_EXPRESSION: + { + SourceLanguage* language; + if (message->FindPointer("language", + reinterpret_cast(&language)) != B_OK) { + break; + } + + // ExpressionEvaluationRequested() acquires a reference + // on our behalf. + BReference reference(language, true); + + const char* expression; + if (message->FindString("expression", &expression) != B_OK) + break; + + type_code resultType; + if (message->FindInt32("type", + reinterpret_cast(&resultType)) != B_OK) { + break; + } + + StackFrame* frame; + if (message->FindPointer("frame", + reinterpret_cast(&frame)) != B_OK) { + // the stack frame isn't needed, unless variable + // evaluation is desired. + frame = NULL; + } + + _HandleEvaluateExpression(language, expression, resultType, frame); + break; + } + case MSG_GENERATE_DEBUG_REPORT: { fReportGenerator->PostMessage(message); @@ -1050,6 +1085,23 @@ TeamDebugger::InspectRequested(target_addr_t address, } +void +TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language, + const char* expression, type_code resultType, StackFrame* frame) +{ + BMessage message(MSG_EVALUATE_EXPRESSION); + message.AddPointer("language", language); + message.AddString("expression", expression); + message.AddInt32("type", resultType); + if (frame != NULL) + message.AddPointer("frame", frame); + + BReference reference(language); + if (PostMessage(&message) == B_OK) + reference.Detach(); +} + + void TeamDebugger::DebugReportRequested(entry_ref* targetPath) { @@ -1928,6 +1980,20 @@ TeamDebugger::_HandleInspectAddress(target_addr_t address, } +void +TeamDebugger::_HandleEvaluateExpression(SourceLanguage* language, + const char* expression, type_code resultType, StackFrame* frame) +{ + status_t result = fWorker->ScheduleJob( + new(std::nothrow) ExpressionEvaluationJob(fTeam, language, + expression, resultType, frame)); + if (result != B_OK) { + _NotifyUser("Evaluate Expression", "Failed to evaluate expression: %s", + strerror(result)); + } +} + + status_t TeamDebugger::_HandleSetArguments(int argc, const char* const* argv) { diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index d48c8487f6..4ef9cba66f 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -102,6 +102,12 @@ private: virtual void InspectRequested(target_addr_t address, TeamMemoryBlock::Listener* listener); + virtual void ExpressionEvaluationRequested( + SourceLanguage* language, + const char* expression, + type_code resultType, + StackFrame* frame = NULL); + virtual void DebugReportRequested(entry_ref* targetPath); virtual void TeamRestartRequested(); @@ -182,6 +188,13 @@ private: void _HandleInspectAddress( target_addr_t address, TeamMemoryBlock::Listener* listener); + + void _HandleEvaluateExpression( + SourceLanguage* language, + const char* expression, + type_code resultType, + StackFrame* frame); + status_t _HandleSetArguments(int argc, const char* const* argv); diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index 47ca84dc99..89bb18bfbb 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, Rene Gollent, rene@gollent.com. + * Copyright 2013-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -21,6 +21,7 @@ #include "Statement.h" #include "TeamDebugInfo.h" #include "Tracing.h" +#include "Value.h" #include "Watchpoint.h" @@ -731,6 +732,19 @@ Team::NotifyDebugReportChanged(const char* reportPath) } +void +Team::NotifyExpressionEvaluated(const char* expression, status_t result, + Value* value) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->ExpressionEvaluated(ExpressionEvaluationEvent( + TEAM_EVENT_EXPRESSION_EVALUATED, this, expression, result, + value)); + } +} + + void Team::_NotifyThreadAdded(Thread* thread) { @@ -890,6 +904,29 @@ Team::UserBreakpointEvent::UserBreakpointEvent(uint32 type, Team* team, } +// #pragma mark - ExpressionEvaluationEvent + + +Team::ExpressionEvaluationEvent::ExpressionEvaluationEvent(uint32 type, + Team* team, const char* expression, status_t result, Value* value) + : + Event(type, team), + fExpression(expression), + fEvaluationResult(result), + fValue(value) +{ + if (fValue != NULL) + fValue->AcquireReference(); +} + + +Team::ExpressionEvaluationEvent::~ExpressionEvaluationEvent() +{ + if (fValue != NULL) + fValue->ReleaseReference(); +} + + // #pragma mark - Listener @@ -1012,3 +1049,10 @@ void Team::Listener::DebugReportChanged(const Team::DebugReportEvent& event) { } + + +void +Team::Listener::ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& event) +{ +} diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 5428084796..dc3c49bb3e 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef TEAM_H @@ -48,8 +48,9 @@ enum { TEAM_EVENT_WATCHPOINT_REMOVED, TEAM_EVENT_WATCHPOINT_CHANGED, - TEAM_EVENT_DEBUG_REPORT_CHANGED + TEAM_EVENT_DEBUG_REPORT_CHANGED, + TEAM_EVENT_EXPRESSION_EVALUATED }; @@ -67,6 +68,7 @@ class TeamDebugInfo; class TeamMemory; class TeamTypeInformation; class UserBreakpoint; +class Value; class Team { @@ -75,6 +77,7 @@ public: class BreakpointEvent; class ConsoleOutputEvent; class DebugReportEvent; + class ExpressionEvaluationEvent; class ImageEvent; class ImageLoadEvent; class ImageLoadNameEvent; @@ -225,6 +228,11 @@ public: void NotifyDebugReportChanged( const char* reportPath); + // expression evaluation related service methods + void NotifyExpressionEvaluated( + const char* expression, + status_t result, Value* value); + private: struct BreakpointByAddressPredicate; struct WatchpointByAddressPredicate; @@ -384,6 +392,25 @@ protected: }; +class Team::ExpressionEvaluationEvent : public Event { +public: + ExpressionEvaluationEvent(uint32 type, + Team* team, const char* expression, + status_t result, Value* value); + virtual ~ExpressionEvaluationEvent(); + + status_t GetResult() const + { return fEvaluationResult; } + BString GetExpression() const { return fExpression; } + Value* GetValue() const { return fValue; } + +protected: + BString fExpression; + status_t fEvaluationResult; + Value* fValue; +}; + + class Team::Listener : public DoublyLinkedListLinkImpl { public: virtual ~Listener(); @@ -428,6 +455,10 @@ public: virtual void WatchpointChanged( const Team::WatchpointEvent& event); + virtual void ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& + event); + virtual void DebugReportChanged( const Team::DebugReportEvent& event); }; diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 50e293ef7b..748b6a8625 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -21,6 +21,7 @@ class CpuState; class FunctionInstance; class Image; class LocatableFile; +class SourceLanguage; class StackFrame; class Team; class TeamUiSettings; @@ -136,6 +137,12 @@ public: target_addr_t address, TeamMemoryBlock::Listener* listener) = 0; + virtual void ExpressionEvaluationRequested( + SourceLanguage* language, + const char* expression, + type_code resultType, + StackFrame* frame = NULL) = 0; + virtual void DebugReportRequested(entry_ref* path) = 0; virtual void TeamRestartRequested() = 0; diff --git a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp index bc841a47c7..a17cfc4e75 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp @@ -19,7 +19,6 @@ enum { - MSG_EVALUATE_EXPRESSION = 'evex', MSG_CHANGE_EVALUATION_TYPE = 'chet' };