Beispiel #1
0
/**
 * Captures the current stack and updates stack tracking information.
 * optionally stores a user data pointer that the tracker will take ownership of and delete upon reset
 * you must allocate the memory with FMemory::Malloc()
 */
void FStackTracker::CaptureStackTrace(int32 EntriesToIgnore /*=2*/, void* UserData /*=NULL*/)
{
	// Avoid re-rentrancy as the code uses TArray/TMap.
	if( !bAvoidCapturing && bIsEnabled )
	{
		// Scoped true/ false.
		bAvoidCapturing = true;

		// Capture callstack and create CRC.
		uint64* FullBackTrace = NULL;
		FullBackTrace = static_cast<uint64*>(FMemory_Alloca((MAX_BACKTRACE_DEPTH + EntriesToIgnore) * sizeof(uint64)));

		FPlatformStackWalk::CaptureStackBackTrace( FullBackTrace, MAX_BACKTRACE_DEPTH + EntriesToIgnore );
		CA_ASSUME(FullBackTrace);

		// Skip first NUM_ENTRIES_TO_SKIP entries as they are inside this code
		uint64* BackTrace = &FullBackTrace[EntriesToIgnore];
		uint32 CRC = FCrc::MemCrc_DEPRECATED( BackTrace, MAX_BACKTRACE_DEPTH * sizeof(uint64) );
        
		// Use index if found
		int32* IndexPtr = CRCToCallStackIndexMap.Find( CRC );
        
		if( IndexPtr )
		{
			// Increase stack count for existing callstack.
			CallStacks[*IndexPtr].StackCount++;
			if (UpdateFn)
			{
				UpdateFn(CallStacks[*IndexPtr], UserData);
			}

			//We can delete this since the user gives ownership at the beginning of this call
			//and had a chance to update their data inside the above callback
			if (UserData)
			{
				FMemory::Free(UserData);
			}
		}
		// Encountered new call stack, add to array and set index mapping.
		else
		{
			// Add to array and set mapping for future use.
			int32 Index = CallStacks.AddUninitialized();
			CRCToCallStackIndexMap.Add( CRC, Index );

			// Fill in callstack and count.
			FCallStack& CallStack = CallStacks[Index];
			FMemory::Memcpy( CallStack.Addresses, BackTrace, sizeof(uint64) * MAX_BACKTRACE_DEPTH );
			CallStack.StackCount = 1;
			CallStack.UserData = UserData;
		}

		// We're done capturing.
		bAvoidCapturing = false;
	}
}
Beispiel #2
0
void FJavaScriptHelper::ExecuteHook(UObject* Receiver, const FString& HookName, ICefRuntimeVariantList* Arguments)
{
	UFunction* Function = Receiver->GetClass()->FindFunctionByName(*HookName);
	if (!Function)
	{
		UE_LOG(RadiantUILog, Error, TEXT("JavaScript Hook Function '%s' was not found"), *HookName);
		return;
	}

	int ArgumentMismatch = -1;

	if (Arguments)
	{
		if (Arguments->GetSize() != Function->NumParms)
		{
			UE_LOG(RadiantUILog, Error, TEXT("JavaScript Hook Function '%s' on Object '%s' was called with the wrong number arguments! The called function(called from JS) desires %i arguments, but the defined(in this game) has %i arguments."), *HookName, *Receiver->GetPathName(), Arguments->GetSize(), Function->NumParms);
			return;
		}
		
		void* Parms = (uint8*)FMemory_Alloca(Function->ParmsSize);
		FMemory::Memzero(Parms, Function->ParmsSize);

		int ArgumentIndex = 0;
		for (TFieldIterator<UProperty> It(Function); It && (It->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm; ++It, ++ArgumentIndex)
		{
			if (!StoreFunctionParameter(HookName, Parms, *It, Arguments->GetValue(ArgumentIndex), ArgumentIndex))
			{
				return;
			}
		}

		Receiver->ProcessEvent(Function, Parms);
	}
	else
	{
		if (Function->NumParms == 0)
		{
			Receiver->ProcessEvent(Function, nullptr);
		}
		else
		{
			ArgumentMismatch = 0;
		}
	}

	if (ArgumentMismatch >= 0)
	{
		UE_LOG(RadiantUILog, Error, TEXT("JavaScript Hook Function '%s' argument %d type mismatch"), *HookName, ArgumentMismatch);
	}
}
void FGenericPlatformMemory::Memswap( void* Ptr1, void* Ptr2, SIZE_T Size )
{
	if (Ptr1 != Ptr2)
	{
		// check that Ptr1 and Ptr2 do not overlap in undefined ways
		checkf(reinterpret_cast<uint8 *>(Ptr1)+Size <= reinterpret_cast<uint8 *>(Ptr2) || reinterpret_cast<uint8 *>(Ptr2)+Size <= reinterpret_cast<uint8 *>(Ptr1),
			TEXT("Pointers given to FPlatformMemory::Memswap() point to overlapping memory areas, results are undefined."));

		void* Temp = FMemory_Alloca(Size);
		FPlatformMemory::Memcpy( Temp, Ptr1, Size );
		FPlatformMemory::Memcpy( Ptr1, Ptr2, Size );
		FPlatformMemory::Memcpy( Ptr2, Temp, Size );
	}
}
PyObject *py_ue_skeletal_mesh_get_raw_indices(ue_PyUObject *self, PyObject * args)
{

	ue_py_check(self);

	int lod_index = 0;

	if (!PyArg_ParseTuple(args, "|i:skeletal_mesh_get_raw_indices", &lod_index))
		return nullptr;

	USkeletalMesh *mesh = ue_py_check_type<USkeletalMesh>(self);
	if (!mesh)
		return PyErr_Format(PyExc_Exception, "uobject is not a USkeletalMesh");

#if ENGINE_MINOR_VERSION < 19
	FSkeletalMeshResource *resource = mesh->GetImportedResource();
#else
	FSkeletalMeshModel *resource = mesh->GetImportedModel();
#endif

	if (lod_index < 0 || lod_index >= resource->LODModels.Num())
		return PyErr_Format(PyExc_Exception, "invalid LOD index, must be between 0 and %d", resource->LODModels.Num() - 1);

#if ENGINE_MINOR_VERSION < 19
	FStaticLODModel &model = resource->LODModels[lod_index];
#else
	FSkeletalMeshLODModel &model = resource->LODModels[lod_index];
#endif


	PyObject *py_list = PyList_New(0);

	int32 *raw_indices = (int32 *)model.RawPointIndices.Lock(LOCK_READ_ONLY);
	int32 *indices = (int32 *)FMemory_Alloca(model.RawPointIndices.GetBulkDataSize());
	FMemory::Memcpy(indices, raw_indices, model.RawPointIndices.GetBulkDataSize());
	model.RawPointIndices.Unlock();

	for (int32 index = 0; index < model.RawPointIndices.GetBulkDataSize() / sizeof(int32); index++)
	{
		PyList_Append(py_list, PyLong_FromLong(indices[index]));
	}

	return py_list;
}
void UPythonFunction::CallPythonCallable(FFrame& Stack, RESULT_DECL)
{

	FScopePythonGIL gil;

	UPythonFunction *function = static_cast<UPythonFunction *>(Stack.CurrentNativeFunction);

	bool on_error = false;
	bool is_static = function->HasAnyFunctionFlags(FUNC_Static);

	// count the number of arguments
	Py_ssize_t argn = (Stack.Object && !is_static) ? 1 : 0;
	TFieldIterator<UProperty> IArgs(function);
	for (; IArgs && ((IArgs->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++IArgs) {
		argn++;
	}
#if defined(UEPY_MEMORY_DEBUG)
	UE_LOG(LogPython, Warning, TEXT("Initializing %d parameters"), argn);
#endif
	PyObject *py_args = PyTuple_New(argn);

	if (Stack.Object && !is_static) {
		PyObject *py_obj = (PyObject *)ue_get_python_wrapper(Stack.Object);
		if (!py_obj) {
			unreal_engine_py_log_error();
			on_error = true;
		}
		else {
			Py_INCREF(py_obj);
			PyTuple_SetItem(py_args, 0, py_obj);
		}
	}

	uint8 *frame = Stack.Locals;

	argn = (Stack.Object && !is_static) ? 1 : 0;
	// is it a blueprint call ?
	if (*Stack.Code == EX_EndFunctionParms) {
		for (UProperty *prop = (UProperty *)function->Children; prop; prop = (UProperty *)prop->Next) {
			if (prop->PropertyFlags & CPF_ReturnParm)
				continue;
			if (!on_error) {
				PyObject *arg = ue_py_convert_property(prop, (uint8 *)Stack.Locals);
				if (!arg) {
					unreal_engine_py_log_error();
					on_error = true;
				}
				else {
					PyTuple_SetItem(py_args, argn++, arg);
				}
			}
		}
	}
	else {
		//UE_LOG(LogPython, Warning, TEXT("BLUEPRINT CALL"));
		frame = (uint8 *)FMemory_Alloca(function->PropertiesSize);
		FMemory::Memzero(frame, function->PropertiesSize);
		for (UProperty *prop = (UProperty *)function->Children; *Stack.Code != EX_EndFunctionParms; prop = (UProperty *)prop->Next) {
			Stack.Step(Stack.Object, prop->ContainerPtrToValuePtr<uint8>(frame));
			if (prop->PropertyFlags & CPF_ReturnParm)
				continue;
			if (!on_error) {
				PyObject *arg = ue_py_convert_property(prop, frame);
				if (!arg) {
					unreal_engine_py_log_error();
					on_error = true;
				}
				else {
					PyTuple_SetItem(py_args, argn++, arg);
				}
			}
		}
	}

	Stack.Code++;

	if (on_error || !function->py_callable) {
		Py_DECREF(py_args);
		return;
	}

	PyObject *ret = PyObject_CallObject(function->py_callable, py_args);
	Py_DECREF(py_args);
	if (!ret) {
		unreal_engine_py_log_error();
		return;
	}

	// get return value (if required)
	UProperty *return_property = function->GetReturnProperty();
	if (return_property && function->ReturnValueOffset != MAX_uint16) {
#if defined(UEPY_MEMORY_DEBUG)
		UE_LOG(LogPython, Warning, TEXT("FOUND RETURN VALUE"));
#endif
		if (ue_py_convert_pyobject(ret, return_property, frame)) {
			// copy value to stack result value
			FMemory::Memcpy(RESULT_PARAM, frame + function->ReturnValueOffset, return_property->ArrayDim * return_property->ElementSize);
		}
		else {
			UE_LOG(LogPython, Error, TEXT("Invalid return value type for function %s"), *function->GetFName().ToString());
		}
	}
	Py_DECREF(ret);
}
/**
 * Captures the current stack and updates stack tracking information.
 * optionally stores a user data pointer that the tracker will take ownership of and delete upon reset
 * you must allocate the memory with FMemory::Malloc()
 */
void FStackTracker::CaptureStackTrace(int32 EntriesToIgnore, void* UserData, int32 StackLen, bool bLookupStringsForAliasRemoval)
{
	// Avoid re-rentrancy as the code uses TArray/TMap.
	if( !bAvoidCapturing && bIsEnabled )
	{
		// Scoped true/ false.
		bAvoidCapturing = true;

		// Capture callstack and create CRC.
		int32 Size = (MAX_BACKTRACE_DEPTH + EntriesToIgnore) * sizeof(uint64);
		uint64* FullBackTrace = static_cast<uint64*>(FMemory_Alloca(Size));

		FMemory::Memzero(FullBackTrace, Size);

		FPlatformStackWalk::CaptureStackBackTrace( FullBackTrace, MAX_BACKTRACE_DEPTH + EntriesToIgnore );
		CA_ASSUME(FullBackTrace);

		// Skip first NUM_ENTRIES_TO_SKIP entries as they are inside this code
		uint64* BackTrace = &FullBackTrace[EntriesToIgnore];
		if (StackLen < MAX_BACKTRACE_DEPTH)
		{
			FMemory::Memzero(BackTrace + StackLen, sizeof(uint64) * (MAX_BACKTRACE_DEPTH - StackLen));
		}
		if (bLookupStringsForAliasRemoval)
		{
			for (int32 Index = 0; Index < StackLen; Index++)
			{
				if (BackTrace[Index])
				{
					uint64* Existing = AliasMap.Find(BackTrace[Index]);
					if (Existing)
					{
						BackTrace[Index] = *Existing;
					}
					else
					{
						ANSICHAR AddressInformation[512];
						AddressInformation[0] = 0;
						FPlatformStackWalk::ProgramCounterToHumanReadableString( 1, BackTrace[Index], AddressInformation, ARRAY_COUNT(AddressInformation)-1 );
						FString Symbol(AddressInformation);
						int32 Spot = Symbol.Find(TEXT(" - "));
						if (Spot != INDEX_NONE)
						{
							Symbol = Symbol.RightChop(Spot + 3);
						}
						Existing = StringAliasMap.Find(Symbol);
						if (Existing)
						{
							AliasMap.Add(BackTrace[Index], *Existing);
							BackTrace[Index] = *Existing;
						}
						else
						{
							AliasMap.Add(BackTrace[Index], BackTrace[Index]);
							StringAliasMap.Add(Symbol, BackTrace[Index]);
						}
					}
				}
			}
		}
		uint32 CRC = FCrc::MemCrc_DEPRECATED( BackTrace, MAX_BACKTRACE_DEPTH * sizeof(uint64) );
        
		// Use index if found
		int32* IndexPtr = CRCToCallStackIndexMap.Find( CRC );
        
		if( IndexPtr )
		{
			// Increase stack count for existing callstack.
			CallStacks[*IndexPtr].StackCount++;
			if (UpdateFn)
			{
				UpdateFn(CallStacks[*IndexPtr], UserData);
			}

			//We can delete this since the user gives ownership at the beginning of this call
			//and had a chance to update their data inside the above callback
			if (UserData)
			{
				FMemory::Free(UserData);
			}
		}
		// Encountered new call stack, add to array and set index mapping.
		else
		{
			// Add to array and set mapping for future use.
			int32 Index = CallStacks.AddUninitialized();
			CRCToCallStackIndexMap.Add( CRC, Index );

			// Fill in callstack and count.
			FCallStack& CallStack = CallStacks[Index];
			FMemory::Memcpy( CallStack.Addresses, BackTrace, sizeof(uint64) * MAX_BACKTRACE_DEPTH );
			CallStack.StackCount = 1;
			CallStack.UserData = UserData;
		}

		// We're done capturing.
		bAvoidCapturing = false;
	}
}