Esempio n. 1
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);
}