status_t DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, ::Thread* thread) { AutoLocker< ::Team> locker; if (thread->State() != THREAD_STATE_STOPPED) return B_OK; StackTrace* trace = NULL; for (;;) { trace = thread->GetStackTrace(); if (trace != NULL) break; locker.Unlock(); status_t result = acquire_sem(fTeamDataSem); if (result != B_OK) return result; locker.Lock(); } _output << "\t\tFrame\t\tIP\t\t\tFunction Name\n"; _output << "\t\t-----------------------------------------------\n"; BString data; for (int32 i = 0; StackFrame* frame = trace->FrameAt(i); i++) { char functionName[512]; data.SetToFormat("\t\t%#08" B_PRIx64 "\t%#08" B_PRIx64 "\t%s\n", frame->FrameAddress(), frame->InstructionPointer(), UiUtils::FunctionNameForFrame(frame, functionName, sizeof(functionName))); _output << data; } _output << "\n\t\tRegisters:\n"; 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); char buffer[64]; data.SetToFormat("\t\t\t%5s:\t%s\n", reg->Name(), UiUtils::VariantToString(value, buffer, sizeof(buffer))); _output << data; } return B_OK; }
status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, bool getFullFrameInfo, ReturnValueInfoList* returnValueInfos, StackFrame*& _frame, CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( functionInstance->GetFunctionDebugInfo()); FunctionID* functionID = functionInstance->GetFunctionID(); BReference<FunctionID> functionIDReference; if (functionID != NULL) functionIDReference.SetTo(functionID, true); DIESubprogram* entry = function != NULL ? function->SubprogramEntry() : NULL; TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, " "function: %s\n", entry, functionID->FunctionName().String()); int32 registerCount = fArchitecture->CountRegisters(); const Register* registers = fArchitecture->Registers(); // get the DWARF <-> architecture register maps RegisterMap* toDwarfMap; RegisterMap* fromDwarfMap; status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, &fromDwarfMap); if (error != B_OK) return error; BReference<RegisterMap> toDwarfMapReference(toDwarfMap, true); BReference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); // create a clean CPU state for the previous frame CpuState* previousCpuState; error = fArchitecture->CreateCpuState(previousCpuState); if (error != B_OK) return error; BReference<CpuState> previousCpuStateReference(previousCpuState, true); // create the target interfaces UnwindTargetInterface* inputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fDebuggerInterface); if (inputInterface == NULL) return B_NO_MEMORY; BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface, true); UnwindTargetInterface* outputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fDebuggerInterface); if (outputInterface == NULL) return B_NO_MEMORY; BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface, true); // do the unwinding target_addr_t instructionPointer = cpuState->InstructionPointer() - fRelocationDelta; target_addr_t framePointer; CompilationUnit* unit = function != NULL ? function->GetCompilationUnit() : NULL; error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry, instructionPointer, inputInterface, outputInterface, framePointer); if (error != B_OK) { TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); return B_UNSUPPORTED; } TRACE_CFI_ONLY( TRACE_CFI("unwound registers:\n"); for (int32 i = 0; i < registerCount; i++) { const Register* reg = registers + i; BVariant value; if (previousCpuState->GetRegisterValue(reg, value)) { TRACE_CFI(" %3s: %#" B_PRIx64 "\n", reg->Name(), value.ToUInt64()); } else TRACE_CFI(" %3s: undefined\n", reg->Name()); } )
status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, StackFrame*& _previousFrame, CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( functionInstance->GetFunctionDebugInfo()); if (function == NULL) return B_BAD_VALUE; TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->SubprogramEntry()); int32 registerCount = fArchitecture->CountRegisters(); const Register* registers = fArchitecture->Registers(); // get the DWARF <-> architecture register maps RegisterMap* toDwarfMap; RegisterMap* fromDwarfMap; status_t error = fArchitecture->GetDwarfRegisterMaps(&toDwarfMap, &fromDwarfMap); if (error != B_OK) return error; Reference<RegisterMap> toDwarfMapReference(toDwarfMap, true); Reference<RegisterMap> fromDwarfMapReference(fromDwarfMap, true); // create a clean CPU state for the previous frame CpuState* previousCpuState; error = fArchitecture->CreateCpuState(previousCpuState); if (error != B_OK) return error; Reference<CpuState> previousCpuStateReference(previousCpuState, true); // create the target interfaces UnwindTargetInterface* inputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory); if (inputInterface == NULL) return B_NO_MEMORY; Reference<UnwindTargetInterface> inputInterfaceReference(inputInterface, true); UnwindTargetInterface* outputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory); if (outputInterface == NULL) return B_NO_MEMORY; Reference<UnwindTargetInterface> outputInterfaceReference(outputInterface, true); // do the unwinding target_addr_t instructionPointer = cpuState->InstructionPointer() - fRelocationDelta; target_addr_t framePointer; CompilationUnit* unit = function->GetCompilationUnit(); error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(), instructionPointer, inputInterface, outputInterface, framePointer); if (error != B_OK) { TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); return B_UNSUPPORTED; } TRACE_CFI_ONLY( TRACE_CFI("unwound registers:\n"); for (int32 i = 0; i < registerCount; i++) { const Register* reg = registers + i; BVariant value; if (previousCpuState->GetRegisterValue(reg, value)) TRACE_CFI(" %3s: %#lx\n", reg->Name(), value.ToUInt32()); else TRACE_CFI(" %3s: undefined\n", reg->Name()); } )
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; }