Sfoglia il codice sorgente

Add uname libc call on Unix systems as platform check
MonoMod's PlatformHelper call causes issues as it calls Process.Create (which breaks in Unity 4.x), so we use a libc uname call to do the same thing without dying

Bepis 4 anni fa
parent
commit
7647862bf4

+ 7 - 6
BepInEx.Preloader/BepInEx.Preloader.csproj

@@ -39,13 +39,13 @@
     <Reference Include="Mono.Cecil.Rocks, Version=0.10.4.0, Culture=neutral, PublicKeyToken=50cebf1cceb9d05e, processorArchitecture=MSIL">
       <HintPath>$(SolutionDir)\packages\Mono.Cecil.0.10.4\lib\net35\Mono.Cecil.Rocks.dll</HintPath>
     </Reference>
-    <Reference Include="MonoMod.RuntimeDetour, Version=20.8.3.5, Culture=neutral, PublicKeyToken=null">
-      <HintPath>..\packages\MonoMod.RuntimeDetour.20.8.3.5\lib\net35\MonoMod.RuntimeDetour.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="MonoMod.RuntimeDetour, Version=20.8.3.5, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\MonoMod\MonoMod.RuntimeDetour\bin\Release\net35\MonoMod.RuntimeDetour.dll</HintPath>
     </Reference>
-    <Reference Include="MonoMod.Utils, Version=20.8.3.5, Culture=neutral, PublicKeyToken=null">
-      <HintPath>..\packages\MonoMod.Utils.20.8.3.5\lib\net35\MonoMod.Utils.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="MonoMod.Utils, Version=20.8.3.5, Culture=neutral, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\MonoMod\MonoMod.RuntimeDetour\bin\Release\net35\MonoMod.Utils.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -55,6 +55,7 @@
     <Compile Include="Patching\AssemblyPatcher.cs" />
     <Compile Include="Entrypoint.cs" />
     <Compile Include="Patching\PatcherPlugin.cs" />
+    <Compile Include="Platform.cs" />
     <Compile Include="RuntimeFixes\ConsoleSetOutFix.cs" />
     <Compile Include="RuntimeFixes\TraceFix.cs" />
     <Compile Include="Preloader.cs" />

+ 2 - 0
BepInEx.Preloader/Entrypoint.cs

@@ -10,6 +10,8 @@ namespace BepInEx.Preloader
 	{
 		public static void PreloaderPreMain()
 		{
+			PlatformUtils.SetPlatform();
+
 			string bepinPath = Utility.ParentDirectory(Path.GetFullPath(EnvVars.DOORSTOP_INVOKE_DLL_PATH), 2);
 
 			Paths.SetExecutablePath(EnvVars.DOORSTOP_PROCESS_PATH, bepinPath, EnvVars.DOORSTOP_MANAGED_FOLDER_DIR);

+ 153 - 0
BepInEx.Preloader/Platform.cs

@@ -0,0 +1,153 @@
+using System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using MonoMod.Utils;
+
+namespace BepInEx.Preloader
+{
+	internal static class PlatformUtils
+	{
+		[StructLayout(LayoutKind.Sequential, Pack = 1)]
+		public struct utsname_osx
+		{
+			private const int osx_utslen = 256;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]
+			public string sysname;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]
+			public string nodename;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]
+			public string release;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]
+			public string version;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]
+			public string machine;
+		}
+
+		[StructLayout(LayoutKind.Sequential, Pack = 1)]
+		public struct utsname_linux
+		{
+			private const int linux_utslen = 65;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]
+			public string sysname;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]
+			public string nodename;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]
+			public string release;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]
+			public string version;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]
+			public string machine;
+
+			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]
+			public string domainname;
+		}
+
+        [DllImport("libc.so.6", EntryPoint = "uname", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+		private static extern IntPtr uname_linux(ref utsname_linux utsname);
+
+		[DllImport("/usr/lib/libSystem.dylib", EntryPoint = "uname", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+		private static extern IntPtr uname_osx(ref utsname_osx utsname);
+
+        /// <summary>
+        /// Recreation of MonoMod's PlatformHelper.DeterminePlatform method, but with libc calls instead of creating processes.
+        /// </summary>
+        public static void SetPlatform()
+		{
+            var current = Platform.Unknown;
+
+            // For old Mono, get from a private property to accurately get the platform.
+            // static extern PlatformID Platform
+            PropertyInfo p_Platform = typeof(Environment).GetProperty("Platform", BindingFlags.NonPublic | BindingFlags.Static);
+            string platID;
+            if (p_Platform != null)
+            {
+                platID = p_Platform.GetValue(null, new object[0]).ToString();
+            }
+            else
+            {
+                // For .NET and newer Mono, use the usual value.
+                platID = Environment.OSVersion.Platform.ToString();
+            }
+            platID = platID.ToLowerInvariant();
+
+            if (platID.Contains("win"))
+            {
+                current = Platform.Windows;
+            }
+            else if (platID.Contains("mac") || platID.Contains("osx"))
+            {
+                current = Platform.MacOS;
+            }
+            else if (platID.Contains("lin") || platID.Contains("unix"))
+            {
+                current = Platform.Linux;
+            }
+
+            if (Is(current, Platform.Linux) && Directory.Exists("/data") && File.Exists("/system/build.prop"))
+            {
+                current = Platform.Android;
+            }
+			else if (Is(current, Platform.Unix) && Directory.Exists("/Applications") && Directory.Exists("/System"))
+			{
+				current = Platform.iOS;
+			}
+
+			// Is64BitOperatingSystem has been added in .NET Framework 4.0
+			MethodInfo m_get_Is64BitOperatingSystem = typeof(Environment).GetProperty("Is64BitOperatingSystem")?.GetGetMethod();
+            if (m_get_Is64BitOperatingSystem != null)
+                current |= (((bool)m_get_Is64BitOperatingSystem.Invoke(null, new object[0])) ? Platform.Bits64 : 0);
+            else
+                current |= (IntPtr.Size >= 8 ? Platform.Bits64 : 0);
+
+			File.AppendAllText("scuffed_debug.log", $"{platID}\n{current}");
+
+			if ((Is(current, Platform.MacOS) || Is(current, Platform.Linux)) && Type.GetType("Mono.Runtime") != null)
+            {
+				string arch;
+				IntPtr result;
+
+				if (Is(current, Platform.MacOS))
+				{
+					utsname_osx utsname_osx = new utsname_osx();
+					result = uname_osx(ref utsname_osx);
+					arch = utsname_osx.machine;
+				}
+				else
+				{
+					// Linux
+					utsname_linux utsname_linux = new utsname_linux();
+					result = uname_linux(ref utsname_linux);
+					arch = utsname_linux.machine;
+				}
+
+				if (result == IntPtr.Zero && (arch.StartsWith("aarch") || arch.StartsWith("arm")))
+					current |= Platform.ARM;
+			}
+            else
+            {
+                // Detect ARM based on PE info or uname.
+                typeof(object).Module.GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine);
+                if (machine == (ImageFileMachine)0x01C4 /* ARM, .NET Framework 4.5 */)
+                    current |= Platform.ARM;
+            }
+
+			PlatformHelper.Current = current;
+		}
+
+		private static bool Is(Platform current, Platform expected)
+		{
+			return (current & expected) == expected;
+		}
+    }
+}

+ 2 - 1
BepInEx.Preloader/Preloader.cs

@@ -68,6 +68,7 @@ namespace BepInEx.Preloader
 				Logger.LogInfo($"Running under Unity v{GetUnityVersion()}");
 				Logger.LogInfo($"CLR runtime version: {Environment.Version}");
 				Logger.LogInfo($"Supports SRE: {Utility.CLRSupportsDynamicAssemblies}");
+				Logger.LogInfo($"System platform: {PlatformHelper.Current}");
 
 				if (runtimePatchException != null)
 					Logger.LogWarning($"Failed to apply runtime patches for Mono. See more info in the output log. Error message: {runtimePatchException.Message}");
@@ -236,7 +237,7 @@ namespace BepInEx.Preloader
 
 		public static string GetUnityVersion()
 		{
-			if (Utility.CurrentOs == Platform.Windows)
+			if (PlatformHelper.Is(Platform.Windows))
 				return FileVersionInfo.GetVersionInfo(Paths.ExecutablePath).FileVersion;
 
 			return $"Unknown ({(IsPostUnity2017 ? "post" : "pre")}-2017)";

+ 2 - 2
BepInEx.Preloader/RuntimeFixes/XTermFix.cs

@@ -13,7 +13,7 @@ namespace BepInEx.Preloader.RuntimeFixes
 	{
 		public static void Apply()
 		{
-			if (Utility.CurrentOs == Platform.Windows)
+			if (PlatformHelper.Is(Platform.Windows))
 				return;
 
 			if (typeof(Console).Assembly.GetType("System.ConsoleDriver") == null)
@@ -34,7 +34,7 @@ namespace BepInEx.Preloader.RuntimeFixes
 			// Because Doorstop does not support ARM at the moment, we can get away with just forcing x86 detour platform.
 			// TODO: Figure out a way to detect ARM on Unix without running Process.Start
 			DetourHelper.Native = new DetourNativeX86Platform();
-
+			
 			var harmony = new HarmonyLib.Harmony("com.bepinex.xtermfix");
 
 			harmony.Patch(AccessTools.Method("System.TermInfoReader:ReadHeader"),

+ 1 - 1
BepInEx/Bootstrap/Chainloader.cs

@@ -97,7 +97,7 @@ namespace BepInEx.Bootstrap
 				Logger.Sources.Add(new UnityLogSource());
 			Logger.Listeners.Add(new UnityLogListener());
 
-			if (Utility.CurrentOs == Platform.Linux)
+			if (PlatformHelper.Is(Platform.Unix))
 			{
 				Logger.LogInfo($"Detected Unity version: v{Application.unityVersion}");
 			}

+ 6 - 13
BepInEx/Console/ConsoleManager.cs

@@ -32,20 +32,13 @@ namespace BepInEx
 
 		public static void Initialize(bool alreadyActive)
 		{
-			switch (Utility.CurrentOs)
+			if (PlatformHelper.Is(Platform.Unix))
 			{
-				case Platform.MacOS:
-				case Platform.Linux:
-				{
-					Driver = new LinuxConsoleDriver();
-					break;
-				}
-
-				case Platform.Windows:
-				{
-					Driver = new WindowsConsoleDriver();
-					break;
-				}
+				Driver = new LinuxConsoleDriver();
+			}
+			else if (PlatformHelper.Is(Platform.Windows))
+			{
+				Driver = new WindowsConsoleDriver();
 			}
 
 			Driver.Initialize(alreadyActive);

+ 1 - 1
BepInEx/Paths.cs

@@ -14,7 +14,7 @@ namespace BepInEx
 			ExecutablePath = executablePath;
 			ProcessName = Path.GetFileNameWithoutExtension(executablePath);
 
-			GameRootPath = Utility.CurrentOs == Platform.MacOS
+			GameRootPath = PlatformHelper.Is(Platform.MacOS)
 				? Utility.ParentDirectory(executablePath, 4)
 				: Path.GetDirectoryName(executablePath);
 

+ 0 - 28
BepInEx/Utility.cs

@@ -44,11 +44,6 @@ namespace BepInEx
 			sreEnabled = true;
 			return sreEnabled.Value;
 		}
-		
-		static Utility()
-		{
-			CheckPlatform();
-		}
 
 		/// <summary>
 		/// Try to perform an action.
@@ -299,28 +294,5 @@ namespace BepInEx
 				return false;
 			}
 		}
-
-		// Adapted from https://github.com/MonoMod/MonoMod.Common/blob/master/Utils/PlatformHelper.cs#L13
-		private static void CheckPlatform()
-		{
-			var pPlatform = typeof(Environment).GetProperty("Platform", BindingFlags.NonPublic | BindingFlags.Static);
-			string platId = pPlatform != null ? pPlatform.GetValue(null, new object[0]).ToString() : Environment.OSVersion.Platform.ToString();
-			platId = platId.ToLowerInvariant();
-
-			var cur = Platform.Unknown;
-			if (platId.Contains("win"))
-				cur = Platform.Windows;
-			else if (platId.Contains("mac") || platId.Contains("osx"))
-				cur = Platform.MacOS;
-			else if (platId.Contains("lin") || platId.Contains("unix"))
-				cur = Platform.Linux;
-
-			CurrentOs = cur;
-		}
-
-		/// <summary>
-		/// Current OS BepInEx is running on.
-		/// </summary>
-		public static Platform CurrentOs { get; private set; }
 	}
 }