void VariablesView::VariableTableModel::ValueNodeChildrenCreated( ValueNode* valueNode) { if (fContainer == NULL) return; AutoLocker<ValueNodeContainer> containerLocker(fContainer); // check whether we know the node ValueNodeChild* nodeChild = valueNode->NodeChild(); if (nodeChild == NULL) return; ModelNode* modelNode = fNodeTable.Lookup(nodeChild); if (modelNode == NULL) return; // Iterate through the children and create model nodes for the ones we // don't know yet. int32 childCount = valueNode->CountChildren(); for (int32 i = 0; i < childCount; i++) { ValueNodeChild* child = valueNode->ChildAt(i); if (fNodeTable.Lookup(child) == NULL) { _AddNode(modelNode->GetVariable(), modelNode, child, child->IsInternal()); } } }
void VariablesView::_RequestNodeValue(ModelNode* node) { // get the node child and its container ValueNodeChild* nodeChild = node->NodeChild(); ValueNodeContainer* container = nodeChild->Container(); BReference<ValueNodeContainer> containerReference(container); AutoLocker<ValueNodeContainer> containerLocker(container); if (container == NULL || nodeChild->Container() != container) return; // get the value node and check whether its value has not yet been resolved ValueNode* valueNode = nodeChild->Node(); if (valueNode == NULL || valueNode->LocationAndValueResolutionState() != VALUE_NODE_UNRESOLVED) { return; } BReference<ValueNode> valueNodeReference(valueNode); containerLocker.Unlock(); // request resolution of the value fListener->ValueNodeValueRequested(fStackFrame->GetCpuState(), container, valueNode); }
status_t DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth) { status_t result = B_OK; if (node->LocationAndValueResolutionState() == VALUE_NODE_UNRESOLVED) { fWaitingNode = node; fListener->ValueNodeValueRequested(frame->GetCpuState(), fNodeManager->GetContainer(), node); do { result = acquire_sem(fTeamDataSem); } while (result == B_INTERRUPTED); } if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) { AutoLocker<ValueNodeContainer> containerLocker( fNodeManager->GetContainer()); for (int32 i = 0; i < node->CountChildren(); i++) { ValueNodeChild* child = node->ChildAt(i); containerLocker.Unlock(); result = fNodeManager->AddChildNodes(child); if (result != B_OK) continue; // since in the case of a pointer to a compound we hide // the intervening compound, don't consider the hidden node // a level for the purposes of depth traversal if (node->GetType()->ResolveRawType(false)->Kind() == TYPE_ADDRESS && child->GetType()->ResolveRawType(false)->Kind() == TYPE_COMPOUND) { _ResolveValueIfNeeded(child->Node(), frame, maxDepth); } else _ResolveValueIfNeeded(child->Node(), frame, maxDepth - 1); containerLocker.Lock(); } } return result; }
status_t ResolveValueNodeValueJob::_ResolveNodeValue() { // get the node child and parent node AutoLocker<ValueNodeContainer> containerLocker(fContainer); ValueNodeChild* nodeChild = fValueNode->NodeChild(); BReference<ValueNodeChild> nodeChildReference(nodeChild); ValueNode* parentNode = nodeChild->Parent(); BReference<ValueNode> parentNodeReference(parentNode); // Check whether the node child location has been resolved already // (successfully). status_t nodeChildResolutionState = nodeChild->LocationResolutionState(); bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED; if (nodeChildDone && nodeChildResolutionState != B_OK) return nodeChildResolutionState; // If the child node location has not been resolved yet, check whether the // parent node location and value have been resolved already (successfully). bool parentDone = true; if (!nodeChildDone && parentNode != NULL) { status_t parentResolutionState = parentNode->LocationAndValueResolutionState(); parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED; if (parentDone && parentResolutionState != B_OK) return parentResolutionState; } containerLocker.Unlock(); // resolve the parent node location and value, if necessary if (!parentDone) { status_t error = _ResolveParentNodeValue(parentNode); if (error != B_OK) { TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " "node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n", fValueNode, fValueNode->Name().String(), parentNode); return error; } } // resolve the node child location, if necessary if (!nodeChildDone) { status_t error = _ResolveNodeChildLocation(nodeChild); if (error != B_OK) { TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " "node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n", fValueNode, fValueNode->Name().String(), nodeChild); return error; } } // resolve the node location and value ValueLoader valueLoader(fArchitecture, fDebuggerInterface, fTypeInformation, fCpuState); ValueLocation* location; Value* value; status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader, location, value); if (error != B_OK) { TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value " "node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() " "failed\n", fValueNode, fValueNode->Name().String()); return error; } BReference<ValueLocation> locationReference(location, true); BReference<Value> valueReference(value, true); // set location and value on the node containerLocker.Lock(); status_t nodeResolutionState = fValueNode->LocationAndValueResolutionState(); if (nodeResolutionState != VALUE_NODE_UNRESOLVED) return nodeResolutionState; fValueNode->SetLocationAndValue(location, value, B_OK); containerLocker.Unlock(); return B_OK; }
status_t DebugReportGenerator::_DumpDebuggedThreadInfo(BFile& _output, ::Thread* thread) { AutoLocker< ::Team> locker; if (thread->State() != THREAD_STATE_STOPPED) return B_OK; status_t error; StackTrace* trace = NULL; for (;;) { trace = thread->GetStackTrace(); if (trace != NULL) break; locker.Unlock(); fTraceWaitingThread = thread; do { error = acquire_sem(fTeamDataSem); } while (error == B_INTERRUPTED); if (error != B_OK) break; locker.Lock(); } BString data("\t\tFrame\t\tIP\t\t\tFunction Name\n"); WRITE_AND_CHECK(_output, data); data = "\t\t-----------------------------------------------\n"; WRITE_AND_CHECK(_output, data); for (int32 i = 0; StackFrame* frame = trace->FrameAt(i); i++) { char functionName[512]; BString sourcePath; target_addr_t ip = frame->InstructionPointer(); FunctionInstance* functionInstance; Statement* statement; if (fTeam->GetStatementAtAddress(ip, functionInstance, statement) == B_OK) { BReference<Statement> statementReference(statement, true); int32 line = statement->StartSourceLocation().Line(); LocatableFile* sourceFile = functionInstance->GetFunction() ->SourceFile(); if (sourceFile != NULL) { sourceFile->GetPath(sourcePath); sourcePath.SetToFormat("(%s:%" B_PRId32 ")", sourcePath.String(), line); } } data.SetToFormat("\t\t%#08" B_PRIx64 "\t%#08" B_PRIx64 "\t%s %s\n", frame->FrameAddress(), ip, UiUtils::FunctionNameForFrame( frame, functionName, sizeof(functionName)), sourcePath.String()); WRITE_AND_CHECK(_output, data); // only dump the topmost frame if (i == 0) { locker.Unlock(); error = _DumpFunctionDisassembly(_output, frame->InstructionPointer()); if (error != B_OK) return error; error = _DumpStackFrameMemory(_output, thread->GetCpuState(), frame->FrameAddress(), thread->GetTeam()->GetArchitecture() ->StackGrowthDirection()); if (error != B_OK) return error; locker.Lock(); } if (frame->CountParameters() == 0 && frame->CountLocalVariables() == 0) continue; data = "\t\t\tVariables:\n"; WRITE_AND_CHECK(_output, data); error = fNodeManager->SetStackFrame(thread, frame); if (error != B_OK) continue; ValueNodeContainer* container = fNodeManager->GetContainer(); AutoLocker<ValueNodeContainer> containerLocker(container); for (int32 i = 0; i < container->CountChildren(); i++) { data.Truncate(0L); ValueNodeChild* child = container->ChildAt(i); containerLocker.Unlock(); _ResolveValueIfNeeded(child->Node(), frame, 1); containerLocker.Lock(); UiUtils::PrintValueNodeGraph(data, child, 3, 1); WRITE_AND_CHECK(_output, data); } data = "\n"; WRITE_AND_CHECK(_output, data); } data = "\n\t\tRegisters:\n"; WRITE_AND_CHECK(_output, data); CpuState* state = thread->GetCpuState(); BVariant value; const Register* reg = NULL; for (int32 i = 0; i < fArchitecture->CountRegisters(); i++) { reg = fArchitecture->Registers() + i; state->GetRegisterValue(reg, value); if (reg->Format() == REGISTER_FORMAT_SIMD) { data.SetToFormat("\t\t\t%5s:\t%s\n", reg->Name(), UiUtils::FormatSIMDValue(value, reg->BitSize(), SIMD_RENDER_FORMAT_INT16, data).String()); } else { char buffer[64]; data.SetToFormat("\t\t\t%5s:\t%s\n", reg->Name(), UiUtils::VariantToString(value, buffer, sizeof(buffer))); } WRITE_AND_CHECK(_output, data); } return B_OK; }