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.
This commit is contained in:
Rene Gollent 2012-12-18 23:31:08 -05:00
parent 9a4802db55
commit 3e441f885e
2 changed files with 57 additions and 6 deletions

View File

@ -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) {

View File

@ -9,6 +9,7 @@
#include <Looper.h>
#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;
};