diff --git a/src/apps/debugger/gui/team_window/RegisterView.cpp b/src/apps/debugger/gui/team_window/RegisterView.cpp new file mode 100644 index 0000000000..be2fc72cae --- /dev/null +++ b/src/apps/debugger/gui/team_window/RegisterView.cpp @@ -0,0 +1,248 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "RegisterView.h" + +#include + +#include + +#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); +} diff --git a/src/apps/debugger/gui/team_window/RegisterView.h b/src/apps/debugger/gui/team_window/RegisterView.h new file mode 100644 index 0000000000..c570a5ef3c --- /dev/null +++ b/src/apps/debugger/gui/team_window/RegisterView.h @@ -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 + +#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 diff --git a/src/apps/debugger/gui/team_window/TeamWindow.cpp b/src/apps/debugger/gui/team_window/TeamWindow.cpp index ff8f626a28..a4e68fa4b9 100644 --- a/src/apps/debugger/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/gui/team_window/TeamWindow.cpp @@ -16,8 +16,10 @@ #include +#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 locker(fDebugModel); _UpdateRunButtons(); + + CpuState* cpuState = fActiveThread != NULL + ? fActiveThread->GetCpuState() : NULL; + Reference 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 locker(fDebugModel); + + CpuState* cpuState = fActiveThread != NULL + ? fActiveThread->GetCpuState() : NULL; + Reference reference(cpuState); + // hold a reference until the register view has one + + locker.Unlock(); + + fRegisterView->SetCpuState(cpuState); +} + + // #pragma mark - Listener diff --git a/src/apps/debugger/gui/team_window/TeamWindow.h b/src/apps/debugger/gui/team_window/TeamWindow.h index ea1661c829..53c2fb664f 100644 --- a/src/apps/debugger/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/gui/team_window/TeamWindow.h @@ -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;