From 3e441f885e85e7f22c41a0e52100d0569bd6874a Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 18 Dec 2012 23:31:08 -0500 Subject: [PATCH] Add frame dumping capabilities to report generator. - If the top frame of a stopped thread has no arguments or variables available, dump the memory block to which the stack frame belongs, starting at the current stack pointer and extending to the end of the block. --- .../controllers/DebugReportGenerator.cpp | 42 ++++++++++++++++++- .../controllers/DebugReportGenerator.h | 21 +++++++--- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index e37ff70840..4041bfe369 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -46,6 +46,7 @@ DebugReportGenerator::DebugReportGenerator(::Team* team, fNodeManager(NULL), fListener(listener), fWaitingNode(NULL), + fCurrentBlock(NULL), fTraceWaitingThread(NULL) { fTeam->AddListener(this); @@ -61,6 +62,9 @@ DebugReportGenerator::~DebugReportGenerator() fNodeManager->RemoveListener(this); fNodeManager->ReleaseReference(); } + + if (fCurrentBlock != NULL) + fCurrentBlock->ReleaseReference(); } @@ -161,6 +165,19 @@ DebugReportGenerator::ThreadStackTraceChanged(const ::Team::ThreadEvent& event) } +void +DebugReportGenerator::MemoryBlockRetrieved(TeamMemoryBlock* block) +{ + if (fCurrentBlock != NULL) { + fCurrentBlock->ReleaseReference(); + fCurrentBlock = NULL; + } + + fCurrentBlock = block; + release_sem(fTeamDataSem); +} + + void DebugReportGenerator::ValueNodeValueChanged(ValueNode* node) { @@ -323,6 +340,9 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, _output << data; if (frame->CountParameters() == 0 && frame->CountLocalVariables() == 0) { + // only dump the topmost frame + if (i == 0) + _DumpStackFrameMemory(_output, thread->GetCpuState()); continue; } @@ -362,6 +382,24 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, } +void +DebugReportGenerator::_DumpStackFrameMemory(BString& _output, + CpuState* state) +{ + target_addr_t address = state->StackPointer(); + if (fCurrentBlock == NULL || !fCurrentBlock->Contains(address)) { + fListener->InspectRequested(address, this); + status_t result = B_OK; + do { + result = acquire_sem(fTeamDataSem); + } while (result == B_INTERRUPTED); + } + _output << "\t\t\tFrame memory:\n"; + UiUtils::DumpMemory(_output, 3, fCurrentBlock, address, 1, 16, + fCurrentBlock->BaseAddress() + fCurrentBlock->Size() - address); +} + + status_t DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth) @@ -371,7 +409,9 @@ DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, fWaitingNode = node; fListener->ValueNodeValueRequested(frame->GetCpuState(), fNodeManager->GetContainer(), node); - result = acquire_sem(fTeamDataSem); + do { + result = acquire_sem(fTeamDataSem); + } while (result == B_INTERRUPTED); } if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) { diff --git a/src/apps/debugger/controllers/DebugReportGenerator.h b/src/apps/debugger/controllers/DebugReportGenerator.h index 01ae75ece0..56bf8a4a7c 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.h +++ b/src/apps/debugger/controllers/DebugReportGenerator.h @@ -9,6 +9,7 @@ #include #include "Team.h" +#include "TeamMemoryBlock.h" #include "ValueNodeContainer.h" @@ -26,7 +27,7 @@ class ValueNodeManager; class DebugReportGenerator : public BLooper, private Team::Listener, - private ValueNodeContainer::Listener { + private TeamMemoryBlock::Listener, private ValueNodeContainer::Listener { public: DebugReportGenerator(::Team* team, UserInterfaceListener* listener); @@ -39,18 +40,27 @@ public: virtual void MessageReceived(BMessage* message); +private: + // Team::Listener virtual void ThreadStackTraceChanged( const Team::ThreadEvent& event); + // TeamMemoryBlock::Listener + virtual void MemoryBlockRetrieved(TeamMemoryBlock* block); + + // ValueNodeContainer::Listener virtual void ValueNodeValueChanged(ValueNode* node); + private: status_t _GenerateReport(const entry_ref& outputPath); - status_t _GenerateReportHeader(BString& output); - status_t _DumpLoadedImages(BString& output); - status_t _DumpRunningThreads(BString& output); - status_t _DumpDebuggedThreadInfo(BString& output, + status_t _GenerateReportHeader(BString& _output); + status_t _DumpLoadedImages(BString& _output); + status_t _DumpRunningThreads(BString& _output); + status_t _DumpDebuggedThreadInfo(BString& _output, ::Thread* thread); + void _DumpStackFrameMemory(BString& _output, + CpuState* state); status_t _ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth); @@ -62,6 +72,7 @@ private: ValueNodeManager* fNodeManager; UserInterfaceListener* fListener; ValueNode* fWaitingNode; + TeamMemoryBlock* fCurrentBlock; ::Thread* fTraceWaitingThread; };