void VariablesView::_RestoreViewState() { if (fPreviousViewState != NULL) { fPreviousViewState->ReleaseReference(); fPreviousViewState = NULL; } if (fThread == NULL || fStackFrame == NULL || fStackFrame->Function() == NULL) { return; } // get the function ID FunctionID* functionID = fStackFrame->Function()->GetFunctionID(); if (functionID == NULL) return; BReference<FunctionID> functionIDReference(functionID, true); // get the previous view state VariablesViewState* viewState = fViewStateHistory->GetState(fThread->ID(), functionID); if (viewState == NULL) return; // apply the view state TreeTablePath path; _ApplyViewStateDescendentNodeInfos(viewState, fVariableTableModel->Root(), path); }
void VariablesView::_SaveViewState() const { if (fThread == NULL || fStackFrame == NULL || fStackFrame->Function() == NULL) { return; } // get the function ID FunctionID* functionID = fStackFrame->Function()->GetFunctionID(); if (functionID == NULL) return; BReference<FunctionID> functionIDReference(functionID, true); // create an empty view state VariablesViewState* viewState = new(std::nothrow) VariablesViewState; if (viewState == NULL) return; BReference<VariablesViewState> viewStateReference(viewState, true); if (viewState->Init() != B_OK) return; // populate it TreeTablePath path; if (_AddViewStateDescendentNodeInfos(viewState, fVariableTableModel->Root(), path) != B_OK) { return; } // TODO: Add values! // add the view state to the history fViewStateHistory->SetState(fThread->ID(), functionID, viewState); }
status_t DwarfImageDebugInfo::CreateFrame(Image* image, FunctionInstance* functionInstance, CpuState* cpuState, StackFrame*& _frame, CpuState*& _previousCpuState) { DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( functionInstance->GetFunctionDebugInfo()); if (function == NULL) return B_BAD_VALUE; FunctionID* functionID = functionInstance->GetFunctionID(); if (functionID == NULL) return B_NO_MEMORY; BReference<FunctionID> functionIDReference(functionID, true); TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, " "function: %s\n", function->SubprogramEntry(), 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, fTeamMemory); if (inputInterface == NULL) return B_NO_MEMORY; BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface, true); UnwindTargetInterface* outputInterface = new(std::nothrow) UnwindTargetInterface(registers, registerCount, fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory); 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->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()); } )
void TeamDebugger::_HandleSetUserBreakpoint(target_addr_t address, bool enabled) { TRACE_CONTROL("TeamDebugger::_HandleSetUserBreakpoint(%#llx, %d)\n", address, enabled); // check whether there already is a breakpoint AutoLocker< ::Team> locker(fTeam); Breakpoint* breakpoint = fTeam->BreakpointAtAddress(address); UserBreakpoint* userBreakpoint = NULL; if (breakpoint != NULL && breakpoint->FirstUserBreakpoint() != NULL) userBreakpoint = breakpoint->FirstUserBreakpoint()->GetUserBreakpoint(); BReference<UserBreakpoint> userBreakpointReference(userBreakpoint); if (userBreakpoint == NULL) { TRACE_CONTROL(" no breakpoint yet\n"); // get the function at the address Image* image = fTeam->ImageByAddress(address); TRACE_CONTROL(" image: %p\n", image); if (image == NULL) return; ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo(); TRACE_CONTROL(" image debug info: %p\n", imageDebugInfo); if (imageDebugInfo == NULL) return; // TODO: Handle this case by loading the debug info, if possible! FunctionInstance* functionInstance = imageDebugInfo->FunctionAtAddress(address); TRACE_CONTROL(" function instance: %p\n", functionInstance); if (functionInstance == NULL) return; Function* function = functionInstance->GetFunction(); TRACE_CONTROL(" function: %p\n", function); // get the source location for the address FunctionDebugInfo* functionDebugInfo = functionInstance->GetFunctionDebugInfo(); SourceLocation sourceLocation; Statement* breakpointStatement = NULL; if (functionDebugInfo->GetSpecificImageDebugInfo()->GetStatement( functionDebugInfo, address, breakpointStatement) != B_OK) { return; } sourceLocation = breakpointStatement->StartSourceLocation(); breakpointStatement->ReleaseReference(); target_addr_t relativeAddress = address - functionInstance->Address(); TRACE_CONTROL(" relative address: %#llx, source location: " "(%ld, %ld)\n", relativeAddress, sourceLocation.Line(), sourceLocation.Column()); // get function id FunctionID* functionID = functionInstance->GetFunctionID(); if (functionID == NULL) return; BReference<FunctionID> functionIDReference(functionID, true); // create the user breakpoint userBreakpoint = new(std::nothrow) UserBreakpoint( UserBreakpointLocation(functionID, function->SourceFile(), sourceLocation, relativeAddress)); if (userBreakpoint == NULL) return; userBreakpointReference.SetTo(userBreakpoint, true); TRACE_CONTROL(" created user breakpoint: %p\n", userBreakpoint); // iterate through all function instances and create // UserBreakpointInstances for (FunctionInstanceList::ConstIterator it = function->Instances().GetIterator(); FunctionInstance* instance = it.Next();) { TRACE_CONTROL(" function instance %p: range: %#llx - %#llx\n", instance, instance->Address(), instance->Address() + instance->Size()); // get the breakpoint address for the instance target_addr_t instanceAddress = 0; if (instance == functionInstance) { instanceAddress = address; } else if (functionInstance->SourceFile() != NULL) { // We have a source file, so get the address for the source // location. Statement* statement = NULL; functionDebugInfo = instance->GetFunctionDebugInfo(); functionDebugInfo->GetSpecificImageDebugInfo() ->GetStatementAtSourceLocation(functionDebugInfo, sourceLocation, statement); if (statement != NULL) { instanceAddress = statement->CoveringAddressRange().Start(); // TODO: What about BreakpointAllowed()? statement->ReleaseReference(); } } TRACE_CONTROL(" breakpoint address using source info: %llx\n", instanceAddress); if (instanceAddress == 0) { // No source file (or we failed getting the statement), so try // to use the same relative address. if (relativeAddress > instance->Size()) continue; instanceAddress = instance->Address() + relativeAddress; } TRACE_CONTROL(" final breakpoint address: %llx\n", instanceAddress); UserBreakpointInstance* breakpointInstance = new(std::nothrow) UserBreakpointInstance(userBreakpoint, instanceAddress); if (breakpointInstance == NULL || !userBreakpoint->AddInstance(breakpointInstance)) { delete breakpointInstance; return; } TRACE_CONTROL(" breakpoint instance: %p\n", breakpointInstance); } } locker.Unlock(); _HandleSetUserBreakpoint(userBreakpoint, enabled); }