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.
This commit is contained in:
Rene Gollent 2012-12-08 22:30:40 -05:00
parent 84a00bf887
commit ad99f882d3
2 changed files with 150 additions and 1 deletions

View File

@ -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<ValueNodeContainer> 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;
}

View File

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