Added view to show registers. Doesn't look particularly nice, but seems to work.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31122 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-06-19 17:31:24 +00:00
parent 8c724eb86c
commit 15b6b23934
4 changed files with 355 additions and 8 deletions

View File

@ -0,0 +1,248 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "RegisterView.h"
#include <stdio.h>
#include <new>
#include "table/TableColumns.h"
#include "Architecture.h"
#include "CpuState.h"
#include "Register.h"
// #pragma mark - RegisterValueColumn
class RegisterView::RegisterValueColumn : public StringTableColumn {
public:
RegisterValueColumn(int32 modelIndex, const char* title, float width,
float minWidth, float maxWidth, uint32 truncate = B_TRUNCATE_MIDDLE,
alignment align = B_ALIGN_RIGHT)
:
StringTableColumn(modelIndex, title, width, minWidth, maxWidth,
truncate, align)
{
}
protected:
virtual BField* PrepareField(const Variant& value) const
{
char buffer[64];
return StringTableColumn::PrepareField(
Variant(_ToString(value, buffer, sizeof(buffer)),
VARIANT_DONT_COPY_DATA));
}
virtual int CompareValues(const Variant& a, const Variant& b)
{
// If neither value is a number, compare the strings. If only one value
// is a number, it is considered to be greater.
if (!a.IsNumber()) {
if (b.IsNumber())
return -1;
char bufferA[64];
char bufferB[64];
return StringTableColumn::CompareValues(
Variant(_ToString(a, bufferA, sizeof(bufferA)),
VARIANT_DONT_COPY_DATA),
Variant(_ToString(b, bufferB, sizeof(bufferB)),
VARIANT_DONT_COPY_DATA));
}
if (!b.IsNumber())
return 1;
// If either value is floating point, we compare floating point values.
if (a.IsFloat() || b.IsFloat()) {
double valueA = a.ToDouble();
double valueB = b.ToDouble();
return valueA < valueB ? -1 : (valueA == valueB ? 0 : 1);
}
uint64 valueA = a.ToUInt64();
uint64 valueB = b.ToUInt64();
return valueA < valueB ? -1 : (valueA == valueB ? 0 : 1);
}
private:
const char* _ToString(const Variant& value, char* buffer,
size_t bufferSize) const
{
if (!value.IsNumber())
return value.ToString();
switch (value.Type()) {
case B_FLOAT_TYPE:
case B_DOUBLE_TYPE:
snprintf(buffer, bufferSize, "%g", value.ToDouble());
break;
case B_INT8_TYPE:
case B_UINT8_TYPE:
snprintf(buffer, bufferSize, "0x%02x", value.ToUInt8());
break;
case B_INT16_TYPE:
case B_UINT16_TYPE:
snprintf(buffer, bufferSize, "0x%04x", value.ToUInt16());
break;
case B_INT32_TYPE:
case B_UINT32_TYPE:
snprintf(buffer, bufferSize, "0x%08lx", value.ToUInt32());
break;
case B_INT64_TYPE:
case B_UINT64_TYPE:
default:
snprintf(buffer, bufferSize, "0x%016llx", value.ToUInt64());
break;
}
return buffer;
}
};
// #pragma mark - RegisterTableModel
class RegisterView::RegisterTableModel : public TableModel {
public:
RegisterTableModel(Architecture* architecture)
:
fArchitecture(architecture),
fCpuState(NULL)
{
}
~RegisterTableModel()
{
}
void SetCpuState(CpuState* cpuState)
{
fCpuState = cpuState;
NotifyRowsChanged(0, CountRows());
}
virtual int32 CountColumns() const
{
return 2;
}
virtual int32 CountRows() const
{
return fArchitecture->CountRegisters();
}
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, Variant& value)
{
if (rowIndex < 0 || rowIndex >= fArchitecture->CountRegisters())
return false;
const Register* reg = fArchitecture->Registers() + rowIndex;
switch (columnIndex) {
case 0:
value.SetTo(reg->Name(), VARIANT_DONT_COPY_DATA);
return true;
case 1:
if (fCpuState == NULL)
return false;
if (!fCpuState->GetRegisterValue(reg, value))
value.SetTo("?", VARIANT_DONT_COPY_DATA);
return true;
default:
return false;
}
}
private:
Architecture* fArchitecture;
CpuState* fCpuState;
};
// #pragma mark - RegisterView
RegisterView::RegisterView(Architecture* architecture)
:
BGroupView(B_VERTICAL),
fArchitecture(architecture),
fRegisterTable(NULL),
fRegisterTableModel(NULL)
{
SetName("Registers");
}
RegisterView::~RegisterView()
{
SetCpuState(NULL);
fRegisterTable->SetTableModel(NULL);
delete fRegisterTableModel;
}
/*static*/ RegisterView*
RegisterView::Create(Architecture* architecture)
{
RegisterView* self = new RegisterView(architecture);
try {
self->_Init();
} catch (...) {
delete self;
throw;
}
return self;
}
void
RegisterView::SetCpuState(CpuState* cpuState)
{
if (cpuState == fCpuState)
return;
if (fCpuState != NULL)
fCpuState->RemoveReference();
fCpuState = cpuState;
if (fCpuState != NULL)
fCpuState->AddReference();
fRegisterTableModel->SetCpuState(fCpuState);
}
void
RegisterView::TableRowInvoked(Table* table, int32 rowIndex)
{
}
void
RegisterView::_Init()
{
fRegisterTable = new Table("register list", 0);
AddChild(fRegisterTable->ToView());
// columns
fRegisterTable->AddColumn(new StringTableColumn(0, "Register", 80, 40, 1000,
B_TRUNCATE_END, B_ALIGN_LEFT));
fRegisterTable->AddColumn(new RegisterValueColumn(1, "Value", 80, 40, 1000,
B_TRUNCATE_END, B_ALIGN_RIGHT));
fRegisterTableModel = new RegisterTableModel(fArchitecture);
fRegisterTable->SetTableModel(fRegisterTableModel);
fRegisterTable->AddTableListener(this);
}

View File

@ -0,0 +1,45 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef REGISTER_VIEW_H
#define REGISTER_VIEW_H
#include <GroupView.h>
#include "table/Table.h"
#include "Team.h"
class Architecture;
class RegisterView : public BGroupView, private TableListener {
public:
RegisterView(Architecture* architecture);
~RegisterView();
static RegisterView* Create(Architecture* architecture);
// throws
void SetCpuState(CpuState* cpuState);
private:
class RegisterValueColumn;
class RegisterTableModel;
private:
// TableListener
virtual void TableRowInvoked(Table* table, int32 rowIndex);
void _Init();
private:
Architecture* fArchitecture;
CpuState* fCpuState;
Table* fRegisterTable;
RegisterTableModel* fRegisterTableModel;
};
#endif // REGISTER_VIEW_H

View File

@ -16,8 +16,10 @@
#include <AutoLocker.h>
#include "CpuState.h"
#include "ImageListView.h"
#include "MessageCodes.h"
#include "RegisterView.h"
#include "TeamDebugModel.h"
@ -32,8 +34,10 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener)
fActiveThread(NULL),
fListener(listener),
fTabView(NULL),
fLocalsTabView(NULL),
fThreadListView(NULL),
fImageListView(NULL),
fRegisterView(NULL),
fRunButton(NULL),
fStepOverButton(NULL),
fStepIntoButton(NULL),
@ -95,7 +99,16 @@ TeamWindow::MessageReceived(BMessage* message)
_HandleThreadStateChanged(threadID);
break;
}
// case MSG_THREAD_CPU_STATE_CHANGED:
case MSG_THREAD_CPU_STATE_CHANGED:
{
int32 threadID;
if (message->FindInt32("thread", &threadID) != B_OK)
break;
_HandleCpuStateChanged(threadID);
break;
}
// case MSG_THREAD_STACK_TRACE_CHANGED:
default:
@ -131,18 +144,18 @@ TeamWindow::ThreadStateChanged(const Team::ThreadEvent& event)
void
TeamWindow::ThreadCpuStateChanged(const Team::ThreadEvent& event)
{
// BMessage message(MSG_THREAD_CPU_STATE_CHANGED);
// message.AddInt32("thread", event.GetThread()->ID());
// PostMessage(&message);
BMessage message(MSG_THREAD_CPU_STATE_CHANGED);
message.AddInt32("thread", event.GetThread()->ID());
PostMessage(&message);
}
void
TeamWindow::ThreadStackTraceChanged(const Team::ThreadEvent& event)
{
// BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
// message.AddInt32("thread", event.GetThread()->ID());
// PostMessage(&message);
BMessage message(MSG_THREAD_STACK_TRACE_CHANGED);
message.AddInt32("thread", event.GetThread()->ID());
PostMessage(&message);
}
@ -162,7 +175,7 @@ TeamWindow::_Init()
.End()
.AddSplit(B_HORIZONTAL, 3.0f)
.Add(new BTextView("source view"), 3.0f)
.Add(new BTextView("variables view"))
.Add(fLocalsTabView = new BTabView("locals view"))
.End()
.End()
.End();
@ -183,6 +196,14 @@ TeamWindow::_Init()
.Add(fImageListView = ImageListView::Create())
.Add(new BTextView("source files"));
// add local variables tab
BView* tab = new BTextView("Variables");
fLocalsTabView->AddTab(tab);
// add registers tab
tab = fRegisterView = RegisterView::Create(fDebugModel->GetArchitecture());
fLocalsTabView->AddTab(tab);
fThreadListView->SetTeam(fDebugModel->GetTeam());
fImageListView->SetTeam(fDebugModel->GetTeam());
@ -210,6 +231,15 @@ TeamWindow::_SetActiveThread(::Thread* thread)
AutoLocker<TeamDebugModel> locker(fDebugModel);
_UpdateRunButtons();
CpuState* cpuState = fActiveThread != NULL
? fActiveThread->GetCpuState() : NULL;
Reference<CpuState> reference(cpuState);
// hold a reference until the register view has one
locker.Unlock();
fRegisterView->SetCpuState(cpuState);
}
@ -258,6 +288,26 @@ TeamWindow::_HandleThreadStateChanged(thread_id threadID)
}
void
TeamWindow::_HandleCpuStateChanged(thread_id threadID)
{
// We're only interested in the currently selected thread
if (fActiveThread == NULL || threadID != fActiveThread->ID())
return;
AutoLocker<TeamDebugModel> locker(fDebugModel);
CpuState* cpuState = fActiveThread != NULL
? fActiveThread->GetCpuState() : NULL;
Reference<CpuState> reference(cpuState);
// hold a reference until the register view has one
locker.Unlock();
fRegisterView->SetCpuState(cpuState);
}
// #pragma mark - Listener

View File

@ -15,6 +15,7 @@
class BButton;
class BTabView;
class ImageListView;
class RegisterView;
class TeamDebugModel;
@ -53,14 +54,17 @@ private:
void _UpdateRunButtons();
void _HandleThreadStateChanged(thread_id threadID);
void _HandleCpuStateChanged(thread_id threadID);
private:
TeamDebugModel* fDebugModel;
::Thread* fActiveThread;
Listener* fListener;
BTabView* fTabView;
BTabView* fLocalsTabView;
ThreadListView* fThreadListView;
ImageListView* fImageListView;
RegisterView* fRegisterView;
BButton* fRunButton;
BButton* fStepOverButton;
BButton* fStepIntoButton;