Exemplo n.º 1
0
status_t
Architecture::CreateStackTrace(Team* team,
	ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
	StackTrace*& _stackTrace, ReturnValueInfoList* returnValueInfos,
	int32 maxStackDepth, bool useExistingTrace, bool getFullFrameInfo)
{
	BReference<CpuState> cpuStateReference(cpuState);

	StackTrace* stackTrace = NULL;
	ObjectDeleter<StackTrace> stackTraceDeleter;
	StackFrame* nextFrame = NULL;

	if (useExistingTrace)
		stackTrace = _stackTrace;
	else {
		// create the object
		stackTrace = new(std::nothrow) StackTrace;
		if (stackTrace == NULL)
			return B_NO_MEMORY;
		stackTraceDeleter.SetTo(stackTrace);
	}

	// if we're passed an already existing partial stack trace,
	// attempt to continue building it from where it left off.
	if (stackTrace->CountFrames() > 0) {
		nextFrame = stackTrace->FrameAt(stackTrace->CountFrames() - 1);
		cpuState = nextFrame->PreviousCpuState();
	}

	while (cpuState != NULL) {
		// get the instruction pointer
		target_addr_t instructionPointer = cpuState->InstructionPointer();

		// get the image for the instruction pointer
		AutoLocker<Team> teamLocker(team);
		Image* image = team->ImageByAddress(instructionPointer);
		BReference<Image> imageReference(image);
		teamLocker.Unlock();

		// get the image debug info
		ImageDebugInfo* imageDebugInfo = NULL;
		if (image != NULL)
			imageInfoProvider->GetImageDebugInfo(image, imageDebugInfo);
		BReference<ImageDebugInfo> imageDebugInfoReference(imageDebugInfo,
			true);

		// get the function
		teamLocker.Lock();
		FunctionInstance* function = NULL;
		FunctionDebugInfo* functionDebugInfo = NULL;
		if (imageDebugInfo != NULL) {
			function = imageDebugInfo->FunctionAtAddress(instructionPointer);
			if (function != NULL)
				functionDebugInfo = function->GetFunctionDebugInfo();
		}
		BReference<FunctionInstance> functionReference(function);
		teamLocker.Unlock();

		// If the CPU state's instruction pointer is actually the return address
		// of the next frame, we let the architecture fix that.
		if (nextFrame != NULL
			&& nextFrame->ReturnAddress() == cpuState->InstructionPointer()) {
			UpdateStackFrameCpuState(nextFrame, image,
				functionDebugInfo, cpuState);
		}

		// create the frame using the debug info
		StackFrame* frame = NULL;
		CpuState* previousCpuState = NULL;
		if (function != NULL) {
			status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
				->CreateFrame(image, function, cpuState, getFullFrameInfo,
					nextFrame == NULL
						? returnValueInfos : NULL, frame,
					previousCpuState);
			if (error != B_OK && error != B_UNSUPPORTED)
				break;
		}

		// If we have no frame yet, let the architecture create it.
		if (frame == NULL) {
			status_t error = CreateStackFrame(image, functionDebugInfo,
				cpuState, nextFrame == NULL, frame, previousCpuState);
			if (error != B_OK)
				break;
		}

		cpuStateReference.SetTo(previousCpuState, true);

		frame->SetImage(image);
		frame->SetFunction(function);

		if (!stackTrace->AddFrame(frame)) {
			delete frame;
			return B_NO_MEMORY;
		}

		nextFrame = frame;
		cpuState = previousCpuState;
		if (--maxStackDepth == 0)
			break;
	}

	if (stackTrace->CountFrames() == 0)
		return B_ERROR;

	stackTraceDeleter.Detach();
	_stackTrace = stackTrace;
	return B_OK;
}