diff --git a/src/apps/debugger/TeamDebugger.cpp b/src/apps/debugger/TeamDebugger.cpp index c65ce285ab..4d7d149b8b 100644 --- a/src/apps/debugger/TeamDebugger.cpp +++ b/src/apps/debugger/TeamDebugger.cpp @@ -14,7 +14,6 @@ #include -#include #include #include "debug_utils.h" @@ -468,12 +467,8 @@ TeamDebugger::MessageReceived(BMessage* message) break; } - const char* addressExpression; target_addr_t address; - if (message->FindString("addressExpression", - &addressExpression) == B_OK) { - _HandleInspectAddress(addressExpression, listener); - } else if (message->FindUInt64("address", + if (message->FindUInt64("address", &address) == B_OK) { _HandleInspectAddress(address, listener); } @@ -695,17 +690,6 @@ TeamDebugger::ClearBreakpointRequested(UserBreakpoint* breakpoint) } -void -TeamDebugger::InspectRequested(const char* addressExpression, - TeamMemoryBlock::Listener *listener) -{ - BMessage message(MSG_INSPECT_ADDRESS); - message.AddString("addressExpression", addressExpression); - message.AddPointer("listener", listener); - PostMessage(&message); -} - - void TeamDebugger::InspectRequested(target_addr_t address, TeamMemoryBlock::Listener *listener) @@ -1300,37 +1284,12 @@ TeamDebugger::_HandleClearUserBreakpoint(UserBreakpoint* breakpoint) } -void -TeamDebugger::_HandleInspectAddress(const char* addressExpression, - TeamMemoryBlock::Listener* listener) -{ - TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(%s, %p)\n", - addressExpression, listener); - - ExpressionParser parser; - parser.SetSupportHexInput(true); - target_addr_t address = 0LL; - try { - address = parser.EvaluateToInt64(addressExpression); - } catch(ParseException parseError) { - _NotifyUser("Inspect Address", "Failed to parse address: %s", - parseError.message.String()); - return; - } catch(...) { - _NotifyUser("Inspect Address", "Unknown error while parsing address"); - return; - } - - _HandleInspectAddress(address, listener); -} - - void TeamDebugger::_HandleInspectAddress(target_addr_t address, TeamMemoryBlock::Listener* listener) { TRACE_CONTROL("TeamDebugger::_HandleInspectAddress(" B_PRIx64 ", %p)\n", - addressExpression, listener); + address, listener); TeamMemoryBlock* memoryBlock = fMemoryBlockManager ->GetMemoryBlock(address); diff --git a/src/apps/debugger/TeamDebugger.h b/src/apps/debugger/TeamDebugger.h index 6b19e06bd9..bd1cf5d267 100644 --- a/src/apps/debugger/TeamDebugger.h +++ b/src/apps/debugger/TeamDebugger.h @@ -68,8 +68,6 @@ private: UserBreakpoint* breakpoint); virtual void InspectRequested(target_addr_t address, TeamMemoryBlock::Listener* listener); - virtual void InspectRequested(const char* addressExpression, - TeamMemoryBlock::Listener* listener); virtual bool UserInterfaceQuitRequested(); // JobListener @@ -126,9 +124,6 @@ private: void _HandleInspectAddress( target_addr_t address, TeamMemoryBlock::Listener* listener); - void _HandleInspectAddress( - const char* addressExpression, - TeamMemoryBlock::Listener* listener); ThreadHandler* _GetThreadHandler(thread_id threadID); diff --git a/src/apps/debugger/model/TeamMemoryBlock.cpp b/src/apps/debugger/model/TeamMemoryBlock.cpp index 64347d55c7..2bae7c303d 100644 --- a/src/apps/debugger/model/TeamMemoryBlock.cpp +++ b/src/apps/debugger/model/TeamMemoryBlock.cpp @@ -77,6 +77,14 @@ TeamMemoryBlock::Invalidate() } +bool +TeamMemoryBlock::Contains(target_addr_t address) const +{ + return fValid && address >= fBaseAddress + && address < (fBaseAddress + sizeof(fData)); +} + + void TeamMemoryBlock::SetWritable(bool writable) { diff --git a/src/apps/debugger/model/TeamMemoryBlock.h b/src/apps/debugger/model/TeamMemoryBlock.h index 893eeb0c05..c02bd67069 100644 --- a/src/apps/debugger/model/TeamMemoryBlock.h +++ b/src/apps/debugger/model/TeamMemoryBlock.h @@ -39,6 +39,7 @@ public: target_addr_t BaseAddress() const { return fBaseAddress; }; uint8* Data() { return fData; }; size_t Size() const { return sizeof(fData); }; + bool Contains(target_addr_t address) const; bool IsWritable() const { return fWritable; } void SetWritable(bool writable); diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index ced05cce32..c5ab2688bf 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -86,9 +86,6 @@ public: virtual void InspectRequested( target_addr_t address, TeamMemoryBlock::Listener* listener) = 0; - virtual void InspectRequested( - const char* addressExpression, - TeamMemoryBlock::Listener* listener) = 0; virtual bool UserInterfaceQuitRequested() = 0; }; 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 292777acd3..94158cfee3 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.cpp @@ -5,13 +5,16 @@ #include "InspectorWindow.h" +#include + +#include #include #include #include #include #include -#include +#include #include "MemoryView.h" #include "MessageCodes.h" @@ -20,9 +23,11 @@ InspectorWindow::InspectorWindow(UserInterfaceListener* listener) : - BWindow(BRect(100, 100, 500, 250), "Inspector", B_DOCUMENT_WINDOW, + BWindow(BRect(100, 100, 500, 250), "Inspector", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS), - fListener(listener) + fListener(listener), + fMemoryView(NULL), + fCurrentBlock(NULL) { } @@ -51,13 +56,18 @@ InspectorWindow::Create(UserInterfaceListener* listener) void InspectorWindow::_Init() { + BScrollView* scrollView; + BLayoutBuilder::Group<>(this, B_VERTICAL) .Add(fAddressInput = new BTextControl("addrInput", "Target Address:", "", new BMessage(MSG_INSPECT_ADDRESS))) - .Add(fMemoryView = new MemoryView(NULL, NULL)) + .Add(scrollView = new BScrollView("memory scroll", + NULL, 0, false, true), 3.0f) .End(); + scrollView->SetTarget(fMemoryView = MemoryView::Create()); + fAddressInput->SetTarget(this); } @@ -69,8 +79,43 @@ InspectorWindow::MessageReceived(BMessage* msg) switch (msg->what) { case MSG_INSPECT_ADDRESS: { + ExpressionParser parser; + parser.SetSupportHexInput(true); + target_addr_t address = 0; const char* addressExpression = fAddressInput->Text(); - fListener->InspectRequested(addressExpression, this); + BString errorMessage; + try { + address = parser.EvaluateToInt64(addressExpression); + } 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 { + if (fCurrentBlock != NULL + && !fCurrentBlock->Contains(address)) { + fCurrentBlock->ReleaseReference(); + fCurrentBlock = NULL; + } + + if (fCurrentBlock == NULL) + fListener->InspectRequested(address, this); + else + fMemoryView->SetTargetAddress(fCurrentBlock, address); + + fCurrentAddress = address; + BString computedAddress; + computedAddress.SetToFormat("0x%" B_PRIx64, address); + fAddressInput->SetText(computedAddress.String()); + } break; } } @@ -88,5 +133,7 @@ InspectorWindow::QuitRequested() void InspectorWindow::MemoryBlockRetrieved(TeamMemoryBlock* block) { - // TODO: implement + fCurrentBlock = block; + fMemoryView->SetTargetAddress(block, fCurrentAddress); + } 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 d4693b8011..867e4f740a 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h +++ b/src/apps/debugger/user_interface/gui/inspector_window/InspectorWindow.h @@ -40,6 +40,8 @@ private: UserInterfaceListener* fListener; BTextControl* fAddressInput; MemoryView* fMemoryView; + TeamMemoryBlock* fCurrentBlock; + target_addr_t fCurrentAddress; }; #endif // INSPECTOR_WINDOW_H diff --git a/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp index 8733732580..49adf89d24 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp +++ b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.cpp @@ -6,26 +6,40 @@ #include "MemoryView.h" +#include -MemoryView::MemoryView(Team* team, Listener* listener) +#include +#include +#include + +#include "TeamMemoryBlock.h" + + +enum { + MSG_TARGET_ADDRESS_CHANGED = 'mtac' +}; + + +MemoryView::MemoryView() : - BView("memoryView", B_WILL_DRAW | B_SUBPIXEL_PRECISE), - fTeam(team), - fListener(listener) + BView("memoryView", B_WILL_DRAW | B_FRAME_EVENTS | B_SUBPIXEL_PRECISE), + fTargetBlock(NULL), + fTargetAddress(0) { } MemoryView::~MemoryView() { - UnsetListener(); + if (fTargetBlock != NULL) + fTargetBlock->ReleaseReference(); } /*static */ MemoryView* -MemoryView::Create(Team* team, Listener* listener) +MemoryView::Create() { - MemoryView* self = new MemoryView(team, listener); + MemoryView* self = new MemoryView(); try { self->_Init(); @@ -39,24 +53,15 @@ MemoryView::Create(Team* team, Listener* listener) void -MemoryView::UnsetListener() -{ - fListener = NULL; -} - - -void -MemoryView::SetTargetAddress(target_addr_t address) +MemoryView::SetTargetAddress(TeamMemoryBlock* block, target_addr_t address) { fTargetAddress = address; - Invalidate(); -} + if (fTargetBlock != NULL) + fTargetBlock->ReleaseReference(); - -void -MemoryView::TargetAddressChanged(target_addr_t address) -{ - SetTargetAddress(address); + fTargetBlock = block; + fTargetBlock->AcquireReference(); + BMessenger(this).SendMessage(MSG_TARGET_ADDRESS_CHANGED); } @@ -64,6 +69,21 @@ void MemoryView::TargetedByScrollView(BScrollView* scrollView) { BView::TargetedByScrollView(scrollView); + scrollView->ScrollBar(B_VERTICAL)->SetRange(0.0, 0.0); +} + + +void +MemoryView::AttachedToWindow() +{ + BView::AttachedToWindow(); + SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR)); + SetFont(be_fixed_font); + fCharWidth = be_fixed_font->StringWidth("a"); + font_height fontHeight; + be_fixed_font->GetHeight(&fontHeight); + fLineHeight = fontHeight.ascent + fontHeight.descent + + fontHeight.leading; } @@ -71,6 +91,48 @@ void MemoryView::Draw(BRect rect) { BView::Draw(rect); + + StrokeLine(BPoint(9 * fCharWidth, rect.top), + BPoint(9 * fCharWidth, rect.bottom)); + + if (fTargetBlock == NULL) + return; + + int32 startLine = (int32)rect.top / fLineHeight; + int32 bytesPerLine = fNybblesPerLine / 2; + int32 startByte = bytesPerLine * startLine; + target_addr_t currentAddress = fTargetBlock->BaseAddress() + startByte; + target_addr_t maxAddress = fTargetBlock->BaseAddress() + + fTargetBlock->Size(); + BPoint drawPoint(1.0, rect.top); + BString tempData; + int32 currentBytesPerLine = bytesPerLine; + for (int32 i = startLine; drawPoint.y < rect.bottom + && currentAddress < maxAddress; i++, drawPoint.y += fLineHeight) { + drawPoint.x = 1.0; + tempData.SetToFormat("%" B_PRIx32 " ", + currentAddress); + DrawString(tempData.String(), drawPoint); + drawPoint.x += fCharWidth * 10; + if (currentAddress + bytesPerLine > maxAddress) + currentBytesPerLine = maxAddress - currentAddress; + for (int32 j = 0; j < currentBytesPerLine; j += 2) { + tempData.SetToFormat("%04" B_PRIx16 " ", + *((uint16*)&fTargetBlock->Data()[i * bytesPerLine + j])); + DrawString(tempData.String(), drawPoint); + drawPoint.x += fCharWidth * 5; + } + currentAddress += bytesPerLine; + } +} + + +void +MemoryView::FrameResized(float width, float height) +{ + BView::FrameResized(width, height); + _RecalcScrollBars(); + Invalidate(); } @@ -78,12 +140,21 @@ void MemoryView::MessageReceived(BMessage* message) { switch(message->what) { + case MSG_TARGET_ADDRESS_CHANGED: + { + _RecalcScrollBars(); + Invalidate(); + break; + } default: + { BView::MessageReceived(message); break; + } } } + void MemoryView::_Init() { @@ -91,6 +162,25 @@ MemoryView::_Init() } -MemoryView::Listener::~Listener() +void +MemoryView::_RecalcScrollBars() { + float max = 0.0; + BScrollBar *scrollBar = ScrollBar(B_VERTICAL); + if (fTargetBlock != NULL) { + BRect bounds = Bounds(); + fNybblesPerLine = bounds.Width() / fCharWidth; + // we allocate 8 characters for the starting address of the current + // line plus some spacing to separate that from the data + fNybblesPerLine -= 10; + // also allocate a space between each 16-bit grouping + fNybblesPerLine -= (fNybblesPerLine / 4); + fNybblesPerLine &= ~3; + int32 lineCount = ceil(2 * fTargetBlock->Size() / fNybblesPerLine); + float totalHeight = lineCount * fLineHeight; + max = totalHeight - bounds.Height(); + scrollBar->SetProportion(bounds.Height() / totalHeight); + scrollBar->SetSteps(fLineHeight, bounds.Height()); + } + scrollBar->SetRange(0.0, max); } diff --git a/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.h b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.h index 0fb150dd54..9ae562c923 100644 --- a/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.h +++ b/src/apps/debugger/user_interface/gui/inspector_window/MemoryView.h @@ -9,49 +9,43 @@ #include -#include "Team.h" +#include "Types.h" + + +class TeamMemoryBlock; class MemoryView : public BView { public: - class Listener; - -public: - MemoryView( - Team* team, Listener* listener); + MemoryView(); virtual ~MemoryView(); - static MemoryView* Create(Team* team, Listener* listener); + static MemoryView* Create(); // throws - void UnsetListener(); - - void SetTargetAddress(target_addr_t address); + void SetTargetAddress(TeamMemoryBlock* block, + target_addr_t address); void TargetAddressChanged(target_addr_t address); + virtual void TargetedByScrollView(BScrollView* scrollView); + virtual void AttachedToWindow(); virtual void Draw(BRect rect); + virtual void FrameResized(float width, float height); virtual void MessageReceived(BMessage* message); private: void _Init(); + void _RecalcScrollBars(); private: - Team* fTeam; + TeamMemoryBlock* fTargetBlock; target_addr_t fTargetAddress; - Listener* fListener; + float fCharWidth; + float fLineHeight; + int32 fNybblesPerLine; }; - -class MemoryView::Listener { -public: - virtual ~Listener(); - - virtual void SetTargetAddressRequested( - target_addr_t address) = 0; -}; - - #endif // MEMORY_VIEW_H