Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for LoongArch64 platform. #35

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MonoMod.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

<TargetFrameworks>net35;net452;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition="$(MSBuildVersion) &gt;= 16.6.0 And $(NETCoreAppMaximumVersion) &gt;= 5.0">$(TargetFrameworks);net5.0</TargetFrameworks>
<TargetFrameworks Condition="$(MSBuildVersion) &gt;= 16.6.0 And $(NETCoreAppMaximumVersion) &gt;= 6.0">$(TargetFrameworks);net6.0</TargetFrameworks>
<OutputType>Library</OutputType>

<MonoModSharedShims Condition="'$(MonoModSharedShims)' == ''">false</MonoModSharedShims>
Expand Down
3 changes: 3 additions & 0 deletions RuntimeDetour/DetourHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ public static IDetourNativePlatform Native {

IDetourNativePlatform native;


if (PlatformHelper.Is(Platform.ARM)) {
native = new DetourNativeARMPlatform();
} else if (PlatformHelper.Is(Platform.LoongArch64)) {
native = new DetourNativeLoongArch64Platform();
} else {
native = new DetourNativeX86Platform();
}
Expand Down
86 changes: 86 additions & 0 deletions RuntimeDetour/Platforms/Native/DetourNativeLoongArch64Platform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace MonoMod.RuntimeDetour.Platforms {
#if !MONOMOD_INTERNAL
public
#endif
unsafe class DetourNativeLoongArch64Platform : IDetourNativePlatform {
public enum DetourType : byte {
LoongArch64,
}

private static readonly uint[] DetourSizes = {
4 + 4 + 8,
};

public void Apply(NativeDetourData detour) {
int offs = 0;

// pcaddi $r21,3
detour.Method.Write(ref offs, (byte) 0x75);
detour.Method.Write(ref offs, (byte) 0x00);
detour.Method.Write(ref offs, (byte) 0x00);
detour.Method.Write(ref offs, (byte) 0x18);
// ld.d $r21,$r21,0
detour.Method.Write(ref offs, (byte) 0xb5);
detour.Method.Write(ref offs, (byte) 0x02);
detour.Method.Write(ref offs, (byte) 0xc0);
detour.Method.Write(ref offs, (byte) 0x28);
// jirl $r0, $r21, 0
detour.Method.Write(ref offs, (byte) 0xA0);
detour.Method.Write(ref offs, (byte) 0x02);
detour.Method.Write(ref offs, (byte) 0x00);
detour.Method.Write(ref offs, (byte) 0x4C);
// <to>
detour.Method.Write(ref offs, (ulong) detour.Target);
}

public void Copy(IntPtr src, IntPtr dst, byte type) {
*(uint*) ((long) dst) = *(uint*) ((long) src);
*(uint*) ((long) dst + 4) = *(uint*) ((long) src + 4);
*(ulong*) ((long) dst + 8) = *(ulong*) ((long) src + 8);
}

public NativeDetourData Create(IntPtr from, IntPtr to, byte? type = null) {
NativeDetourData detour = new NativeDetourData {
Method = (IntPtr) ((long) from & ~0x1),
Target = (IntPtr) ((long) to & ~0x1)
};
detour.Size = DetourSizes[0];
return detour;
}

public void FlushICache(IntPtr src, uint size) {
}

public void Free(NativeDetourData detour) {
// No extra data.
}

public void MakeExecutable(IntPtr src, uint size) {
// no-op.
}

public void MakeReadWriteExecutable(IntPtr src, uint size) {
// no-op.
}

public void MakeWritable(IntPtr src, uint size) {
// no-op.
}

public IntPtr MemAlloc(uint size) {
return Marshal.AllocHGlobal((int) size);
}

public void MemFree(IntPtr ptr) {
Marshal.FreeHGlobal(ptr);
}

private readonly byte[] _FlushCache64 = { 0x85, 0x94, 0x10, 0x00, 0x0c, 0xf0, 0xff, 0x02, 0x84, 0xb0, 0x14, 0x00, 0x85, 0x14, 0x00, 0x6c, 0x86, 0x00, 0x80, 0x03, 0x00, 0x00, 0x72, 0x38, 0xc6, 0x10, 0xc0, 0x02, 0xc5, 0xf8, 0xff, 0x6b, 0x00, 0x00, 0x72, 0x38, 0x85, 0x10, 0x00, 0x6c, 0x00, 0x00, 0x72, 0x38, 0x84, 0x10, 0xc0, 0x02, 0x85, 0xf8, 0xff, 0x6b, 0x00, 0x00, 0x72, 0x38, 0x20, 0x00, 0x00, 0x4c};
}
}
60 changes: 60 additions & 0 deletions RuntimeDetour/Platforms/Runtime/DetourRuntimeNETPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,66 @@ IntPtr WalkPrecode(IntPtr curr) {
}
}
}
} else if (PlatformHelper.Is(Platform.LoongArch64)) {
IntPtr WalkPrecode(IntPtr curr) {
long lptr = (long) curr;

if (
// StubPrecode
// https://github.com/dotnet/runtime/blob/7830fddeead7907f6dd45f814fc3b8d49cd4b082/src/coreclr/vm/arm64/cgencpu.h#L567-L572
*(uint*) (lptr + 0x00) == 0x18000095 && //pcaddi $r21,4
*(uint*) (lptr + 0x04) == 0x28c022ae && //ld.d $t2,$r21,8
*(uint*) (lptr + 0x08) == 0x28c002b5 && //ld.d $r21,$r21,0
*(uint*) (lptr + 0x0c) == 0x4c0002a0 //jirl $r0,$r21,0
) {
IntPtr next = *(IntPtr*) (lptr + 0x10);
return NotThePreStub(curr, next);
} else if (
// NDirectImportPrecode
// https://github.com/dotnet/runtime/blob/7830fddeead7907f6dd45f814fc3b8d49cd4b082/src/coreclr/vm/arm64/cgencpu.h#L628-L633
*(uint*) (lptr + 0x00) == 0x18000035 && //pcaddi $r21,1
*(uint*) (lptr + 0x04) == 0x28c052ae && //ld.d $t2,$r21,20
*(uint*) (lptr + 0x08) == 0x28c032b5 && //ld.d $r21,$r21,12
*(uint*) (lptr + 0x0c) == 0x4c0002a0 //jirl $r0,$r21,0
) {
IntPtr next = *(IntPtr*) (lptr + 0x10);
return NotThePreStub(curr, next);
} else if (
// FixupPrecode
// https://github.com/dotnet/runtime/blob/7830fddeead7907f6dd45f814fc3b8d49cd4b082/src/coreclr/vm/arm64/cgencpu.h#L666-L672
*(uint*) (lptr + 0x00) == 0x18000075 && //pcaddi $r21,3
*(uint*) (lptr + 0x04) == 0x02ffd2ae && //addi.d $t2,$r21,-12
*(uint*) (lptr + 0x08) == 0x28c012b5 && //ld.d $r21,$r21,4
*(uint*) (lptr + 0x0c) == 0x4c0002a0 //jirl $r0,$r21,0
) {
IntPtr next = *(IntPtr*) (lptr + 0x10);
return NotThePreStub(curr, next);
} else if (
// ThisPtrRetBufPrecode
// https://github.com/dotnet/runtime/blob/4da6b9a8d55913c0ea560d63590d35dc942425be/src/coreclr/vm/arm64/stubs.cpp#L641-L647
*(uint*) (lptr + 0x00) == 0x18000055 && //pcaddi r21,2
*(uint*) (lptr + 0x04) == 0x28c042b5 && //ld.d r21,16(r21)
*(uint*) (lptr + 0x08) == 0x0380008f && //ori r15,a0,0x0
*(uint*) (lptr + 0x0c) == 0x038000a4 && //ori a0,a1,0x0
*(uint*) (lptr + 0x10) == 0x038001e5 && //ori a1,r15,0x0
*(uint*) (lptr + 0x14) == 0x4c0002a0 //jirl r0,r21,0
) {
IntPtr next = *(IntPtr*) (lptr + 0x18);
return NotThePreStub(curr, next);
}

return curr;
}

int numIterations = 0;

IntPtr nextPtr = WalkPrecode(ptr);
while (nextPtr != ptr && numIterations < 16) {
numIterations++;
ptr = nextPtr;

nextPtr = WalkPrecode(ptr);
}
} else if (IntPtr.Size == 4) {
int iptr = (int) ptr;
// x86
Expand Down
5 changes: 5 additions & 0 deletions Utils/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public enum Platform : int {
/// </summary>
Wine = 1 << 17,

/// <summary>
/// On demand LoongArch64 platform bit.
/// </summary>
LoongArch64 = 1 << 18,

/// <summary>
/// Unknown OS.
/// </summary>
Expand Down
6 changes: 5 additions & 1 deletion Utils/PlatformHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,12 @@ private static void DeterminePlatform() {
_current |= (IntPtr.Size >= 8 ? Platform.Bits64 : 0);

#if NETSTANDARD
/* Detect LoongArch64, Architecture.LoongArch64 may not be recognized by other platform.
* And I found RuntimeInformation.ProcessArchitecture.HasFlag(Architecture.Arm) returns True on LoongArch64. */
if("LoongArch64" == RuntimeInformation.ProcessArchitecture.ToString())
_current |= Platform.LoongArch64;
// Detect ARM based on RuntimeInformation.
if (RuntimeInformation.ProcessArchitecture.HasFlag(Architecture.Arm) ||
else if (RuntimeInformation.ProcessArchitecture.HasFlag(Architecture.Arm) ||
RuntimeInformation.OSArchitecture.HasFlag(Architecture.Arm))
_current |= Platform.ARM;
#else
Expand Down