From b630789ea3478c82cbc2edc9be048622f3a2ea51 Mon Sep 17 00:00:00 2001 From: Sam Byass Date: Mon, 7 Sep 2020 23:15:20 +0100 Subject: [PATCH] A small amount of work on actions, I'm not at a place I can do a lot of work rn --- .../GlobalMethodRefToConstantAction.cs | 23 ++++++++++++--- .../GlobalStringRefToConstantAction.cs | 14 ++++++++-- .../Actions/GlobalTypeRefToConstantAction.cs | 6 ++-- LibCpp2IL/GlobalIdentifier.cs | 15 +++++++++- LibCpp2IL/LibCpp2IlMain.cs | 28 ++----------------- 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/Cpp2IL/Analysis/Actions/GlobalMethodRefToConstantAction.cs b/Cpp2IL/Analysis/Actions/GlobalMethodRefToConstantAction.cs index 4261063e..9fcacef6 100644 --- a/Cpp2IL/Analysis/Actions/GlobalMethodRefToConstantAction.cs +++ b/Cpp2IL/Analysis/Actions/GlobalMethodRefToConstantAction.cs @@ -1,18 +1,33 @@ -using Cpp2IL.Analysis.ResultModels; +using System; +using System.Linq; +using Cpp2IL.Analysis.ResultModels; using LibCpp2IL; +using LibCpp2IL.Metadata; using Mono.Cecil; using SharpDisasm; +using SharpDisasm.Udis86; namespace Cpp2IL.Analysis.Actions { public class GlobalMethodRefToConstantAction : BaseAction { - public GlobalIdentifier GlobalRead; - public MethodDefinition ResolvedMethod; + public Il2CppMethodDefinition? MethodData; + public MethodDefinition? ResolvedMethod; public ConstantDefinition ConstantWritten; public GlobalMethodRefToConstantAction(MethodAnalysis context, Instruction instruction) : base(context, instruction) { + var globalAddress = context.MethodStart + LibCpp2ILUtils.GetOffsetFromMemoryAccess(instruction, instruction.Operands[1]); + MethodData = LibCpp2IlMain.GetMethodDefinitionByGlobalAddress(globalAddress); + var (type, genericParams) = Utils.TryLookupTypeDefByName(MethodData!.DeclaringType.FullName); + ResolvedMethod = type.Methods.FirstOrDefault(m => m.Name == MethodData.Name); + + if (ResolvedMethod == null) return; + + var destReg = instruction.Operands[0].Type == ud_type.UD_OP_REG ? Utils.GetRegisterName(instruction.Operands[0]) : null; + var name = ResolvedMethod.Name; + + ConstantWritten = context.MakeConstant(typeof(MethodDefinition), ResolvedMethod, name, destReg); } public override Mono.Cecil.Cil.Instruction[] ToILInstructions() @@ -27,7 +42,7 @@ public override string ToPsuedoCode() public override string ToTextSummary() { - throw new System.NotImplementedException(); + return $"Loads the type definition for managed method {ResolvedMethod!.FullName} as a constant \"{ConstantWritten.Name}\""; } } } \ No newline at end of file diff --git a/Cpp2IL/Analysis/Actions/GlobalStringRefToConstantAction.cs b/Cpp2IL/Analysis/Actions/GlobalStringRefToConstantAction.cs index 0d553a8b..b72bdb83 100644 --- a/Cpp2IL/Analysis/Actions/GlobalStringRefToConstantAction.cs +++ b/Cpp2IL/Analysis/Actions/GlobalStringRefToConstantAction.cs @@ -2,17 +2,25 @@ using LibCpp2IL; using Mono.Cecil; using SharpDisasm; +using SharpDisasm.Udis86; namespace Cpp2IL.Analysis.Actions { public class GlobalStringRefToConstantAction : BaseAction { - public GlobalIdentifier GlobalRead; - public string ResolvedString; + public string? ResolvedString; public ConstantDefinition ConstantWritten; public GlobalStringRefToConstantAction(MethodAnalysis context, Instruction instruction) : base(context, instruction) { + var globalAddress = context.MethodStart + LibCpp2ILUtils.GetOffsetFromMemoryAccess(instruction, instruction.Operands[1]); + ResolvedString = LibCpp2IlMain.GetLiteralByAddress(globalAddress); + + if (ResolvedString == null) return; + + var destReg = instruction.Operands[0].Type == ud_type.UD_OP_REG ? Utils.GetRegisterName(instruction.Operands[0]) : null; + + ConstantWritten = context.MakeConstant(typeof(string), ResolvedString, null, destReg); } public override Mono.Cecil.Cil.Instruction[] ToILInstructions() @@ -27,7 +35,7 @@ public override string ToPsuedoCode() public override string ToTextSummary() { - throw new System.NotImplementedException(); + return $"Loads the string literal \"{ResolvedString}\" as a constant \"{ConstantWritten.Name}\""; } } } \ No newline at end of file diff --git a/Cpp2IL/Analysis/Actions/GlobalTypeRefToConstantAction.cs b/Cpp2IL/Analysis/Actions/GlobalTypeRefToConstantAction.cs index f00fb364..c683c881 100644 --- a/Cpp2IL/Analysis/Actions/GlobalTypeRefToConstantAction.cs +++ b/Cpp2IL/Analysis/Actions/GlobalTypeRefToConstantAction.cs @@ -16,8 +16,8 @@ public class GlobalTypeRefToConstantAction : BaseAction public GlobalTypeRefToConstantAction(MethodAnalysis context, Instruction instruction) : base(context, instruction) { var globalAddress = context.MethodStart + LibCpp2ILUtils.GetOffsetFromMemoryAccess(instruction, instruction.Operands[1]); - GlobalRead = SharedState.GlobalsByOffset[globalAddress]; - var (type, genericParams) = Utils.TryLookupTypeDefByName(GlobalRead.Name); + var typeData = LibCpp2IlMain.GetTypeGlobalByAddress(globalAddress); + var (type, genericParams) = Utils.TryLookupTypeDefByName(typeData!.ToString()); ResolvedType = type; if (ResolvedType == null) return; @@ -40,7 +40,7 @@ public override string ToPsuedoCode() public override string ToTextSummary() { - return $"Loads the type definition for managed type {ResolvedType?.FullName} as a constant \"{ConstantWritten.Name}\""; + return $"Loads the type definition for managed type {ResolvedType.FullName} as a constant \"{ConstantWritten.Name}\""; } } } \ No newline at end of file diff --git a/LibCpp2IL/GlobalIdentifier.cs b/LibCpp2IL/GlobalIdentifier.cs index 05e80a24..7f368c29 100644 --- a/LibCpp2IL/GlobalIdentifier.cs +++ b/LibCpp2IL/GlobalIdentifier.cs @@ -1,4 +1,7 @@ -namespace LibCpp2IL +using LibCpp2IL.Metadata; +using LibCpp2IL.Reflection; + +namespace LibCpp2IL { public struct GlobalIdentifier { @@ -12,6 +15,16 @@ public override string ToString() return $"LibCpp2IL Global Identifier (Name = {Name}, Offset = 0x{Offset:X}, Type = {IdentifierType})"; } + public Il2CppFieldDefinition? ReferencedField => IdentifierType != Type.FIELDREF ? null + : Value is Il2CppFieldDefinition def ? def : null; + + public Il2CppTypeReflectionData? ReferencedType => IdentifierType != Type.TYPEREF ? null + : Value is Il2CppTypeReflectionData data ? data : null; + + public Il2CppMethodDefinition? ReferencedMethod => IdentifierType != Type.METHODREF ? null + : Value is Il2CppGlobalGenericMethodRef genericMethodRef ? genericMethodRef.baseMethod //TODO Can we get a specific generic variant? + : Value is Il2CppMethodDefinition definition ? definition : null; + public enum Type { TYPEREF, diff --git a/LibCpp2IL/LibCpp2IlMain.cs b/LibCpp2IL/LibCpp2IlMain.cs index 32eab761..8e5739ea 100644 --- a/LibCpp2IL/LibCpp2IlMain.cs +++ b/LibCpp2IL/LibCpp2IlMain.cs @@ -31,12 +31,7 @@ public class LibCpp2IlSettings var typeGlobal = LibCpp2IlGlobalMapper.TypeRefs.FirstOrDefault(lit => lit.Offset == address); if (typeGlobal.Offset != address) return null; - if (typeGlobal.Value is Il2CppTypeReflectionData reflectionData) - { - return reflectionData; - } - - return null; + return typeGlobal.ReferencedType; } public static Il2CppFieldDefinition? GetFieldGlobalByAddress(ulong address) @@ -46,12 +41,7 @@ public class LibCpp2IlSettings var typeGlobal = LibCpp2IlGlobalMapper.FieldRefs.FirstOrDefault(lit => lit.Offset == address); if (typeGlobal.Offset != address) return null; - if (typeGlobal.Value is Il2CppFieldDefinition fieldDefinition) - { - return fieldDefinition; - } - - return null; + return typeGlobal.ReferencedField; } public static GlobalIdentifier? GetMethodGlobalByAddress(ulong address) @@ -70,19 +60,7 @@ public class LibCpp2IlSettings if (global.Value.Offset != address) return null; - if (global.Value.Value is Il2CppGlobalGenericMethodRef genericMethodRef) - { - //TODO: This isn't quite right, there should be a way to get the specific generic reference here for specific method pointers. - return genericMethodRef.baseMethod; - } - - if (global.Value.Value is Il2CppMethodDefinition methodDefinition) - { - return methodDefinition; - } - - //Nasty fallback but we shouldn't ever get here. - return TheMetadata!.methodDefs.FirstOrDefault(type => type.GlobalKey == global.Value.Name); + return global.Value.ReferencedMethod; } ///