Beispiel #1
0
 public bool Equals(DllManipulatorOptions other)
 {
     return(other.dllPathPattern == dllPathPattern && other.assemblyNames.SequenceEqual(assemblyNames) &&
            other.loadingMode == loadingMode && other.posixDlopenFlags == posixDlopenFlags &&
            other.threadSafe == threadSafe && other.enableCrashLogs == enableCrashLogs &&
            other.crashLogsDir == crashLogsDir && other.crashLogsStackTrace == crashLogsStackTrace &&
            other.mockAllNativeFunctions == mockAllNativeFunctions && other.onlyInEditor == onlyInEditor &&
            other.enableInEditMode == enableInEditMode);
 }
Beispiel #2
0
        /// <summary>
        /// Will unload/forget all dll's and reset the state
        /// </summary>
        public static void Reset()
        {
            UnloadAll();
            ForgetAllDlls();
            ClearCrashLogs();

            _customLoadedTriggers?.Clear();
            _customAfterUnloadTriggers?.Clear();
            _customBeforeUnloadTriggers?.Clear();

            Options = null;
        }
Beispiel #3
0
        public DllManipulatorOptions CloneTo(DllManipulatorOptions other)
        {
            other.dllPathPattern         = dllPathPattern;
            other.assemblyNames          = assemblyNames.Select(item => (string)item.Clone()).ToList();
            other.loadingMode            = loadingMode;
            other.posixDlopenFlags       = posixDlopenFlags;
            other.threadSafe             = threadSafe;
            other.enableCrashLogs        = enableCrashLogs;
            other.crashLogsDir           = crashLogsDir;
            other.crashLogsStackTrace    = crashLogsStackTrace;
            other.mockAllNativeFunctions = mockAllNativeFunctions;
            other.onlyInEditor           = onlyInEditor;
            other.enableInEditMode       = enableInEditMode;

            return(other);
        }
Beispiel #4
0
        private void DrawOptions(DllManipulatorOptions options)
        {
            var guiEnabledStack = new Stack <bool>();

            guiEnabledStack.Push(GUI.enabled);
            if (EditorApplication.isPlaying)
            {
                GUI.enabled = false;
            }
            options.mockAllNativeFunctions = EditorGUILayout.Toggle(TARGET_ALL_NATIVE_FUNCTIONS_GUI_CONTENT, options.mockAllNativeFunctions);

            if (EditorGUILayout.Toggle(TARGET_ONLY_EXECUTING_ASSEMBLY_GUI_CONTENT, options.assemblyPaths.Length == 0))
            {
                options.assemblyPaths = new string[0];
            }
            else
            {
                var prevIndent1 = EditorGUI.indentLevel;
                EditorGUI.indentLevel++;

                if (_allKnownAssemblies == null || _lastKnownAssembliesRefreshTime + ASSEMBLIES_REFRESH_INTERVAL < DateTime.Now)
                {
                    var playerCompiledAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player)
                                                   .Select(a => PathUtils.NormallizeUnityAssemblyPath(a.outputPath));

                    var editorCompiledAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Editor)
                                                   .Select(a => PathUtils.NormallizeUnityAssemblyPath(a.outputPath));

                    var assemblyAssets = Resources.FindObjectsOfTypeAll <PluginImporter>()
                                         .Where(p => !p.isNativePlugin)
                                         .Select(p => PathUtils.NormallizeUnityAssemblyPath(p.assetPath));

                    string[] defaultAssemblyPrefixes = { "UnityEngine.", "UnityEditor.", "Unity.", "com.unity.", "Mono.", "nunit." };

                    _allKnownAssemblies = playerCompiledAssemblies
                                          .Concat(assemblyAssets)
                                          .Concat(editorCompiledAssemblies)
                                          .OrderBy(path => Array.FindIndex(defaultAssemblyPrefixes, p => path.Substring(path.LastIndexOf('/') + 1).StartsWith(p)))
                                          .ToArray();
                    _lastKnownAssembliesRefreshTime = DateTime.Now;
                }

                if (options.assemblyPaths.Length == 0)
                {
                    var first = GetFirstAssemblyToList(_allKnownAssemblies);
                    if (first != null)
                    {
                        options.assemblyPaths = new[] { first }
                    }
                    ;
                }

                _showTargetAssemblies = EditorGUILayout.Foldout(_showTargetAssemblies, TARGET_ASSEMBLIES_GUI_CONTENT);
                if (_showTargetAssemblies)
                {
                    var prevIndent2 = EditorGUI.indentLevel;
                    EditorGUI.indentLevel++;

                    var selectedAssemblies    = options.assemblyPaths.Where(p => _allKnownAssemblies.Any(a => PathUtils.DllPathsEqual(a, p))).ToList();
                    var notSelectedAssemblies = _allKnownAssemblies.Except(selectedAssemblies).ToArray();
                    DrawList(selectedAssemblies, i =>
                    {
                        var values = new[] { selectedAssemblies[i] }
                        .Concat(notSelectedAssemblies)
                        .Select(a => a.Substring(a.LastIndexOf('/') + 1))
                        .ToArray();

                        var selectedIndex = EditorGUILayout.Popup(0, values);
                        return(selectedIndex == 0 ? selectedAssemblies[i] : notSelectedAssemblies[selectedIndex - 1]);
                    }, notSelectedAssemblies.Length > 0, () => notSelectedAssemblies[0]);
                    options.assemblyPaths = selectedAssemblies.ToArray();

                    EditorGUI.indentLevel = prevIndent2;
                }

                EditorGUI.indentLevel = prevIndent1;
            }

            options.onlyInEditor = EditorGUILayout.Toggle(ONLY_IN_EDITOR, options.onlyInEditor);

            options.dllPathPattern = EditorGUILayout.TextField(DLL_PATH_PATTERN_GUI_CONTENT, options.dllPathPattern);

            options.loadingMode = (DllLoadingMode)EditorGUILayout.EnumPopup(DLL_LOADING_MODE_GUI_CONTENT, options.loadingMode);

#if UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX
            options.posixDlopenFlags = (PosixDlopenFlags)EditorGUILayout.EnumPopup(POSIX_DLOPEN_FLAGS_GUI_CONTENT, options.posixDlopenFlags);
#endif

            guiEnabledStack.Push(GUI.enabled);
            if (options.loadingMode != DllLoadingMode.Preload)
            {
                options.threadSafe = false;
                GUI.enabled        = false;
            }
            options.threadSafe = EditorGUILayout.Toggle(THREAD_SAFE_GUI_CONTENT, options.threadSafe);
            GUI.enabled        = guiEnabledStack.Pop();

            options.enableCrashLogs = EditorGUILayout.Toggle(CRASH_LOGS_GUI_CONTENT, options.enableCrashLogs);

            if (options.enableCrashLogs)
            {
                var prevIndent = EditorGUI.indentLevel;
                EditorGUI.indentLevel += 1;

                options.crashLogsDir = EditorGUILayout.TextField(CRASH_LOGS_DIR_GUI_CONTENT, options.crashLogsDir);

                options.crashLogsStackTrace = EditorGUILayout.Toggle(CRASH_LOGS_STACK_TRACE_GUI_CONTENT, options.crashLogsStackTrace);

                EditorGUI.indentLevel = prevIndent;
            }

            GUI.enabled = guiEnabledStack.Pop();
        }
Beispiel #5
0
        private void DrawOptions(DllManipulatorOptions options)
        {
            options.onlyInEditor     = EditorGUILayout.Toggle(ONLY_IN_EDITOR, options.onlyInEditor);
            options.enableInEditMode = EditorGUILayout.Toggle(ENABLE_IN_EDIT_MODE, options.enableInEditMode);

            EditorGUILayout.Separator();
            EditorGUILayout.LabelField("Managed Side", EditorStyles.boldLabel);

            options.mockAllNativeFunctions = EditorGUILayout.Toggle(TARGET_ALL_NATIVE_FUNCTIONS_GUI_CONTENT, options.mockAllNativeFunctions);

            if (EditorGUILayout.Toggle(ONLY_ASSEMBLY_CSHARP_GUI_CONTENT, options.assemblyNames.Count == 0))
            {
                options.assemblyNames.Clear();
            }
            else
            {
                var prevIndent1 = EditorGUI.indentLevel;
                EditorGUI.indentLevel++;

                if (_possibleTargetAssemblies == null || _lastKnownAssembliesRefreshTime + ASSEMBLIES_REFRESH_INTERVAL < DateTime.Now)
                {
                    RefreshPossibleTargetAssemblies();
                }

                if (options.assemblyNames.Count == 0)
                {
                    options.assemblyNames.AddRange(DllManipulator.DEFAULT_ASSEMBLY_NAMES);
                }

                _showTargetAssemblies = EditorGUILayout.Foldout(_showTargetAssemblies, TARGET_ASSEMBLIES_GUI_CONTENT);
                if (_showTargetAssemblies)
                {
                    var prevIndent2 = EditorGUI.indentLevel;
                    EditorGUI.indentLevel++;

                    DrawList(options.assemblyNames, i =>
                    {
                        var result = EditorGUILayout.TextField(options.assemblyNames[i]);

                        // Show a pop up for quickly selecting an assembly
                        var selectedId = EditorGUILayout.Popup(0,
                                                               new[] { "Find" }.Concat(_possibleTargetAssemblies).ToArray(), GUILayout.Width(80));

                        if (selectedId > 0)
                        {
                            result = _possibleTargetAssemblies[selectedId - 1];
                        }
                        return(result);
                    }, true, () => "",
                             () =>
                    {
                        options.assemblyNames = options.assemblyNames
                                                .Concat(_possibleTargetAssemblies).Distinct().ToList();
                    });

                    EditorGUI.indentLevel = prevIndent2;
                }

                EditorGUI.indentLevel = prevIndent1;
            }

            EditorGUILayout.Separator();
            EditorGUILayout.LabelField("Native Side", EditorStyles.boldLabel);

            options.dllPathPattern = EditorGUILayout.TextField(DLL_PATH_PATTERN_GUI_CONTENT, options.dllPathPattern);

            options.loadingMode = (DllLoadingMode)EditorGUILayout.EnumPopup(DLL_LOADING_MODE_GUI_CONTENT, options.loadingMode);

#if UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX
            options.posixDlopenFlags = (PosixDlopenFlags)EditorGUILayout.EnumPopup(POSIX_DLOPEN_FLAGS_GUI_CONTENT, options.posixDlopenFlags);
#endif

            var guiEnabled = GUI.enabled;
            if (options.loadingMode != DllLoadingMode.Preload)
            {
                options.threadSafe = false;
                GUI.enabled        = false;
            }
            options.threadSafe = EditorGUILayout.Toggle(THREAD_SAFE_GUI_CONTENT, options.threadSafe);
            GUI.enabled        = guiEnabled;

            options.enableCrashLogs = EditorGUILayout.Toggle(CRASH_LOGS_GUI_CONTENT, options.enableCrashLogs);

            if (options.enableCrashLogs)
            {
                var prevIndent = EditorGUI.indentLevel;
                EditorGUI.indentLevel += 1;

                options.crashLogsDir = EditorGUILayout.TextField(CRASH_LOGS_DIR_GUI_CONTENT, options.crashLogsDir);

                options.crashLogsStackTrace = EditorGUILayout.Toggle(CRASH_LOGS_STACK_TRACE_GUI_CONTENT, options.crashLogsStackTrace);

                EditorGUI.indentLevel = prevIndent;
            }
        }
Beispiel #6
0
        /// <summary>
        /// Initialization.
        /// Finds and mocks relevant native function declarations.
        /// If <see cref="DllLoadingMode.Preload"/> option is specified, loads all DLLs specified by these functions.
        /// Options have to be configured before calling this method.
        /// </summary>
        internal static void Initialize(DllManipulatorOptions options, int unityMainThreadId, string assetsPath)
        {
            // Make a deep copy of the options so we can edit them in DllManipulatorScript independently
            Options = new DllManipulatorOptions();
            options.CloneTo(Options);
            _unityMainThreadId = unityMainThreadId;
            _assetsPath        = assetsPath;

            LowLevelPluginManager.ResetStubPlugin();

            IEnumerable <string> assemblyPathsTemp = Options.assemblyNames;

            if (!assemblyPathsTemp.Any())
            {
                assemblyPathsTemp = DEFAULT_ASSEMBLY_NAMES;
            }

            assemblyPathsTemp = assemblyPathsTemp.Concat(INTERNAL_ASSEMBLY_NAMES);

            var allAssemblies     = AppDomain.CurrentDomain.GetAssemblies();
            var assemblies        = allAssemblies.Where(a => !a.IsDynamic && assemblyPathsTemp.Any(p => p == Path.GetFileNameWithoutExtension(a.Location))).ToArray();
            var missingAssemblies = assemblyPathsTemp.Except(assemblies.Select(a => Path.GetFileNameWithoutExtension(a.Location)));

            foreach (var assembly in missingAssemblies.Except(DEFAULT_ASSEMBLY_NAMES))
            {
                Debug.LogError($"Could not find assembly: {assembly}");
            }

            foreach (var assembly in assemblies)
            {
                var allTypes = assembly.GetTypes();
                foreach (var type in allTypes)
                {
                    foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
                    {
                        if (method.IsDefined(typeof(DllImportAttribute)))
                        {
                            if (method.IsDefined(typeof(DisableMockingAttribute)))
                            {
                                continue;
                            }

                            if (method.DeclaringType.IsDefined(typeof(DisableMockingAttribute)))
                            {
                                continue;
                            }

                            if (Options.mockAllNativeFunctions || method.IsDefined(typeof(MockNativeDeclarationAttribute)) || method.DeclaringType.IsDefined(typeof(MockNativeDeclarationsAttribute)))
                            {
                                MockNativeFunction(method);
                            }
                        }
                        else
                        {
                            if (method.IsDefined(typeof(NativeDllLoadedTriggerAttribute)))
                            {
                                RegisterTriggerMethod(method, ref _customLoadedTriggers, method.GetCustomAttribute <NativeDllLoadedTriggerAttribute>());
                            }

                            if (method.IsDefined(typeof(NativeDllBeforeUnloadTriggerAttribute)))
                            {
                                RegisterTriggerMethod(method, ref _customBeforeUnloadTriggers, method.GetCustomAttribute <NativeDllBeforeUnloadTriggerAttribute>());
                            }

                            if (method.IsDefined(typeof(NativeDllAfterUnloadTriggerAttribute)))
                            {
                                RegisterTriggerMethod(method, ref _customAfterUnloadTriggers, method.GetCustomAttribute <NativeDllAfterUnloadTriggerAttribute>());
                            }
                        }
                    }
                }
            }

            if (Options.loadingMode == DllLoadingMode.Preload)
            {
                LoadAll();
            }
        }