Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround garbage field offset values #59

Merged
merged 1 commit into from
Dec 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions Il2CppInterop.Generator/Extensions/CustomAttributeEx.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Globalization;
using System.Linq;
using Mono.Cecil;

namespace Il2CppInterop.Generator.Extensions;
Expand All @@ -8,30 +6,42 @@ public static class CustomAttributeEx
{
public static long ExtractOffset(this ICustomAttributeProvider originalMethod)
{
return Extract(originalMethod, "AddressAttribute", "Offset");
return ExtractLong(originalMethod, "AddressAttribute", "Offset");
}

public static long ExtractRva(this ICustomAttributeProvider originalMethod)
{
return Extract(originalMethod, "AddressAttribute", "RVA");
return ExtractLong(originalMethod, "AddressAttribute", "RVA");
}

public static long ExtractToken(this ICustomAttributeProvider originalMethod)
{
return Extract(originalMethod, "TokenAttribute", "Token");
return ExtractLong(originalMethod, "TokenAttribute", "Token");
}

private static long Extract(this ICustomAttributeProvider originalMethod, string attributeName,
public static int ExtractFieldOffset(this ICustomAttributeProvider originalField)
{
return ExtractInt(originalField, "FieldOffsetAttribute", "Offset");
}

private static string Extract(this ICustomAttributeProvider originalMethod, string attributeName,
string parameterName)
{
var addressAttribute =
originalMethod.CustomAttributes.SingleOrDefault(it => it.AttributeType.Name == attributeName);
var rvaField = addressAttribute?.Fields.SingleOrDefault(it => it.Name == parameterName);
var attribute = originalMethod.CustomAttributes.SingleOrDefault(it => it.AttributeType.Name == attributeName);
var field = attribute?.Fields.SingleOrDefault(it => it.Name == parameterName);

if (rvaField?.Name == null) return 0;
if (field?.Name == null) return null;

return (string)field.Value.Argument.Value;
}

var addressString = (string)rvaField.Value.Argument.Value;
long.TryParse(addressString.Substring(2), NumberStyles.HexNumber, null, out var address);
return address;
private static long ExtractLong(this ICustomAttributeProvider originalMethod, string attributeName, string parameterName)
{
return Convert.ToInt64(Extract(originalMethod, attributeName, parameterName), 16);
}

private static int ExtractInt(this ICustomAttributeProvider originalMethod, string attributeName, string parameterName)
{
return Convert.ToInt32(Extract(originalMethod, attributeName, parameterName), 16);
}
}
8 changes: 8 additions & 0 deletions Il2CppInterop.Generator/Passes/Pass11ComputeTypeSpecifics.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Il2CppInterop.Generator.Contexts;
using Il2CppInterop.Generator.Extensions;

namespace Il2CppInterop.Generator.Passes;

Expand All @@ -18,6 +19,13 @@ private static void ComputeSpecifics(TypeRewriteContext typeContext)

foreach (var originalField in typeContext.OriginalType.Fields)
{
// Sometimes il2cpp metadata has invalid field offsets for some reason (https://github.com/SamboyCoding/Cpp2IL/issues/167)
if (originalField.ExtractFieldOffset() >= 0x8000000)
{
typeContext.ComputedTypeSpecifics = TypeRewriteContext.TypeSpecifics.NonBlittableStruct;
return;
}

if (originalField.IsStatic) continue;

var fieldType = originalField.FieldType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ public static void DoPass(RewriteGlobalContext context)
? assemblyContext.Imports.Module.IntPtr()
: assemblyContext.RewriteTypeRef(field.FieldType));

newField.Offset = Convert.ToInt32(
(string)field.CustomAttributes
.Single(it => it.AttributeType.Name == "FieldOffsetAttribute")
.Fields.Single().Argument.Value, 16);
newField.Offset = field.ExtractFieldOffset();

// Special case: bools in Il2Cpp are bytes
if (newField.FieldType.FullName == "System.Boolean")
Expand Down