Calculate and output pointers to the end of each method

This commit is contained in:
Katy Coe
2019-11-14 02:44:56 +01:00
parent 312c2f8e66
commit a880e8bd04
6 changed files with 50 additions and 26 deletions

View File

@@ -195,7 +195,7 @@ namespace Il2CppInspector
// Fixed buffers // Fixed buffers
if (field.GetCustomAttributes(FBAttribute).Any()) { if (field.GetCustomAttributes(FBAttribute).Any()) {
if (!SuppressMetadata) if (!SuppressMetadata)
sb.Append($"/* {((ulong) field.GetCustomAttributes(FBAttribute)[0].VirtualAddress).ToAddressString()} */ "); sb.Append($"/* {field.GetCustomAttributes(FBAttribute)[0].VirtualAddress.ToAddressString()} */ ");
sb.Append($"{field.FieldType.DeclaredFields[0].FieldType.CSharpName} {field.Name}[0]"); // FixedElementField sb.Append($"{field.FieldType.DeclaredFields[0].FieldType.CSharpName} {field.Name}[0]"); // FixedElementField
} }
// Regular fields // Regular fields
@@ -237,10 +237,10 @@ namespace Il2CppInspector
+ (prop.CanWrite? prop.SetMethod.CustomAttributes.Where(a => !SuppressGenerated || a.AttributeType.FullName != CGAttribute).ToString(inline: true, emitPointer: !SuppressMetadata) + (prop.CanWrite? prop.SetMethod.CustomAttributes.Where(a => !SuppressGenerated || a.AttributeType.FullName != CGAttribute).ToString(inline: true, emitPointer: !SuppressMetadata)
+ (setAccess < getAccess? prop.SetMethod.GetAccessModifierString() : "") + "set; " : "") + "}"); + (setAccess < getAccess? prop.SetMethod.GetAccessModifierString() : "") + "set; " : "") + "}");
if (!SuppressMetadata) { if (!SuppressMetadata) {
if ((prop.CanRead && prop.GetMethod.VirtualAddress != 0) || (prop.CanWrite && prop.SetMethod.VirtualAddress != 0)) if ((prop.CanRead && prop.GetMethod.VirtualAddress != null) || (prop.CanWrite && prop.SetMethod.VirtualAddress != null))
sb.Append(" // "); sb.Append(" // ");
sb.Append((prop.CanRead && prop.GetMethod.VirtualAddress != 0 ? prop.GetMethod.VirtualAddress.ToAddressString() + " " : "") sb.Append((prop.CanRead && prop.GetMethod.VirtualAddress != null ? prop.GetMethod.VirtualAddress.ToAddressString() + " " : "")
+ (prop.CanWrite && prop.SetMethod.VirtualAddress != 0 ? prop.SetMethod.VirtualAddress.ToAddressString() : "")); + (prop.CanWrite && prop.SetMethod.VirtualAddress != null ? prop.SetMethod.VirtualAddress.ToAddressString() : ""));
} }
sb.Append("\n"); sb.Append("\n");
@@ -257,7 +257,7 @@ namespace Il2CppInspector
string modifiers = evt.AddMethod?.GetModifierString(); string modifiers = evt.AddMethod?.GetModifierString();
sb.Append($"{prefix}\t{modifiers}event {evt.EventHandlerType.CSharpName} {evt.Name} {{\n"); sb.Append($"{prefix}\t{modifiers}event {evt.EventHandlerType.CSharpName} {evt.Name} {{\n");
var m = new Dictionary<string, ulong>(); var m = new Dictionary<string, (ulong, ulong)?>();
if (evt.AddMethod != null) m.Add("add", evt.AddMethod.VirtualAddress); if (evt.AddMethod != null) m.Add("add", evt.AddMethod.VirtualAddress);
if (evt.RemoveMethod != null) m.Add("remove", evt.RemoveMethod.VirtualAddress); if (evt.RemoveMethod != null) m.Add("remove", evt.RemoveMethod.VirtualAddress);
if (evt.RaiseMethod != null) m.Add("raise", evt.RaiseMethod.VirtualAddress); if (evt.RaiseMethod != null) m.Add("raise", evt.RaiseMethod.VirtualAddress);
@@ -279,7 +279,7 @@ namespace Il2CppInspector
sb.Append($"{prefix}\t{method.GetModifierString()}{method.DeclaringType.UnmangledBaseName}{method.GetTypeParametersString()}("); sb.Append($"{prefix}\t{method.GetModifierString()}{method.DeclaringType.UnmangledBaseName}{method.GetTypeParametersString()}(");
sb.Append(method.GetParametersString(!SuppressMetadata) + ")" + (method.IsAbstract? ";" : @" {}")); sb.Append(method.GetParametersString(!SuppressMetadata) + ")" + (method.IsAbstract? ";" : @" {}"));
sb.Append((!SuppressMetadata && method.VirtualAddress != 0 ? $" // {method.VirtualAddress.ToAddressString()}" : "") + "\n"); sb.Append((!SuppressMetadata && method.VirtualAddress != null ? $" // {method.VirtualAddress.ToAddressString()}" : "") + "\n");
} }
codeBlocks.Add("Constructors", sb.ToString()); codeBlocks.Add("Constructors", sb.ToString());
@@ -384,7 +384,7 @@ namespace Il2CppInspector
writer.Append($"\n{prefix}\t\t{constraint}"); writer.Append($"\n{prefix}\t\t{constraint}");
} }
writer.Append((method.IsAbstract? ";" : @" {}") + (!SuppressMetadata && method.VirtualAddress != 0 ? $" // {method.VirtualAddress.ToAddressString()}" : "") + "\n"); writer.Append((method.IsAbstract? ";" : @" {}") + (!SuppressMetadata && method.VirtualAddress != null ? $" // {method.VirtualAddress.ToAddressString()}" : "") + "\n");
return writer.ToString(); return writer.ToString();
} }

View File

@@ -38,7 +38,7 @@ namespace Il2CppInspector
public long[] FieldOffsetPointers { get; private set; } public long[] FieldOffsetPointers { get; private set; }
// Generated functions which call constructors on custom attributes // Generated functions which call constructors on custom attributes
public long[] CustomAttributeGenerators { get; private set; } public ulong[] CustomAttributeGenerators { get; private set; }
// Every defined type // Every defined type
public List<Il2CppType> Types { get; private set; } public List<Il2CppType> Types { get; private set; }
@@ -187,7 +187,7 @@ namespace Il2CppInspector
Types = image.ReadMappedObjectPointerArray<Il2CppType>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount); Types = image.ReadMappedObjectPointerArray<Il2CppType>(MetadataRegistration.ptypes, (int) MetadataRegistration.typesCount);
// Custom attribute constructors // Custom attribute constructors
CustomAttributeGenerators = Image.ReadMappedWordArray(CodeRegistration.customAttributeGenerators, (int) CodeRegistration.customAttributeCount); CustomAttributeGenerators = Image.ReadMappedArray<ulong>(CodeRegistration.customAttributeGenerators, (int) CodeRegistration.customAttributeCount);
} }
} }
} }

View File

@@ -19,6 +19,9 @@ namespace Il2CppInspector
private Il2CppBinary Binary { get; } private Il2CppBinary Binary { get; }
private Metadata Metadata { get; } private Metadata Metadata { get; }
// All method pointers sorted in ascending order (for finding the end of a method)
private List<ulong> sortedMethodPointers { get; set; }
// Shortcuts // Shortcuts
public double Version => Metadata.Version; public double Version => Metadata.Version;
@@ -43,7 +46,7 @@ namespace Il2CppInspector
public List<long> FieldOffsets { get; } public List<long> FieldOffsets { get; }
public List<Il2CppType> TypeUsages => Binary.Types; public List<Il2CppType> TypeUsages => Binary.Types;
public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules; public Dictionary<string, Il2CppCodeGenModule> Modules => Binary.Modules;
public long[] CustomAttributeGenerators => Binary.CustomAttributeGenerators; public ulong[] CustomAttributeGenerators => Binary.CustomAttributeGenerators;
// TODO: Finish all file access in the constructor and eliminate the need for this // TODO: Finish all file access in the constructor and eliminate the need for this
public IFileFormatReader BinaryImage => Binary.Image; public IFileFormatReader BinaryImage => Binary.Image;
@@ -149,33 +152,50 @@ namespace Il2CppInspector
FieldOffsets = offsets.OrderBy(x => x.Key).Select(x => x.Value).ToList(); FieldOffsets = offsets.OrderBy(x => x.Key).Select(x => x.Value).ToList();
} }
// Get sorted list of method pointers
if (Version <= 24.1)
sortedMethodPointers = Binary.GlobalMethodPointers.OrderBy(m => m).ToList();
if (Version >= 24.2)
sortedMethodPointers = Binary.ModuleMethodPointers.SelectMany(module => module.Value).OrderBy(m => m).ToList();
} }
public ulong GetMethodPointer(Il2CppCodeGenModule module, Il2CppMethodDefinition methodDef) { public (ulong Start, ulong End)? GetMethodPointer(Il2CppCodeGenModule module, Il2CppMethodDefinition methodDef) {
// Find method pointer // Find method pointer
if (methodDef.methodIndex < 0) if (methodDef.methodIndex < 0)
return 0; return null;
ulong start = 0;
// Global method pointer array // Global method pointer array
if (Version <= 24.1) { if (Version <= 24.1) {
return Binary.GlobalMethodPointers[methodDef.methodIndex] & 0xffff_ffff_ffff_fffe; start = Binary.GlobalMethodPointers[methodDef.methodIndex] & 0xffff_ffff_ffff_fffe;
} }
// Per-module method pointer array uses the bottom 24 bits of the method's metadata token // Per-module method pointer array uses the bottom 24 bits of the method's metadata token
// Derived from il2cpp::vm::MetadataCache::GetMethodPointer // Derived from il2cpp::vm::MetadataCache::GetMethodPointer
var method = (methodDef.token & 0xffffff); if (Version >= 24.2) {
if (method == 0) var method = (methodDef.token & 0xffffff);
return 0; if (method == 0)
return null;
// In the event of an exception, the method pointer is not set in the file // In the event of an exception, the method pointer is not set in the file
// This probably means it has been optimized away by the compiler, or is an unused generic method // This probably means it has been optimized away by the compiler, or is an unused generic method
try { try {
// Remove ARM Thumb marker LSB if necessary // Remove ARM Thumb marker LSB if necessary
return Binary.ModuleMethodPointers[module][method - 1] & 0xffff_ffff_ffff_fffe; start = Binary.ModuleMethodPointers[module][method - 1] & 0xffff_ffff_ffff_fffe;
}
catch (IndexOutOfRangeException) {
return null;
}
} }
catch (IndexOutOfRangeException) { }
return 0; if (start == 0)
return null;
// Consider the end of the method to be the start of the next method (or zero)
// The last method end will be wrong but there is no way to calculate it
return (start, sortedMethodPointers.FirstOrDefault(p => p > start));
} }
public static List<Il2CppInspector> LoadFromFile(string codeFile, string metadataFile) { public static List<Il2CppInspector> LoadFromFile(string codeFile, string metadataFile) {

View File

@@ -21,7 +21,9 @@ namespace Il2CppInspector.Reflection
// The type of the attribute // The type of the attribute
public TypeInfo AttributeType { get; set; } public TypeInfo AttributeType { get; set; }
public long VirtualAddress => package.CustomAttributeGenerators[Index]; public (ulong Start, ulong End)? VirtualAddress =>
// The last one will be wrong but there is no way to calculate it
(package.CustomAttributeGenerators[Index], package.CustomAttributeGenerators[Math.Min(Index + 1, package.CustomAttributeGenerators.Length - 1)]);
public override string ToString() => "[" + AttributeType.FullName + "]"; public override string ToString() => "[" + AttributeType.FullName + "]";

View File

@@ -17,7 +17,7 @@ namespace Il2CppInspector.Reflection
name = name[..suffix]; name = name[..suffix];
sb.Append($"{linePrefix}[{attributePrefix}{name}]"); sb.Append($"{linePrefix}[{attributePrefix}{name}]");
if (emitPointer) if (emitPointer)
sb.Append($" {(inline? "/*" : "//")} {((ulong)cad.VirtualAddress).ToAddressString()}{(inline? " */" : "")}"); sb.Append($" {(inline? "/*" : "//")} {cad.VirtualAddress.ToAddressString()}{(inline? " */" : "")}");
sb.Append(inline? " ":"\n"); sb.Append(inline? " ":"\n");
} }
@@ -29,6 +29,8 @@ namespace Il2CppInspector.Reflection
? string.Format($"0x{(uint)address:X8}") ? string.Format($"0x{(uint)address:X8}")
: string.Format($"0x{address:X16}"); : string.Format($"0x{address:X16}");
public static string ToAddressString(this (ulong start, ulong end)? address) => ToAddressString(address?.start ?? 0) + "-" + ToAddressString(address?.end ?? 0);
// Output a value in C#-friendly syntax // Output a value in C#-friendly syntax
public static string ToCSharpValue(this object value) { public static string ToCSharpValue(this object value) {
if (value is bool) if (value is bool)

View File

@@ -17,7 +17,7 @@ namespace Il2CppInspector.Reflection
// IL2CPP-specific data // IL2CPP-specific data
public Il2CppMethodDefinition Definition { get; } public Il2CppMethodDefinition Definition { get; }
public int Index { get; } public int Index { get; }
public ulong VirtualAddress { get; } public (ulong Start, ulong End)? VirtualAddress { get; }
// Information/flags about the method // Information/flags about the method
public MethodAttributes Attributes { get; protected set; } public MethodAttributes Attributes { get; protected set; }