Esempio n. 1
0
Statement*
ThreadHandler::_GetStatementAtInstructionPointer(StackFrame* frame)
{
	AutoLocker<Team> locker(fThread->GetTeam());

	FunctionInstance* functionInstance = frame->Function();
	if (functionInstance == NULL)
		return NULL;
	FunctionDebugInfo* function = functionInstance->GetFunctionDebugInfo();

	// If there's source code attached to the function, we can just get the
	// statement.
//	SourceCode* sourceCode = function->GetSourceCode();
//	if (sourceCode != NULL) {
//		Statement* statement = sourceCode->StatementAtAddress(
//			frame->InstructionPointer());
//		if (statement != NULL)
//			statement->AcquireReference();
//		return statement;
//	}

	locker.Unlock();

	// We need to get the statement from the debug info of the function.
	Statement* statement;
	if (function->GetSpecificImageDebugInfo()->GetStatement(function,
			frame->InstructionPointer(), statement) != B_OK) {
		return NULL;
	}

	return statement;
}
	virtual bool GetValueAt(void* object, int32 columnIndex, BVariant& value)
	{
		if (columnIndex != 0)
			return false;

		if (object == this)
			return false;

		if (object >= fSourceFileIndices
			&& object < fSourceFileIndices + fSourceFileCount) {
			int32 index = *(int32*)object;
			if (LocatableFile* file = fFunctions[index]->SourceFile()) {
				BString path;
				file->GetPath(path);
				value.SetTo(path);
			} else
				value.SetTo("<no source file>", B_VARIANT_DONT_COPY_DATA);

			return true;
		}

		FunctionInstance* function = (FunctionInstance*)object;
		value.SetTo(function->PrettyName(), B_VARIANT_DONT_COPY_DATA);
		return true;
	}
Esempio n. 3
0
Function*
TeamDebugInfo::FunctionByID(FunctionID* functionID) const
{
	if (SourceFunctionID* sourceFunctionID
			= dynamic_cast<SourceFunctionID*>(functionID)) {
		// get the source file
		LocatableFile* file = fFileManager->GetSourceFile(
			sourceFunctionID->SourceFilePath());
		if (file == NULL)
			return NULL;
		BReference<LocatableFile> fileReference(file, true);

		if (SourceFileEntry* entry = fSourceFiles->Lookup(file))
			return entry->FunctionByName(functionID->FunctionName());
		return NULL;
	}

	ImageFunctionID* imageFunctionID
		= dynamic_cast<ImageFunctionID*>(functionID);
	if (imageFunctionID == NULL)
		return NULL;

	ImageDebugInfo* imageDebugInfo
		= ImageDebugInfoByName(imageFunctionID->ImageName());
	if (imageDebugInfo == NULL)
		return NULL;

	FunctionInstance* functionInstance = imageDebugInfo->FunctionByName(
		functionID->FunctionName());
	return functionInstance != NULL ? functionInstance->GetFunction() : NULL;
}
Esempio n. 4
0
status_t
Team::GetStatementAtAddress(target_addr_t address, FunctionInstance*& _function,
	Statement*& _statement)
{
	TRACE_CODE("Team::GetStatementAtAddress(%#" B_PRIx64 ")\n", address);

	// get the image at the address
	Image* image = ImageByAddress(address);
	if (image == NULL) {
		TRACE_CODE("  -> no image\n");
		return B_ENTRY_NOT_FOUND;
	}

	ImageDebugInfo* imageDebugInfo = image->GetImageDebugInfo();
	if (imageDebugInfo == NULL) {
		TRACE_CODE("  -> no image debug info\n");
		return B_ENTRY_NOT_FOUND;
	}

	// get the function
	FunctionInstance* functionInstance
		= imageDebugInfo->FunctionAtAddress(address);
	if (functionInstance == NULL) {
		TRACE_CODE("  -> no function instance\n");
		return B_ENTRY_NOT_FOUND;
	}

	// If the function instance has disassembled code attached, we can get the
	// statement directly.
	if (DisassembledCode* code = functionInstance->GetSourceCode()) {
		Statement* statement = code->StatementAtAddress(address);
		if (statement == NULL)
			return B_ENTRY_NOT_FOUND;

		statement->AcquireReference();
		_statement = statement;
		_function = functionInstance;
		return B_OK;
	}

	// get the statement from the image debug info
	FunctionDebugInfo* functionDebugInfo
		= functionInstance->GetFunctionDebugInfo();
	status_t error = functionDebugInfo->GetSpecificImageDebugInfo()
		->GetStatement(functionDebugInfo, address, _statement);
	if (error != B_OK) {
		TRACE_CODE("  -> no statement from the specific image debug info\n");
		return error;
	}

	_function = functionInstance;
	return B_OK;
}
Esempio n. 5
0
status_t
BreakConditionConfigWindow::_FindExceptionFunction(ImageDebugInfo* info,
	target_addr_t& _foundAddress) const
{
	if (info != NULL) {
		FunctionInstance* instance = info->FunctionByName(
			"__cxa_allocate_exception");
		if (instance == NULL)
			instance = info->FunctionByName("__throw(void)");

		if (instance != NULL) {
			_foundAddress = instance->Address();
			return B_OK;
		}
	}

	return B_NAME_NOT_FOUND;
}
Esempio n. 6
0
status_t
Team::GetStatementAtSourceLocation(SourceCode* sourceCode,
	const SourceLocation& location, Statement*& _statement)
{
	TRACE_CODE("Team::GetStatementAtSourceLocation(%p, (%" B_PRId32 ", %"
		B_PRId32 "))\n", sourceCode, location.Line(), location.Column());

	// If we're lucky the source code can provide us with a statement.
	if (DisassembledCode* code = dynamic_cast<DisassembledCode*>(sourceCode)) {
		Statement* statement = code->StatementAtLocation(location);
		if (statement == NULL)
			return B_ENTRY_NOT_FOUND;

		statement->AcquireReference();
		_statement = statement;
		return B_OK;
	}

	// Go the long and stony way over the source file and the team debug info.
	// get the source file for the source code
	LocatableFile* sourceFile = sourceCode->GetSourceFile();
	if (sourceFile == NULL)
		return B_ENTRY_NOT_FOUND;

	// get the function at the source location
	Function* function = fDebugInfo->FunctionAtSourceLocation(sourceFile,
		location);
	if (function == NULL)
		return B_ENTRY_NOT_FOUND;

	// Get some function instance and ask its image debug info to provide us
	// with a statement.
	FunctionInstance* functionInstance = function->FirstInstance();
	if (functionInstance == NULL)
		return B_ENTRY_NOT_FOUND;

	FunctionDebugInfo* functionDebugInfo
		= functionInstance->GetFunctionDebugInfo();
	return functionDebugInfo->GetSpecificImageDebugInfo()
		->GetStatementAtSourceLocation(functionDebugInfo, location, _statement);
}
Esempio n. 7
0
status_t
Architecture::CreateStackTrace(Team* team,
                               ImageDebugInfoProvider* imageInfoProvider, CpuState* cpuState,
                               StackTrace*& _stackTrace, int32 maxStackDepth, bool useExistingTrace)
{
    BReference<CpuState> cpuStateReference(cpuState);

    StackTrace* stackTrace = NULL;
    ObjectDeleter<StackTrace> stackTraceDeleter;
    StackFrame* frame = 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) {
        frame = stackTrace->FrameAt(stackTrace->CountFrames() - 1);
        cpuState = frame->GetCpuState();
    }

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

        // 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 (frame != NULL
                && frame->ReturnAddress() == cpuState->InstructionPointer()) {
            UpdateStackFrameCpuState(frame, image,
                                     functionDebugInfo, cpuState);
        }

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

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

        cpuStateReference.SetTo(previousCpuState, true);

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

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

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

    stackTraceDeleter.Detach();
    _stackTrace = stackTrace;
    return B_OK;
}
Esempio n. 8
0
status_t
DebugReportGenerator::_DumpFunctionDisassembly(BFile& _output,
	target_addr_t instructionPointer)
{
	AutoLocker< ::Team> teamLocker(fTeam);
	BString data;
	FunctionInstance* instance = NULL;
	Statement* statement = NULL;
	status_t error = fTeam->GetStatementAtAddress(instructionPointer, instance,
		statement);
	if (error != B_OK) {
		data.SetToFormat("Unable to retrieve disassembly for IP %#" B_PRIx64
				": %s\n", instructionPointer, strerror(error));
		WRITE_AND_CHECK(_output, data);
		return B_OK;
	}

	DisassembledCode* code = instance->GetSourceCode();
	Function* function = instance->GetFunction();
	if (code == NULL) {
		switch (function->SourceCodeState()) {
			case FUNCTION_SOURCE_NOT_LOADED:
			case FUNCTION_SOURCE_LOADED:
				// FUNCTION_SOURCE_LOADED is included since, if we entered
				// here, it implies that the high level source for the
				// function has been loaded, but the disassembly has not.
				function->AddListener(this);
				fSourceWaitingFunction = function;
				fListener->FunctionSourceCodeRequested(instance, true);
				// fall through
			case FUNCTION_SOURCE_LOADING:
			{
				teamLocker.Unlock();
				do {
					error = acquire_sem(fTeamDataSem);
				} while (error == B_INTERRUPTED);

				if (error != B_OK)
					return error;

				teamLocker.Lock();
				break;
			}
			default:
				return B_OK;
		}

		if (instance->SourceCodeState() == 	FUNCTION_SOURCE_UNAVAILABLE)
			return B_OK;

		error = fTeam->GetStatementAtAddress(instructionPointer, instance,
			statement);
		code = instance->GetSourceCode();
	}

	SourceLocation location = statement->StartSourceLocation();

	data = "\t\t\tDisassembly:\n";
	WRITE_AND_CHECK(_output, data);
	for (int32 i = 0; i <= location.Line(); i++) {
		data = "\t\t\t\t";
		data << code->LineAt(i);
		if (i == location.Line())
			data << " <--";
		data << "\n";
		WRITE_AND_CHECK(_output, data);
	}
	data = "\n";
	WRITE_AND_CHECK(_output, data);

	return B_OK;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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);
}