Skip to content

Commit

Permalink
More generic method improvements, update array offsets for x86_64, ad…
Browse files Browse the repository at this point in the history
…d support for JA.
  • Loading branch information
Sam Byass committed Feb 17, 2021
1 parent 01bd398 commit 1d35796
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 10 deletions.
5 changes: 5 additions & 0 deletions Cpp2IL/Analysis/ASMAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,10 @@ private void CheckForSingleOpInstruction(Instruction instruction)
case Mnemonic.Jne:
Analysis.Actions.Add(new JumpIfNonZeroOrNonNullAction(Analysis, instruction));
break;
case Mnemonic.Ja:
//Jump if >
Analysis.Actions.Add(new JumpIfGreaterThanAction(Analysis, instruction));
break;
case Mnemonic.Jge:
case Mnemonic.Jae: //JNC in Ghidra
//Jump if >=
Expand Down Expand Up @@ -865,6 +869,7 @@ private void CheckForTwoOpInstruction(Instruction instruction)
Analysis.Actions.Add(new StaticFieldOffsetToRegAction(Analysis, instruction));
break;
case Mnemonic.Mov when type1 == OpKind.Memory && type0 == OpKind.Register && memR != "rip" && instruction.MemoryIndex == Register.None && memOp is LocalDefinition local && local.Type?.IsArray == true:
case Mnemonic.Lea when type1 == OpKind.Memory && type0 == OpKind.Register && memR != "rip" && instruction.MemoryIndex == Register.None && memOp is LocalDefinition local2 && local2.Type?.IsArray == true:
//Move reg, [reg+0x10]
//Reading a field from an array at a fixed offset
if (Il2CppArrayUtils.IsAtLeastFirstItemPtr(instruction.MemoryDisplacement))
Expand Down
5 changes: 5 additions & 0 deletions Cpp2IL/Analysis/Actions/CallManagedFunctionAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ public CallManagedFunctionAction(MethodAnalysis context, Instruction instruction

if (ManagedMethodBeingCalled?.ReturnType is { } returnType && returnType.FullName != "System.Void")
{
if (returnType is GenericParameter gp && _objectMethodBeingCalledOn?.Type != null)
{
returnType = MethodUtils.ResolveGenericParameterType(ManagedMethodBeingCalled, _objectMethodBeingCalledOn.Type, gp);
}

var destReg = Utils.ShouldBeInFloatingPointRegister(returnType) ? "xmm0" : "rax";
_returnedLocal = context.MakeLocal(returnType, reg: destReg);
}
Expand Down
6 changes: 5 additions & 1 deletion Cpp2IL/Analysis/Actions/ConstantArrayOffsetToRegAction.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Cpp2IL.Analysis.ResultModels;
using Iced.Intel;
using Mono.Cecil;

namespace Cpp2IL.Analysis.Actions
{
Expand All @@ -24,7 +25,10 @@ public ConstantArrayOffsetToRegAction(MethodAnalysis context, Instruction instru

//Regardless of if we have an index local, we can still work out the type of the array and make a local.
//Resolve() turns array types into non-array types
_destLocal = context.MakeLocal(_arrayLocal.Type.Resolve(), reg: destinationReg);

var elementType = _arrayLocal.Type is ArrayType at ? at.ElementType : _arrayLocal.Type.Resolve();

_destLocal = context.MakeLocal(elementType, reg: destinationReg);
}

public override Mono.Cecil.Cil.Instruction[] ToILInstructions()
Expand Down
32 changes: 32 additions & 0 deletions Cpp2IL/Analysis/Actions/JumpIfGreaterThanAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Cpp2IL.Analysis.ResultModels;
using Iced.Intel;

namespace Cpp2IL.Analysis.Actions
{
public class JumpIfGreaterThanAction : ConditionalJumpAction
{
public JumpIfGreaterThanAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
{
//All handled by base class
}

public override Mono.Cecil.Cil.Instruction[] ToILInstructions()
{
throw new System.NotImplementedException();
}

protected override string GetPseudocodeCondition()
{
//Invert condition, so <=, not >
return $"({GetArgumentOnePseudocodeValue()} <= {GetArgumentTwoPseudocodeValue()})";
}

protected override string GetTextSummaryCondition()
{
if (associatedCompare == null)
return "the compare showed that it was greater than";

return $"{associatedCompare.ArgumentOne} is greater than {associatedCompare.ArgumentTwo}";
}
}
}
38 changes: 31 additions & 7 deletions Cpp2IL/Analysis/MethodUtils.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Cpp2IL.Analysis.Actions;
using Cpp2IL.Analysis.ResultModels;
using Iced.Intel;
using LibCpp2IL;
using LibCpp2IL.Metadata;
using LibCpp2IL.Reflection;
using Mono.Cecil;

namespace Cpp2IL.Analysis
Expand Down Expand Up @@ -49,17 +47,21 @@ private static bool CheckParameters64(MethodReference method, MethodAnalysis con
actualArgs.Add(context.GetOperandInRegister("r8") ?? context.GetOperandInRegister("xmm2"));
actualArgs.Add(context.GetOperandInRegister("r9") ?? context.GetOperandInRegister("xmm3"));

if (actualArgs.FindLast(a => a is ConstantDefinition {Value: MethodReference ag} && ag.Name == method.Name && ag.DeclaringType == method.DeclaringType) is ConstantDefinition {Value: MethodReference actualGenericMethod})
method = actualGenericMethod;

var tempArgs = new List<IAnalysedOperand>();
foreach (var parameterData in method.Parameters!)
{
if (actualArgs.Count(a => a != null) == 0) return false;

var parameterType = parameterData.ParameterType;

if (parameterType is GenericParameter gp && beingCalledOn is GenericInstanceType git)
if (parameterType is GenericParameter gp)
{
var genericIdx = git.ElementType.GenericParameters.ToList().FindIndex(g => g.Name == gp.FullName);
parameterType = git.GenericArguments[genericIdx];
var temp = ResolveGenericParameterType(method, beingCalledOn, gp);
temp ??= parameterType;
parameterType = temp;
}

var arg = actualArgs.RemoveAndReturn(0);
Expand All @@ -84,7 +86,8 @@ private static bool CheckParameters64(MethodReference method, MethodAnalysis con
tempArgs.Add(arg);
}

if (failOnLeftoverArgs && actualArgs.Any(a => a != null && !context.IsEmptyRegArg(a) && !(a is LocalDefinition {KnownInitialValue: 0})))
actualArgs = actualArgs.Where(a => a != null && !context.IsEmptyRegArg(a) && !(a is LocalDefinition {KnownInitialValue: 0})).ToList();
if (failOnLeftoverArgs && actualArgs.Count > 0)
{
if (actualArgs.Count != 1 || !(actualArgs[0] is ConstantDefinition {Value: MethodReference reference}) || reference != method)
{
Expand All @@ -96,6 +99,27 @@ private static bool CheckParameters64(MethodReference method, MethodAnalysis con
return true;
}

internal static TypeReference? ResolveGenericParameterType(MethodReference method, TypeReference instance, GenericParameter gp)
{
var git = instance as GenericInstanceType;
if (git?.ElementType.GenericParameters.ToList().FindIndex(g => g.Name == gp.FullName) is { } genericIdx && genericIdx >= 0)
return git.GenericArguments[genericIdx];

if (method is GenericInstanceMethod gim && gim.ElementMethod.HasGenericParameters)
{
var p = gim.ElementMethod.GenericParameters.ToList();

if (git != null && git.ElementType.HasGenericParameters)
//Filter to generic params not specified in the type
p = p.Where(genericParam => git.ElementType.GenericParameters.All(gitP => gitP.FullName != genericParam.FullName)).ToList();

if (p.FindIndex(g => g.Name == gp.FullName) is { } methodGenericIdx && methodGenericIdx >= 0)
return gim.GenericArguments[methodGenericIdx];
}

return null;
}

private static bool CheckParameters32(Instruction associatedInstruction, MethodReference method, MethodAnalysis context, bool isInstance, TypeReference beingCalledOn, [NotNullWhen(true)] out List<IAnalysedOperand>? arguments)
{
arguments = new List<IAnalysedOperand>();
Expand Down
2 changes: 1 addition & 1 deletion Cpp2IL/Il2CppArrayUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Cpp2IL
{
public static class Il2CppArrayUtils
{
public static uint FirstItemOffset = (uint) (LibCpp2IlMain.ThePe!.is32Bit ? 0x10 : 0x28);
public static uint FirstItemOffset = (uint) (LibCpp2IlMain.ThePe!.is32Bit ? 0x10 : 0x20);
//32-bit:
//0x0: klass ptr
//0x4: monitor ptr
Expand Down
2 changes: 1 addition & 1 deletion Cpp2IL/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ private static void SaveHeaderDLLs(string outputPath)

private static ConcurrentDictionary<string, AsmDumper.TaintReason> DoAssemblyCSharpAnalysis(string methodOutputDir, List<(TypeDefinition type, List<CppMethodData> methods)> methods, KeyFunctionAddresses keyFunctionAddresses, out int total)
{
var assembly = Assemblies.Find(a => a.Name.Name == "Assembly-CSharp" || a.Name.Name == "CSharp3");
var assembly = Assemblies.Find(a => a.Name.Name == "Assembly-CSharp" || a.Name.Name == "CSharp3" || a.Name.Name == "CSharp2");

if (assembly == null)
{
Expand Down

0 comments on commit 1d35796

Please sign in to comment.