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_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',
@@ -17,19 +17,20 @@
#include <TextControl.h>
#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<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_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
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);
}
@@ -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.
*/
#ifndef INSPECTOR_WINDOW_H
@@ -9,6 +9,7 @@
#include <Window.h>
#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;
};
@@ -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<BLooper> lock(this);
if (!lock.IsLocked())
return;
if (event.GetExpression() != fExpressionInput->Text())
return;
lock.Unlock();
message.AddInt32("result", event.GetResult());
BReference<Value> 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<Value> reference;
if (message->FindPointer("value",
@@ -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 (...) {
@@ -13,45 +13,58 @@
#include <String.h>
#include <TextControl.h>
#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<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
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<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) {
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;
@@ -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 <Window.h>
#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