Skip to content

Commit

Permalink
WIP on new analysis stuff. Would CI-SKIP if I could :((
Browse files Browse the repository at this point in the history
  • Loading branch information
Sam Byass committed Jul 15, 2020
1 parent c10c712 commit 20b83ec
Show file tree
Hide file tree
Showing 11 changed files with 337 additions and 79 deletions.
209 changes: 151 additions & 58 deletions Cpp2IL/Analysis/ASMAnalyzer.cs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cpp2IL/Analysis/Actions/BaseAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public BaseAction(MethodAnalysis context, Instruction instruction)

public abstract Mono.Cecil.Cil.Instruction[] ToILInstructions();

public abstract string ToPsuedoCode();
public abstract string? ToPsuedoCode();

public abstract string ToTextSummary();

Expand Down
36 changes: 36 additions & 0 deletions Cpp2IL/Analysis/Actions/RegContentCopyAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using Cpp2IL.Analysis.ResultModels;
using SharpDisasm;

namespace Cpp2IL.Analysis.Actions
{
/// <summary>
/// Action for a simple reg->reg move
/// </summary>
public class RegContentCopyAction : BaseAction
{
private IAnalysedOperand beingMoved;
private string originalReg;
private string newReg;

public RegContentCopyAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
{
}

public override Mono.Cecil.Cil.Instruction[] ToILInstructions()
{
//No-op
return new Mono.Cecil.Cil.Instruction[0];
}

public override string? ToPsuedoCode()
{
return null;
}

public override string ToTextSummary()
{
return $"Copies {beingMoved} from {originalReg} into {newReg}";
}
}
}
2 changes: 1 addition & 1 deletion Cpp2IL/Analysis/FieldInType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Cpp2IL.Analysis
public struct FieldInType : IComparable<FieldInType>
{
public string Name;
public TypeReference Type;
public TypeReference? Type;
public ulong Offset;
public bool Static;
public object Constant;
Expand Down
2 changes: 1 addition & 1 deletion Cpp2IL/Analysis/ResultModels/LocalDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace Cpp2IL.Analysis.ResultModels
public class LocalDefinition : IAnalysedOperand
{
public string Name;
public TypeDefinition Type;
public TypeDefinition? Type;
}
}
91 changes: 85 additions & 6 deletions Cpp2IL/Analysis/ResultModels/MethodAnalysis.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,98 @@
using System.Collections.Generic;
using System.Linq;
using Cpp2IL.Analysis.Actions;
using Mono.Cecil;

namespace Cpp2IL.Analysis.ResultModels
{
public class MethodAnalysis
{
public List<LocalDefinition> Locals = new List<LocalDefinition>();
public List<ConstantDefinition> Constants = new List<ConstantDefinition>();
public List<BaseAction> Actions = new List<BaseAction>();
private MethodDefinition _forMethod;
public readonly List<LocalDefinition> Locals = new List<LocalDefinition>();
public readonly List<ConstantDefinition> Constants = new List<ConstantDefinition>();
public readonly List<BaseAction> Actions = new List<BaseAction>();

private MethodDefinition _method;

private readonly Dictionary<string, IAnalysedOperand> RegisterData = new Dictionary<string, IAnalysedOperand>();
private readonly Dictionary<int, IAnalysedOperand> StackData = new Dictionary<int, IAnalysedOperand>();

internal MethodAnalysis(MethodDefinition method)
{
_method = method;

//Set up parameters in registers & as locals.
var regList = new List<string> {"rcx", "rdx", "r8", "r9"};

if (!method.IsStatic)
MakeLocal(method.DeclaringType, "this", regList.RemoveAndReturn(0));

var args = method.Parameters.ToList();
while (args.Count > 0 && regList.Count > 0)
{
var arg = args.RemoveAndReturn(0);
var dest = regList.RemoveAndReturn(0);

MakeLocal(arg.ParameterType.Resolve(), arg.Name, dest);
}

var stackIdx = 0;
while (args.Count > 0)
{
//Push remainder to stack
var arg = args.RemoveAndReturn(0);
PushToStack(MakeLocal(arg.ParameterType.Resolve(), arg.Name), stackIdx);
stackIdx += (int) Utils.GetSizeOfObject(arg.ParameterType);
}
}

public LocalDefinition MakeLocal(TypeDefinition? type, string? name = null, string? reg = null)
{
var local = new LocalDefinition
{
Name = name ?? $"local{Locals.Count}",
Type = type
};

Locals.Add(local);

if (reg != null)
RegisterData[reg] = local;

return local;
}

public IAnalysedOperand PushToStack(IAnalysedOperand operand, int pos)
{
StackData[pos] = operand;
return operand;
}

public IAnalysedOperand? GetOperandInRegister(string reg)
{
if (!RegisterData.TryGetValue(reg, out var result))
return null;

return result;
}

public LocalDefinition? GetLocalInReg(string reg)
{
if (!RegisterData.TryGetValue(reg, out var result))
return null;

if (!(result is LocalDefinition local)) return null;

return local;
}

internal MethodAnalysis(MethodDefinition forMethod)
public ConstantDefinition? GetConstantInReg(string reg)
{
_forMethod = forMethod;
if (!RegisterData.TryGetValue(reg, out var result))
return null;

if (!(result is ConstantDefinition constant)) return null;

return constant;
}
}
}
4 changes: 2 additions & 2 deletions Cpp2IL/Analysis/SafeCastResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace Cpp2IL.Analysis
{
public class SafeCastResult
{
public TypeDefinition originalType;
public string originalAlias;
public TypeDefinition? originalType;
public string? originalAlias;
public TypeDefinition castTo;
}
}
2 changes: 1 addition & 1 deletion Cpp2IL/Cpp2IL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Exe</OutputType>
<LangVersion>8</LangVersion>
<Nullable>disable</Nullable>
<Nullable>annotations</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>ubuntu-x64;win-x64;osx-x64</RuntimeIdentifiers>
</PropertyGroup>
Expand Down
9 changes: 8 additions & 1 deletion Cpp2IL/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@ public static class Extensions
{
public static T[] SubArray<T>(this T[] data, int index, int length)
{
T[] result = new T[length];
var result = new T[length];
Array.Copy(data, index, result, 0, length);
return result;
}

public static T RemoveAndReturn<T>(this List<T> data, int index)
{
var result = data[index];
data.RemoveAt(index);
return result;
}

public static string Repeat(this string source, int count)
{
var res = new StringBuilder();
Expand Down
59 changes: 51 additions & 8 deletions Cpp2IL/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using Cpp2IL.Metadata;
using Cpp2IL.PE;
using Mono.Cecil;
Expand Down Expand Up @@ -268,7 +269,7 @@ internal static string GetTypeName(Il2CppMetadata metadata, PE.PE cppAssembly, I
case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
{
var typeDef = metadata.typeDefs[type.data.classIndex];
ret = string.Empty;
ret = String.Empty;
if (fullName)
{
ret = metadata.GetStringFromIndex(typeDef.namespaceIndex);
Expand Down Expand Up @@ -380,7 +381,7 @@ public static ulong GetJumpTarget(Instruction insn, ulong start)

//Console.WriteLine(mode + " " + mode.GetType());

var num = ulong.MaxValue >> 64 - mode;
var num = UInt64.MaxValue >> 64 - mode;
return opr.Size switch
{
8 => (start + (ulong) opr.LvalSByte & num),
Expand Down Expand Up @@ -526,7 +527,7 @@ public static ulong GetOffsetFromMemoryAccess(Instruction insn, Operand op)
return num1 + insn.PC;
}

public static Tuple<TypeDefinition, string[]> TryLookupTypeDefByName(string name)
public static Tuple<TypeDefinition, string[]> TryLookupTypeDefByName(string? name)
{
if (name == null) return new Tuple<TypeDefinition, string[]>(null, new string[0]);

Expand All @@ -547,7 +548,7 @@ private static Tuple<TypeDefinition, string[]> InternalTryLookupTypeDefByName(st
if (primitiveTypeMappings.ContainsKey(name))
return new Tuple<TypeDefinition, string[]>(primitiveTypeMappings[name], new string[0]);

var definedType = SharedState.AllTypeDefinitions.Find(t => string.Equals(t.FullName, name, StringComparison.OrdinalIgnoreCase));
var definedType = SharedState.AllTypeDefinitions.Find(t => String.Equals(t.FullName, name, StringComparison.OrdinalIgnoreCase));

if (name.EndsWith("[]"))
{
Expand All @@ -574,12 +575,12 @@ private static Tuple<TypeDefinition, string[]> InternalTryLookupTypeDefByName(st

//It's possible they didn't specify a `System.` prefix
var searchString = $"System.{name}";
definedType = SharedState.AllTypeDefinitions.Find(t => string.Equals(t.FullName, searchString, StringComparison.OrdinalIgnoreCase));
definedType = SharedState.AllTypeDefinitions.Find(t => String.Equals(t.FullName, searchString, StringComparison.OrdinalIgnoreCase));

if (definedType != null) return new Tuple<TypeDefinition, string[]>(definedType, genericParams);

//Still not got one? Ok, is there only one match for non FQN?
var matches = SharedState.AllTypeDefinitions.Where(t => string.Equals(t.Name, name, StringComparison.OrdinalIgnoreCase)).ToList();
var matches = SharedState.AllTypeDefinitions.Where(t => String.Equals(t.Name, name, StringComparison.OrdinalIgnoreCase)).ToList();
if (matches.Count == 1)
definedType = matches.First();

Expand Down Expand Up @@ -758,10 +759,10 @@ public static List<Instruction> GetMethodBodyAtRawAddress(PE.PE theDll, ulong ad
return ret /*.Where(i => !i.Error).ToList()*/;
}

public static string TryGetLiteralAt(PE.PE theDll, ulong addr)
public static string? TryGetLiteralAt(PE.PE theDll, ulong addr)
{
var c = Convert.ToChar(theDll.raw[addr]);
if (char.IsLetter(c) && c < 'z') //includes uppercase
if (Char.IsLetter(c) && c < 'z') //includes uppercase
{
var isUnicode = theDll.raw[addr + 1] == 0;
var literal = new StringBuilder();
Expand Down Expand Up @@ -802,5 +803,47 @@ public static ulong GetSizeOfObject(TypeReference type)
? result
: PrimitiveSizes["IntPtr"];
}

private static readonly Regex UpscaleRegex = new Regex("(?:^|([^a-zA-Z]))e([a-z]{2})", RegexOptions.Compiled);

public static string UpscaleRegisters(string replaceIn)
{
if (replaceIn.Length < 2) return replaceIn;

//Special case the few 8-bit register: "al" => "rax" etc
if (replaceIn == "al")
return "rax";
if (replaceIn == "bl")
return "rbx";
if (replaceIn == "dl")
return "rdx";
if (replaceIn == "ax")
return "rax";
if (replaceIn == "cx" || replaceIn == "cl")
return "rcx";

//R9d, etc.
if (replaceIn[0] == 'r' && replaceIn[replaceIn.Length - 1] == 'd')
return replaceIn.Substring(0, replaceIn.Length - 1);

return UpscaleRegex.Replace(replaceIn, "$1r$2");
}

public static string GetFloatingRegister(string original)
{
switch (original)
{
case "rcx":
return "xmm0";
case "rdx":
return "xmm1";
case "r8":
return "xmm2";
case "r9":
return "xmm3";
default:
return original;
}
}
}
}

0 comments on commit 20b83ec

Please sign in to comment.