From ad99f882d332df8e2ad38587380eaa73f0b63be2 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Sat, 8 Dec 2012 22:30:40 -0500 Subject: [PATCH] Print parameters/local variables if available.. - If debug information is present, then for each stack frame we now also dump all function parameters and local variables and their respective values, as well as their first level of children if applicable. --- .../controllers/DebugReportGenerator.cpp | 137 +++++++++++++++++- .../controllers/DebugReportGenerator.h | 14 ++ 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index 996e67f631..d8a16d7cf8 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -26,7 +26,13 @@ #include "StringUtils.h" #include "Team.h" #include "Thread.h" +#include "Type.h" #include "UiUtils.h" +#include "Value.h" +#include "ValueLoader.h" +#include "ValueLocation.h" +#include "ValueNode.h" +#include "ValueNodeManager.h" DebugReportGenerator::DebugReportGenerator(::Team* team) @@ -34,7 +40,8 @@ DebugReportGenerator::DebugReportGenerator(::Team* team) BLooper("DebugReportGenerator"), fTeam(team), fArchitecture(team->GetArchitecture()), - fTeamDataSem(-1) + fTeamDataSem(-1), + fNodeManager(NULL) { fTeam->AddListener(this); fArchitecture->AcquireReference(); @@ -45,6 +52,8 @@ DebugReportGenerator::~DebugReportGenerator() { fTeam->RemoveListener(this); fArchitecture->ReleaseReference(); + if (fNodeManager != NULL) + fNodeManager->ReleaseReference(); } @@ -55,6 +64,10 @@ DebugReportGenerator::Init() if (fTeamDataSem < B_OK) return fTeamDataSem; + fNodeManager = new(std::nothrow) ValueNodeManager(); + if (fNodeManager == NULL) + return B_NO_MEMORY; + Run(); return B_OK; @@ -285,6 +298,23 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, sizeof(functionName))); _output << data; + if (frame->CountParameters() == 0 + && frame->CountLocalVariables() == 0) { + continue; + } + + _output << "\t\t\tVariables:\n"; + status_t result = fNodeManager->SetStackFrame(thread, frame); + if (result != B_OK) + continue; + + ValueNodeContainer* container = fNodeManager->GetContainer(); + AutoLocker containerLocker(container); + for (int32 i = 0; i < container->CountChildren(); i++) { + ValueNodeChild* child = container->ChildAt(i); + _DumpValueNode(_output, frame, child); + } + _output << "\n"; } _output << "\n\t\tRegisters:\n"; @@ -304,3 +334,108 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, return B_OK; } + + +status_t +DebugReportGenerator::_DumpValueNode(BString& _output, StackFrame* frame, + ValueNodeChild* child, bool recurse) +{ + status_t result = _ResolveLocationIfNeeded(child, frame); + if (result != B_OK) + return result; + + _output << "\t\t\t"; + if (!recurse) + _output << "\t"; + _output << child->Name() << ": "; + + ValueNode* node = child->Node(); + if (node->LocationAndValueResolutionState() == VALUE_NODE_UNRESOLVED) { + if (_ResolveValueIfNeeded(node, frame) == B_OK) { + Value* value = node->GetValue(); + if (value != NULL) { + BString valueData; + value->ToString(valueData); + _output << valueData; + } else + _output << "Unavailable"; + } else + _output << "Unknown"; + } + if (recurse && node->CountChildren() != 0) + _output << " {"; + + _output << "\n"; + + if (recurse) { + if (node->CountChildren() == 0) + return B_OK; + + if (node->CountChildren() == 1 + && node->GetType()->Kind() == TYPE_ADDRESS + && node->ChildAt(0)->GetType()->Kind() == TYPE_COMPOUND) { + // for the case of a pointer to a compound type, + // we want to hide the intervening compound node and print + // the children directly. + status_t result = fNodeManager->AddChildNodes(node->ChildAt(0)); + if (result == B_OK) { + result = _ResolveLocationIfNeeded(node->ChildAt(0), frame); + if (result == B_OK) { + node = node->ChildAt(0)->Node(); + // attempt to resolve the value here since the node's + // representation may requires its value to be resolved + // before its children can be created + result = _ResolveValueIfNeeded(node, frame); + } + } + } + + for (int32 i = 0; i < node->CountChildren(); i++) { + if (fNodeManager->AddChildNodes(node->ChildAt(i)) != B_OK) + continue; + + // don't dump compound nodes since we won't traverse into + // them anyways and their top level node has no interesting + // information. + if (node->ChildAt(i)->GetType()->Kind() != TYPE_COMPOUND) + _DumpValueNode(_output, frame, node->ChildAt(i), false); + } + _output << "\t\t\t}\n"; + } + + return B_OK; +} + + +status_t +DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame) +{ + ValueLocation* location = NULL; + Value* value = NULL; + ValueLoader loader(fTeam->GetArchitecture(), fTeam->GetTeamMemory(), + fTeam->GetTeamTypeInformation(), frame->GetCpuState()); + status_t result = node->ResolvedLocationAndValue(&loader, location, + value); + node->SetLocationAndValue(location, value, result); + if (location != NULL) + location->ReleaseReference(); + if (value != NULL) + value->ReleaseReference(); + + return result; +} + + +status_t +DebugReportGenerator::_ResolveLocationIfNeeded(ValueNodeChild* child, + StackFrame* frame) +{ + ValueLocation* location = NULL; + ValueLoader loader(fTeam->GetArchitecture(), fTeam->GetTeamMemory(), + fTeam->GetTeamTypeInformation(), frame->GetCpuState()); + status_t result = child->ResolveLocation(&loader, location); + child->SetLocation(location, result); + if (location != NULL) + location->ReleaseReference(); + return result; +} diff --git a/src/apps/debugger/controllers/DebugReportGenerator.h b/src/apps/debugger/controllers/DebugReportGenerator.h index 1ea4dff8e0..03d7f5c6db 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.h +++ b/src/apps/debugger/controllers/DebugReportGenerator.h @@ -14,8 +14,13 @@ class entry_ref; class Architecture; class BString; +class StackFrame; class Team; class Thread; +class Value; +class ValueNode; +class ValueNodeChild; +class ValueNodeManager; class DebugReportGenerator : public BLooper, public Team::Listener { @@ -39,11 +44,20 @@ private: status_t _DumpRunningThreads(BString& output); status_t _DumpDebuggedThreadInfo(BString& output, ::Thread* thread); + status_t _DumpValueNode(BString& output, + StackFrame* frame, ValueNodeChild* child, + bool recurse = true); + + status_t _ResolveLocationIfNeeded(ValueNodeChild* child, + StackFrame* frame); + status_t _ResolveValueIfNeeded(ValueNode* node, + StackFrame* frame); private: ::Team* fTeam; Architecture* fArchitecture; sem_id fTeamDataSem; + ValueNodeManager* fNodeManager; }; #endif // DEBUG_REPORT_GENERATOR_H