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.
This commit is contained in:
Rene Gollent
2014-10-29 10:52:50 -04:00
parent 7c5dfbad75
commit fdb2d5d961
7 changed files with 227 additions and 95 deletions
+1
View File
@@ -69,6 +69,7 @@ enum {
MSG_EXPRESSION_WINDOW_CLOSED = 'ewwc', MSG_EXPRESSION_WINDOW_CLOSED = 'ewwc',
MSG_INSPECT_ADDRESS = 'isad', MSG_INSPECT_ADDRESS = 'isad',
MSG_EVALUATE_EXPRESSION = 'evex', MSG_EVALUATE_EXPRESSION = 'evex',
MSG_EXPRESSION_EVALUATED = 'exev',
MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp', MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp',
MSG_TYPECAST_TO_ARRAY = 'stta', MSG_TYPECAST_TO_ARRAY = 'stta',
MSG_TYPECAST_NODE = 'tyno', MSG_TYPECAST_NODE = 'tyno',
@@ -17,19 +17,20 @@
#include <TextControl.h> #include <TextControl.h>
#include "Architecture.h" #include "Architecture.h"
#include "CLanguageExpressionEvaluator.h" #include "CppLanguage.h"
#include "GuiTeamUiSettings.h" #include "GuiTeamUiSettings.h"
#include "MemoryView.h" #include "MemoryView.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "Number.h" #include "Number.h"
#include "Team.h" #include "Team.h"
#include "UserInterface.h" #include "UserInterface.h"
#include "Value.h"
enum { enum {
MSG_NAVIGATE_PREVIOUS_BLOCK = 'npbl', MSG_NAVIGATE_PREVIOUS_BLOCK = 'npbl',
MSG_NAVIGATE_NEXT_BLOCK = 'npnl', 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), fCurrentBlock(NULL),
fCurrentAddress(0LL), fCurrentAddress(0LL),
fTeam(team), fTeam(team),
fLanguage(NULL),
fTarget(target) fTarget(target)
{ {
AutoLocker< ::Team> teamLocker(fTeam);
fTeam->AddListener(this);
} }
@@ -57,6 +61,12 @@ InspectorWindow::~InspectorWindow()
fCurrentBlock->RemoveListener(this); fCurrentBlock->RemoveListener(this);
fCurrentBlock->ReleaseReference(); 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 void
InspectorWindow::_Init() InspectorWindow::_Init()
{ {
fLanguage = new CppLanguage();
BScrollView* scrollView; BScrollView* scrollView;
BMenu* hexMenu = new BMenu("Hex Mode"); BMenu* hexMenu = new BMenu("Hex Mode");
@@ -197,45 +209,44 @@ InspectorWindow::MessageReceived(BMessage* message)
case MSG_INSPECT_ADDRESS: case MSG_INSPECT_ADDRESS:
{ {
target_addr_t address = 0; target_addr_t address = 0;
bool addressValid = false;
if (message->FindUInt64("address", &address) != B_OK) { if (message->FindUInt64("address", &address) != B_OK) {
CLanguageExpressionEvaluator evaluator; fListener->ExpressionEvaluationRequested(
const char* addressExpression = fAddressInput->Text(); fLanguage,
BString errorMessage; fAddressInput->Text(),
try { B_UINT64_TYPE);
Number value; } else
value = evaluator.Evaluate(addressExpression, _SetToAddress(address);
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);
}
break; break;
} }
case MSG_EXPRESSION_EVALUATED:
{
BString errorMessage;
BReference<Value> reference;
Value* value = NULL;
if (message->FindPointer("value",
reinterpret_cast<void**>(&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_PREVIOUS_BLOCK:
case MSG_NAVIGATE_NEXT_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<BLooper> lock(this);
if (!lock.IsLocked())
return;
if (event.GetExpression() != fAddressInput->Text())
return;
lock.Unlock();
message.AddInt32("result", event.GetResult());
Value* value = event.GetValue();
BReference<Value> reference;
if (value != NULL) {
reference.SetTo(value);
message.AddPointer("value", value);
}
if (PostMessage(&message) == B_OK)
reference.Detach();
}
status_t status_t
InspectorWindow::LoadSettings(const GuiTeamUiSettings& settings) InspectorWindow::LoadSettings(const GuiTeamUiSettings& settings)
{ {
@@ -432,3 +469,15 @@ InspectorWindow::_SaveMenuFieldMode(BMenuField* field, const char* name,
return B_OK; 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);
}
@@ -1,5 +1,5 @@
/* /*
* Copyright 2011-2013, Rene Gollent, [email protected]. All rights reserved. * Copyright 2011-2014, Rene Gollent, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef INSPECTOR_WINDOW_H #ifndef INSPECTOR_WINDOW_H
@@ -9,6 +9,7 @@
#include <Window.h> #include <Window.h>
#include "MemoryView.h" #include "MemoryView.h"
#include "Team.h"
#include "TeamMemoryBlock.h" #include "TeamMemoryBlock.h"
#include "Types.h" #include "Types.h"
@@ -18,13 +19,14 @@ class BMenuField;
class BMessenger; class BMessenger;
class BTextControl; class BTextControl;
class GuiTeamUiSettings; class GuiTeamUiSettings;
class Team; class SourceLanguage;
class UserInterfaceListener; class UserInterfaceListener;
class InspectorWindow : public BWindow, class InspectorWindow : public BWindow,
public TeamMemoryBlock::Listener, public TeamMemoryBlock::Listener,
public MemoryView::Listener { public MemoryView::Listener,
private Team::Listener {
public: public:
InspectorWindow(::Team* team, InspectorWindow(::Team* team,
UserInterfaceListener* listener, UserInterfaceListener* listener,
@@ -47,10 +49,16 @@ public:
// MemoryView::Listener // MemoryView::Listener
virtual void TargetAddressChanged(target_addr_t address); virtual void TargetAddressChanged(target_addr_t address);
// Team::Listener
virtual void ExpressionEvaluated(
const Team::ExpressionEvaluationEvent&
event);
status_t LoadSettings( status_t LoadSettings(
const GuiTeamUiSettings& settings); const GuiTeamUiSettings& settings);
status_t SaveSettings( status_t SaveSettings(
BMessage& settings); BMessage& settings);
private: private:
void _Init(); void _Init();
@@ -61,6 +69,8 @@ private:
const char* name, const char* name,
BMessage& settings); BMessage& settings);
void _SetToAddress(target_addr_t address);
private: private:
UserInterfaceListener* fListener; UserInterfaceListener* fListener;
BTextControl* fAddressInput; BTextControl* fAddressInput;
@@ -73,6 +83,7 @@ private:
TeamMemoryBlock* fCurrentBlock; TeamMemoryBlock* fCurrentBlock;
target_addr_t fCurrentAddress; target_addr_t fCurrentAddress;
::Team* fTeam; ::Team* fTeam;
SourceLanguage* fLanguage;
BHandler* fTarget; BHandler* fTarget;
}; };
@@ -21,8 +21,7 @@
enum { enum {
MSG_CHANGE_EVALUATION_TYPE = 'chet', MSG_CHANGE_EVALUATION_TYPE = 'chet'
MSG_EXPRESSION_EVALUATED = 'exev'
}; };
@@ -164,9 +163,16 @@ ExpressionEvaluationWindow::ExpressionEvaluated(
const Team::ExpressionEvaluationEvent& event) const Team::ExpressionEvaluationEvent& event)
{ {
BMessage message(MSG_EXPRESSION_EVALUATED); BMessage message(MSG_EXPRESSION_EVALUATED);
message.AddString("expression", event.GetExpression());
message.AddInt32("result", event.GetResult());
AutoLocker<BLooper> lock(this);
if (!lock.IsLocked())
return;
if (event.GetExpression() != fExpressionInput->Text())
return;
lock.Unlock();
message.AddInt32("result", event.GetResult());
BReference<Value> reference; BReference<Value> reference;
Value* value = event.GetValue(); Value* value = event.GetValue();
if (value != NULL) { if (value != NULL) {
@@ -207,7 +213,7 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
break; break;
fListener->ExpressionEvaluationRequested(fLanguage, fListener->ExpressionEvaluationRequested(fLanguage,
fExpressionInput->TextView()->Text(), fCurrentEvaluationType); fExpressionInput->Text(), fCurrentEvaluationType);
break; break;
} }
@@ -219,13 +225,6 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message)
case MSG_EXPRESSION_EVALUATED: case MSG_EXPRESSION_EVALUATED:
{ {
BString expression;
if (message->FindString("expression", &expression) != B_OK)
break;
if (expression != fExpressionInput->TextView()->Text())
break;
Value* value = NULL; Value* value = NULL;
BReference<Value> reference; BReference<Value> reference;
if (message->FindPointer("value", if (message->FindPointer("value",
@@ -408,7 +408,7 @@ TeamWindow::MessageReceived(BMessage* message)
try { try {
WatchPromptWindow* window = WatchPromptWindow::Create( WatchPromptWindow* window = WatchPromptWindow::Create(
fTeam->GetArchitecture(), address, type, length, fTeam, address, type, length,
fListener); fListener);
window->Show(); window->Show();
} catch (...) { } catch (...) {
@@ -13,45 +13,58 @@
#include <String.h> #include <String.h>
#include <TextControl.h> #include <TextControl.h>
#include "AutoLocker.h"
#include "Architecture.h" #include "Architecture.h"
#include "CLanguageExpressionEvaluator.h" #include "CppLanguage.h"
#include "MessageCodes.h" #include "MessageCodes.h"
#include "Number.h" #include "Number.h"
#include "UserInterface.h" #include "UserInterface.h"
#include "Value.h"
#include "Watchpoint.h" #include "Watchpoint.h"
WatchPromptWindow::WatchPromptWindow(Architecture* architecture, WatchPromptWindow::WatchPromptWindow(::Team* team, target_addr_t address,
target_addr_t address, uint32 type, int32 length, uint32 type, int32 length, UserInterfaceListener* listener)
UserInterfaceListener* listener)
: :
BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW, BWindow(BRect(), "Edit Watchpoint", B_FLOATING_WINDOW,
B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fInitialAddress(address), fInitialAddress(address),
fInitialType(type), fInitialType(type),
fInitialLength(length), fInitialLength(length),
fArchitecture(architecture), fTeam(team),
fRequestedAddress(0),
fRequestedLength(0),
fAddressInput(NULL), fAddressInput(NULL),
fLengthInput(NULL), fLengthInput(NULL),
fTypeField(NULL), fTypeField(NULL),
fListener(listener) fListener(listener),
fLanguage(NULL)
{ {
fArchitecture->AcquireReference(); AutoLocker< ::Team> teamLocker(fTeam);
fTeam->AddListener(this);
fTeam->GetArchitecture()->AcquireReference();
} }
WatchPromptWindow::~WatchPromptWindow() WatchPromptWindow::~WatchPromptWindow()
{ {
fArchitecture->ReleaseReference(); fTeam->GetArchitecture()->ReleaseReference();
AutoLocker< ::Team> teamLocker(fTeam);
fTeam->RemoveListener(this);
if (fLanguage != NULL)
fLanguage->ReleaseReference();
} }
WatchPromptWindow* WatchPromptWindow*
WatchPromptWindow::Create(Architecture* architecture, target_addr_t address, WatchPromptWindow::Create(::Team* team, target_addr_t address, uint32 type,
uint32 type, int32 length, UserInterfaceListener* listener) int32 length, UserInterfaceListener* listener)
{ {
WatchPromptWindow* self = new WatchPromptWindow(architecture, address, WatchPromptWindow* self = new WatchPromptWindow(team, address, type,
type, length, listener); length, listener);
try { try {
self->_Init(); self->_Init();
@@ -68,6 +81,8 @@ WatchPromptWindow::Create(Architecture* architecture, target_addr_t address,
void void
WatchPromptWindow::_Init() WatchPromptWindow::_Init()
{ {
fLanguage = new CppLanguage();
BString text; BString text;
text.SetToFormat("0x%" B_PRIx64, fInitialAddress); text.SetToFormat("0x%" B_PRIx64, fInitialAddress);
fAddressInput = new BTextControl("Address:", text, NULL); fAddressInput = new BTextControl("Address:", text, NULL);
@@ -78,7 +93,7 @@ WatchPromptWindow::_Init()
int32 maxDebugRegisters = 0; int32 maxDebugRegisters = 0;
int32 maxBytesPerRegister = 0; int32 maxBytesPerRegister = 0;
uint8 debugCapabilityFlags = 0; uint8 debugCapabilityFlags = 0;
fArchitecture->GetWatchpointDebugCapabilities(maxDebugRegisters, fTeam->GetArchitecture()->GetWatchpointDebugCapabilities(maxDebugRegisters,
maxBytesPerRegister, debugCapabilityFlags); maxBytesPerRegister, debugCapabilityFlags);
BMenu* typeMenu = new BMenu("Watch type"); 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<BLooper> 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<Value> reference;
if (value != NULL) {
reference.SetTo(value);
message.AddPointer("value", value);
}
if (PostMessage(&message) == B_OK)
reference.Detach();
}
void void
WatchPromptWindow::MessageReceived(BMessage* message) WatchPromptWindow::MessageReceived(BMessage* message)
{ {
switch (message->what) { switch (message->what) {
case MSG_SET_WATCHPOINT: case MSG_EXPRESSION_EVALUATED:
{ {
target_addr_t address = 0;
int32 length = 0;
CLanguageExpressionEvaluator evaluator;
BString errorMessage; BString errorMessage;
try { BReference<Value> reference;
Number value = evaluator.Evaluate(fAddressInput->Text(), Value* value = NULL;
B_UINT64_TYPE); if (message->FindPointer("value",
address = value.GetValue().ToUInt64(); reinterpret_cast<void**>(&value)) == B_OK) {
value = evaluator.Evaluate(fLengthInput->Text(), reference.SetTo(value, true);
B_INT32_TYPE); BVariant variant;
length = value.GetValue().ToInt32(); value->ToVariant(variant);
} catch(ParseException parseError) { if (variant.Type() == B_UINT64_TYPE) {
errorMessage.SetToFormat("Failed to parse data: %s", fRequestedAddress = variant.ToUInt64();
parseError.message.String()); break;
} catch(...) { } else if (variant.Type() == B_INT32_TYPE)
errorMessage.SetToFormat( fRequestedLength = variant.ToInt32();
"Unknown error while parsing address"); 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()) { if (!errorMessage.IsEmpty()) {
BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint", BAlert* alert = new(std::nothrow) BAlert("Edit Watchpoint",
errorMessage.String(), "Close"); errorMessage.String(), "Close");
@@ -169,13 +218,27 @@ WatchPromptWindow::MessageReceived(BMessage* message)
} }
fListener->ClearWatchpointRequested(fInitialAddress); fListener->ClearWatchpointRequested(fInitialAddress);
fListener->SetWatchpointRequested(address, fTypeField->Menu() fListener->SetWatchpointRequested(fRequestedAddress,
->IndexOf(fTypeField->Menu()->FindMarked()), length, true); fTypeField->Menu()->IndexOf(fTypeField->Menu()->FindMarked()),
fRequestedLength, true);
PostMessage(B_QUIT_REQUESTED); PostMessage(B_QUIT_REQUESTED);
break; 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: default:
BWindow::MessageReceived(message); BWindow::MessageReceived(message);
break; break;
@@ -1,5 +1,5 @@
/* /*
* Copyright 2012, Rene Gollent, [email protected]. * Copyright 2012-2014, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef WATCH_PROMPT_WINDOW_H #ifndef WATCH_PROMPT_WINDOW_H
@@ -8,27 +8,28 @@
#include <Window.h> #include <Window.h>
#include "Team.h"
#include "types/Types.h" #include "types/Types.h"
class Architecture;
class BTextControl;
class Watchpoint;
class BMenuField; class BMenuField;
class BTextControl;
class SourceLanguage;
class Watchpoint;
class UserInterfaceListener; class UserInterfaceListener;
class WatchPromptWindow : public BWindow class WatchPromptWindow : public BWindow, private Team::Listener
{ {
public: public:
WatchPromptWindow(Architecture* architecture, WatchPromptWindow(::Team* team,
target_addr_t address, uint32 type, target_addr_t address, uint32 type,
int32 length, int32 length,
UserInterfaceListener* listener); UserInterfaceListener* listener);
~WatchPromptWindow(); ~WatchPromptWindow();
static WatchPromptWindow* Create(Architecture* architecture, static WatchPromptWindow* Create(::Team* team,
target_addr_t address, uint32 type, target_addr_t address, uint32 type,
int32 length, int32 length,
UserInterfaceListener* listener); UserInterfaceListener* listener);
@@ -39,6 +40,11 @@ public:
virtual void Show(); virtual void Show();
// Team::Listener
virtual void ExpressionEvaluated(
const Team::ExpressionEvaluationEvent&
event);
private: private:
void _Init(); void _Init();
@@ -47,13 +53,16 @@ private:
target_addr_t fInitialAddress; target_addr_t fInitialAddress;
uint32 fInitialType; uint32 fInitialType;
int32 fInitialLength; int32 fInitialLength;
Architecture* fArchitecture; ::Team* fTeam;
target_addr_t fRequestedAddress;
int32 fRequestedLength;
BTextControl* fAddressInput; BTextControl* fAddressInput;
BTextControl* fLengthInput; BTextControl* fLengthInput;
BMenuField* fTypeField; BMenuField* fTypeField;
UserInterfaceListener* fListener; UserInterfaceListener* fListener;
BButton* fWatchButton; BButton* fWatchButton;
BButton* fCancelButton; BButton* fCancelButton;
SourceLanguage* fLanguage;
}; };
#endif // WATCH_PROMPT_WINDOW_H #endif // WATCH_PROMPT_WINDOW_H