mirror of https://github.com/Xpl0itR/protodec.git
testing
This commit is contained in:
parent
d43deef033
commit
54ba50bfb4
|
@ -0,0 +1,67 @@
|
|||
// Copyright © 2024 Xpl0itR
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using SystemEx.Memory;
|
||||
|
||||
namespace LibProtodec;
|
||||
|
||||
public static class CilReader
|
||||
{
|
||||
// Temporary AOT incompatible method to fill the dictionary, TODO: replace with a source generator
|
||||
private static readonly Dictionary<int, OpCode> OpCodeLookup =
|
||||
typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static)
|
||||
.Select(field => (OpCode)field.GetValue(null)!)
|
||||
.ToDictionary(opCode => (int)(ushort)opCode.Value);
|
||||
|
||||
public static OpCode ReadCilOpCode(this ref MemoryReader reader, out int operandLength)
|
||||
{
|
||||
byte opCodeByte = reader.ReadByte();
|
||||
int opCodeInt = opCodeByte == OpCodes.Prefix1.Value
|
||||
? (opCodeByte << 8) | reader.ReadByte()
|
||||
: opCodeByte;
|
||||
|
||||
OpCode opCode = OpCodeLookup[opCodeInt];
|
||||
operandLength = SizeOf(opCode.OperandType);
|
||||
|
||||
return opCode;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int SizeOf(OperandType operandType)
|
||||
{
|
||||
switch (operandType)
|
||||
{
|
||||
case OperandType.ShortInlineBrTarget:
|
||||
case OperandType.ShortInlineI:
|
||||
case OperandType.ShortInlineVar:
|
||||
return 1;
|
||||
case OperandType.InlineVar:
|
||||
return 2;
|
||||
case OperandType.InlineBrTarget:
|
||||
case OperandType.InlineField:
|
||||
case OperandType.InlineI:
|
||||
case OperandType.InlineMethod:
|
||||
case OperandType.InlineSig:
|
||||
case OperandType.InlineString:
|
||||
case OperandType.InlineSwitch:
|
||||
case OperandType.InlineTok:
|
||||
case OperandType.InlineType:
|
||||
case OperandType.ShortInlineR:
|
||||
return 4;
|
||||
case OperandType.InlineI8:
|
||||
case OperandType.InlineR:
|
||||
return 8;
|
||||
case OperandType.InlineNone:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="8.0.0" />
|
||||
<PackageReference Include="Xpl0itR.SystemEx" Version="1.1.0" />
|
||||
<PackageReference Include="Xpl0itR.SystemEx" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -11,12 +11,14 @@ using System.Diagnostics;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using SystemEx;
|
||||
using CommunityToolkit.Diagnostics;
|
||||
using LibProtodec.Models;
|
||||
using LibProtodec.Models.Fields;
|
||||
using LibProtodec.Models.TopLevels;
|
||||
using LibProtodec.Models.Types;
|
||||
using SystemEx.Memory;
|
||||
|
||||
namespace LibProtodec;
|
||||
|
||||
|
@ -70,6 +72,8 @@ public sealed class ProtodecContext
|
|||
|
||||
Protobuf protobuf = GetProtobuf(messageClass, message, options);
|
||||
|
||||
ParseWriteToMethodTesting(messageClass);
|
||||
|
||||
FieldInfo[] idFields = messageClass.GetFields(PublicStatic);
|
||||
PropertyInfo[] properties = messageClass.GetProperties(PublicInstanceDeclared);
|
||||
|
||||
|
@ -128,6 +132,39 @@ public sealed class ProtodecContext
|
|||
return message;
|
||||
}
|
||||
|
||||
private static void ParseWriteToMethodTesting(Type messageClass)
|
||||
{
|
||||
MethodInfo writeTo = messageClass.GetMethod("WriteTo", BindingFlags.Public | BindingFlags.Instance)!;
|
||||
MemoryReader reader = new(writeTo.GetMethodBody()!.GetILAsByteArray()!);
|
||||
|
||||
int fieldToken = 0;
|
||||
while (reader.Remaining > 0)
|
||||
{
|
||||
OpCode opCode = reader.ReadCilOpCode(out int operandLength);
|
||||
if (opCode == OpCodes.Ret) // DummyDLL from il2cppdumper will only have ret in method body
|
||||
return;
|
||||
|
||||
if (opCode == OpCodes.Ldfld)
|
||||
{
|
||||
fieldToken = reader.ReadInt32LittleEndian();
|
||||
}
|
||||
else if (opCode == OpCodes.Call)
|
||||
{
|
||||
Guard.IsNotEqualTo(fieldToken, 0);
|
||||
int methodToken = reader.ReadInt32LittleEndian();
|
||||
|
||||
MethodBase? method = messageClass.Module.ResolveMethod(methodToken); // System.NotSupportedException: 'Resolving tokens is not supported on assemblies loaded by a MetadataLoadContext.'
|
||||
FieldInfo? field = messageClass.Module.ResolveField(fieldToken);
|
||||
|
||||
//TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Position += operandLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Enum ParseEnum(Type enumEnum, ParserOptions options = ParserOptions.None)
|
||||
{
|
||||
Guard.IsTrue(enumEnum.IsEnum);
|
||||
|
|
Loading…
Reference in New Issue