From fdb2d5d961fed2e838859db047e284795cf5cb30 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Wed, 29 Oct 2014 10:09:33 -0400 Subject: [PATCH] Debugger: Adapt expression eval users to async interface. Factor out message constant for expression evaluation completion, as multiple places will be using that. ExpressionEvaluationWindow: - Check for expression match immediately in listener hook, and don't bother dispatching to the message loop in such a case. Simplifies some of the other code. InspectorWindow / WatchPromptWindow: - Rather than attempting to evaluate an expression directly, we now defer to the async interface. Clean up and adjust accordingly. TeamWindow: - Adjust window creation calls due to parameter changes. This leaves only the CLI dump memory command to be adapted. --- src/apps/debugger/MessageCodes.h | 1 + .../gui/inspector_window/InspectorWindow.cpp | 125 +++++++++++------ .../gui/inspector_window/InspectorWindow.h | 17 ++- .../ExpressionEvaluationWindow.cpp | 23 ++-- .../gui/team_window/TeamWindow.cpp | 2 +- .../gui/team_window/WatchPromptWindow.cpp | 129 +++++++++++++----- .../gui/team_window/WatchPromptWindow.h | 25 ++-- 7 files changed, 227 insertions(+), 95 deletions(-) diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index 63dcd001e7..42d99667f0 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -69,6 +69,7 @@ enum { MSG_EXPRESSION_WINDOW_CLOSED = 'ewwc', MSG_INSPECT_ADDRESS = 'isad', MSG_EVALUATE_EXPRESSION = 'evex', + MSG_EXPRESSION_EVALUATED = 'exev', MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp', MSG_TYPECAST_TO_ARRAY = 'stta', MSG_TYPECAST_NODE = 'tyno', diff --git a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp index 3c29e44720..eb0f8cdd14 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp @@ -17,19 +17,20 @@ #include #include "Architecture.h" -#include "CLanguageExpressionEvaluator.h" +#include "CppLanguage.h" #include "GuiTeamUiSettings.h" #include "MemoryView.h" #include "MessageCodes.h" #include "Number.h" #include "Team.h" #include "UserInterface.h" +#include "Value.h" enum { MSG_NAVIGATE_PREVIOUS_BLOCK = 'npbl', MSG_NAVIGATE_NEXT_BLOCK = 'npnl', - MSG_MEMORY_BLOCK_RETRIEVED = 'mbre', + MSG_MEMORY_BLOCK_RETRIEVED = 'mbre' }; @@ -46,8 +47,11 @@ InspectorWindow::InspectorWindow(::Team* team, UserInterfaceListener* listener, fCurrentBlock(NULL), fCurrentAddress(0LL), fTeam(team), + fLanguage(NULL), fTarget(target) { + AutoLocker< ::Team> teamLocker(fTeam); + fTeam->AddListener(this); } @@ -57,6 +61,12 @@ InspectorWindow::~InspectorWindow() fCurrentBlock->RemoveListener(this); fCurrentBlock->ReleaseReference(); } + + AutoLocker< ::Team> teamLocker(fTeam); + fTeam->RemoveListener(this); + + if (fLanguage != NULL) + fLanguage->ReleaseReference(); } @@ -80,6 +90,8 @@ InspectorWindow::Create(::Team* team, UserInterfaceListener* listener, void InspectorWindow::_Init() { + fLanguage = new CppLanguage(); + BScrollView* scrollView; BMenu* hexMenu = new BMenu("Hex Mode"); @@ -197,45 +209,44 @@ InspectorWindow::MessageReceived(BMessage* message) case MSG_INSPECT_ADDRESS: { target_addr_t address = 0; - bool addressValid = false; if (message->FindUInt64("address", &address) != B_OK) { - CLanguageExpressionEvaluator evaluator; - const char* addressExpression = fAddressInput->Text(); - BString errorMessage; - try { - Number value; - value = evaluator.Evaluate(addressExpression, - B_INT64_TYPE); - address = value.GetValue().ToUInt64(); - } catch(ParseException parseError) { - errorMessage.SetToFormat("Failed to parse address: %s", - parseError.message.String()); - } catch(...) { - errorMessage.SetToFormat( - "Unknown error while parsing address"); - } - - if (errorMessage.Length() > 0) { - BAlert* alert = new(std::nothrow) BAlert("Inspect Address", - errorMessage.String(), "Close"); - if (alert != NULL) - alert->Go(); - } else - addressValid = true; - } else { - addressValid = true; - } - - if (addressValid) { - fCurrentAddress = address; - if (fCurrentBlock == NULL - || !fCurrentBlock->Contains(address)) { - fListener->InspectRequested(address, this); - } else - fMemoryView->SetTargetAddress(fCurrentBlock, address); - } + fListener->ExpressionEvaluationRequested( + fLanguage, + fAddressInput->Text(), + B_UINT64_TYPE); + } else + _SetToAddress(address); break; } + + case MSG_EXPRESSION_EVALUATED: + { + BString errorMessage; + BReference reference; + Value* value = NULL; + if (message->FindPointer("value", + reinterpret_cast(&value)) == B_OK) { + reference.SetTo(value, true); + BVariant variant; + value->ToVariant(variant); + if (variant.Type() == B_UINT64_TYPE) { + _SetToAddress(variant.ToUInt64()); + break; + } else + value->ToString(errorMessage); + } else { + status_t result = message->FindInt32("result"); + errorMessage.SetToFormat("Failed to evaluate expression: %s", + strerror(result)); + } + + BAlert* alert = new(std::nothrow) BAlert("Inspect Address", + errorMessage.String(), "Close"); + if (alert != NULL) + alert->Go(); + break; + } + case MSG_NAVIGATE_PREVIOUS_BLOCK: case MSG_NAVIGATE_NEXT_BLOCK: { @@ -344,6 +355,32 @@ InspectorWindow::TargetAddressChanged(target_addr_t address) } +void +InspectorWindow::ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& event) +{ + BMessage message(MSG_EXPRESSION_EVALUATED); + AutoLocker lock(this); + if (!lock.IsLocked()) + return; + + if (event.GetExpression() != fAddressInput->Text()) + return; + + lock.Unlock(); + message.AddInt32("result", event.GetResult()); + Value* value = event.GetValue(); + BReference reference; + if (value != NULL) { + reference.SetTo(value); + message.AddPointer("value", value); + } + + if (PostMessage(&message) == B_OK) + reference.Detach(); +} + + status_t InspectorWindow::LoadSettings(const GuiTeamUiSettings& settings) { @@ -432,3 +469,15 @@ InspectorWindow::_SaveMenuFieldMode(BMenuField* field, const char* name, return B_OK; } + + +void +InspectorWindow::_SetToAddress(target_addr_t address) +{ + fCurrentAddress = address; + if (fCurrentBlock == NULL + || !fCurrentBlock->Contains(address)) { + fListener->InspectRequested(address, this); + } else + fMemoryView->SetTargetAddress(fCurrentBlock, address); +} diff --git a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h index 528701d9b8..f2b11d3db6 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013, Rene Gollent, rene@gollent.com. All rights reserved. + * Copyright 2011-2014, Rene Gollent, rene@gollent.com. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef INSPECTOR_WINDOW_H @@ -9,6 +9,7 @@ #include #include "MemoryView.h" +#include "Team.h" #include "TeamMemoryBlock.h" #include "Types.h" @@ -18,13 +19,14 @@ class BMenuField; class BMessenger; class BTextControl; class GuiTeamUiSettings; -class Team; +class SourceLanguage; class UserInterfaceListener; class InspectorWindow : public BWindow, public TeamMemoryBlock::Listener, - public MemoryView::Listener { + public MemoryView::Listener, + private Team::Listener { public: InspectorWindow(::Team* team, UserInterfaceListener* listener, @@ -47,10 +49,16 @@ public: // MemoryView::Listener virtual void TargetAddressChanged(target_addr_t address); + // Team::Listener + virtual void ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& + event); + status_t LoadSettings( const GuiTeamUiSettings& settings); status_t SaveSettings( BMessage& settings); + private: void _Init(); @@ -61,6 +69,8 @@ private: const char* name, BMessage& settings); + void _SetToAddress(target_addr_t address); + private: UserInterfaceListener* fListener; BTextControl* fAddressInput; @@ -73,6 +83,7 @@ private: TeamMemoryBlock* fCurrentBlock; target_addr_t fCurrentAddress; ::Team* fTeam; + SourceLanguage* fLanguage; BHandler* fTarget; }; 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 446d68ca72..c8d55adb89 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp @@ -21,8 +21,7 @@ enum { - MSG_CHANGE_EVALUATION_TYPE = 'chet', - MSG_EXPRESSION_EVALUATED = 'exev' + MSG_CHANGE_EVALUATION_TYPE = 'chet' }; @@ -164,9 +163,16 @@ ExpressionEvaluationWindow::ExpressionEvaluated( const Team::ExpressionEvaluationEvent& event) { BMessage message(MSG_EXPRESSION_EVALUATED); - message.AddString("expression", event.GetExpression()); - message.AddInt32("result", event.GetResult()); + AutoLocker lock(this); + if (!lock.IsLocked()) + return; + + if (event.GetExpression() != fExpressionInput->Text()) + return; + + lock.Unlock(); + message.AddInt32("result", event.GetResult()); BReference reference; Value* value = event.GetValue(); if (value != NULL) { @@ -207,7 +213,7 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message) break; fListener->ExpressionEvaluationRequested(fLanguage, - fExpressionInput->TextView()->Text(), fCurrentEvaluationType); + fExpressionInput->Text(), fCurrentEvaluationType); break; } @@ -219,13 +225,6 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message) case MSG_EXPRESSION_EVALUATED: { - BString expression; - if (message->FindString("expression", &expression) != B_OK) - break; - - if (expression != fExpressionInput->TextView()->Text()) - break; - Value* value = NULL; BReference reference; if (message->FindPointer("value", diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 1eda3b8040..b962600ba6 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -408,7 +408,7 @@ TeamWindow::MessageReceived(BMessage* message) try { WatchPromptWindow* window = WatchPromptWindow::Create( - fTeam->GetArchitecture(), address, type, length, + fTeam, address, type, length, fListener); window->Show(); } catch (...) { diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp index bdeffcfd25..f96e3b7dcd 100644 --- a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.cpp @@ -13,45 +13,58 @@ #include #include +#include "AutoLocker.h" + #include "Architecture.h" -#include "CLanguageExpressionEvaluator.h" +#include "CppLanguage.h" #include "MessageCodes.h" #include "Number.h" #include "UserInterface.h" +#include "Value.h" #include "Watchpoint.h" -WatchPromptWindow::WatchPromptWindow(Architecture* architecture, - target_addr_t address, uint32 type, int32 length, - UserInterfaceListener* listener) +WatchPromptWindow::WatchPromptWindow(::Team* team, target_addr_t address, + uint32 type, int32 length, UserInterfaceListener* listener) : BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), fInitialAddress(address), fInitialType(type), fInitialLength(length), - fArchitecture(architecture), + fTeam(team), + fRequestedAddress(0), + fRequestedLength(0), fAddressInput(NULL), fLengthInput(NULL), fTypeField(NULL), - fListener(listener) + fListener(listener), + fLanguage(NULL) { - fArchitecture->AcquireReference(); + AutoLocker< ::Team> teamLocker(fTeam); + fTeam->AddListener(this); + fTeam->GetArchitecture()->AcquireReference(); } WatchPromptWindow::~WatchPromptWindow() { - fArchitecture->ReleaseReference(); + fTeam->GetArchitecture()->ReleaseReference(); + + AutoLocker< ::Team> teamLocker(fTeam); + fTeam->RemoveListener(this); + + if (fLanguage != NULL) + fLanguage->ReleaseReference(); } WatchPromptWindow* -WatchPromptWindow::Create(Architecture* architecture, target_addr_t address, - uint32 type, int32 length, UserInterfaceListener* listener) +WatchPromptWindow::Create(::Team* team, target_addr_t address, uint32 type, + int32 length, UserInterfaceListener* listener) { - WatchPromptWindow* self = new WatchPromptWindow(architecture, address, - type, length, listener); + WatchPromptWindow* self = new WatchPromptWindow(team, address, type, + length, listener); try { self->_Init(); @@ -68,6 +81,8 @@ WatchPromptWindow::Create(Architecture* architecture, target_addr_t address, void WatchPromptWindow::_Init() { + fLanguage = new CppLanguage(); + BString text; text.SetToFormat("0x%" B_PRIx64, fInitialAddress); fAddressInput = new BTextControl("Address:", text, NULL); @@ -78,7 +93,7 @@ WatchPromptWindow::_Init() int32 maxDebugRegisters = 0; int32 maxBytesPerRegister = 0; uint8 debugCapabilityFlags = 0; - fArchitecture->GetWatchpointDebugCapabilities(maxDebugRegisters, + fTeam->GetArchitecture()->GetWatchpointDebugCapabilities(maxDebugRegisters, maxBytesPerRegister, debugCapabilityFlags); BMenu* typeMenu = new BMenu("Watch type"); @@ -135,31 +150,65 @@ WatchPromptWindow::Show() } +void +WatchPromptWindow::ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& event) +{ + BMessage message(MSG_EXPRESSION_EVALUATED); + AutoLocker lock(this); + if (!lock.IsLocked()) + return; + + BString expression = event.GetExpression(); + if (expression != fAddressInput->Text() + && expression != fLengthInput->Text()) { + return; + } + + lock.Unlock(); + message.AddInt32("result", event.GetResult()); + Value* value = event.GetValue(); + BReference reference; + if (value != NULL) { + reference.SetTo(value); + message.AddPointer("value", value); + } + + if (PostMessage(&message) == B_OK) + reference.Detach(); +} + + void WatchPromptWindow::MessageReceived(BMessage* message) { switch (message->what) { - case MSG_SET_WATCHPOINT: + case MSG_EXPRESSION_EVALUATED: { - target_addr_t address = 0; - int32 length = 0; - CLanguageExpressionEvaluator evaluator; BString errorMessage; - try { - Number value = evaluator.Evaluate(fAddressInput->Text(), - B_UINT64_TYPE); - address = value.GetValue().ToUInt64(); - value = evaluator.Evaluate(fLengthInput->Text(), - B_INT32_TYPE); - length = value.GetValue().ToInt32(); - } catch(ParseException parseError) { - errorMessage.SetToFormat("Failed to parse data: %s", - parseError.message.String()); - } catch(...) { - errorMessage.SetToFormat( - "Unknown error while parsing address"); + BReference reference; + Value* value = NULL; + if (message->FindPointer("value", + reinterpret_cast(&value)) == B_OK) { + reference.SetTo(value, true); + BVariant variant; + value->ToVariant(variant); + if (variant.Type() == B_UINT64_TYPE) { + fRequestedAddress = variant.ToUInt64(); + break; + } else if (variant.Type() == B_INT32_TYPE) + fRequestedLength = variant.ToInt32(); + else + value->ToString(errorMessage); + } else { + status_t result = message->FindInt32("result"); + errorMessage.SetToFormat("Failed to evaluate expression: %s", + strerror(result)); } + if (fRequestedLength <= 0) + errorMessage = "Watchpoint length must be at least 1 byte."; + if (!errorMessage.IsEmpty()) { BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint", errorMessage.String(), "Close"); @@ -169,13 +218,27 @@ WatchPromptWindow::MessageReceived(BMessage* message) } fListener->ClearWatchpointRequested(fInitialAddress); - fListener->SetWatchpointRequested(address, fTypeField->Menu() - ->IndexOf(fTypeField->Menu()->FindMarked()), length, true); + fListener->SetWatchpointRequested(fRequestedAddress, + fTypeField->Menu()->IndexOf(fTypeField->Menu()->FindMarked()), + fRequestedLength, true); PostMessage(B_QUIT_REQUESTED); - break; } + + case MSG_SET_WATCHPOINT: + { + fRequestedAddress = 0; + fRequestedLength = 0; + + fListener->ExpressionEvaluationRequested(fLanguage, + fAddressInput->Text(), B_UINT64_TYPE); + + fListener->ExpressionEvaluationRequested(fLanguage, + fLengthInput->Text(), B_INT32_TYPE); + break; + } + default: BWindow::MessageReceived(message); break; diff --git a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h index 5854ca8e4e..7e07c0660d 100644 --- a/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/WatchPromptWindow.h @@ -1,5 +1,5 @@ /* - * Copyright 2012, Rene Gollent, rene@gollent.com. + * Copyright 2012-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef WATCH_PROMPT_WINDOW_H @@ -8,27 +8,28 @@ #include +#include "Team.h" #include "types/Types.h" -class Architecture; -class BTextControl; -class Watchpoint; class BMenuField; +class BTextControl; +class SourceLanguage; +class Watchpoint; class UserInterfaceListener; -class WatchPromptWindow : public BWindow +class WatchPromptWindow : public BWindow, private Team::Listener { public: - WatchPromptWindow(Architecture* architecture, + WatchPromptWindow(::Team* team, target_addr_t address, uint32 type, int32 length, UserInterfaceListener* listener); ~WatchPromptWindow(); - static WatchPromptWindow* Create(Architecture* architecture, + static WatchPromptWindow* Create(::Team* team, target_addr_t address, uint32 type, int32 length, UserInterfaceListener* listener); @@ -39,6 +40,11 @@ public: virtual void Show(); + // Team::Listener + virtual void ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& + event); + private: void _Init(); @@ -47,13 +53,16 @@ private: target_addr_t fInitialAddress; uint32 fInitialType; int32 fInitialLength; - Architecture* fArchitecture; + ::Team* fTeam; + target_addr_t fRequestedAddress; + int32 fRequestedLength; BTextControl* fAddressInput; BTextControl* fLengthInput; BMenuField* fTypeField; UserInterfaceListener* fListener; BButton* fWatchButton; BButton* fCancelButton; + SourceLanguage* fLanguage; }; #endif // WATCH_PROMPT_WINDOW_H