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
This commit is contained in:
Bepis committed 2020-08-30 01:19:02 +10:00
1 parent ec7bd7f08a
commit 7647862bf4
9 files changed
+174 -52

No files matched your search

+7 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
-28
View File
@@ -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; }
}
}