Skip to content

Commit 0ac9268

Browse files
authored
Fix attributes on metadata version >= 104 (#555)
1 parent 9b6e67d commit 0ac9268

7 files changed

Lines changed: 66 additions & 13 deletions

File tree

Cpp2IL.Core/Model/Contexts/ApplicationAnalysisContext.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,17 @@ private void PopulateMethodsByAddressTable()
211211

212212
return ConcreteGenericMethodsByRef.TryGetValue(methodReference, out var context) ? context : new(methodReference, this);
213213
}
214+
215+
[return: NotNullIfNotNull(nameof(methodReference))]
216+
public MethodAnalysisContext? ResolveContextForMethod(MetadataUsage? methodReference)
217+
{
218+
return methodReference?.Type switch
219+
{
220+
null => null,
221+
MetadataUsageType.MethodDef => ResolveContextForMethod(methodReference.AsMethod()),
222+
MetadataUsageType.MethodRef => ResolveContextForMethod(methodReference.AsGenericMethodRef()),
223+
};
224+
}
214225

215226
public FieldAnalysisContext? ResolveContextForField(Il2CppFieldDefinition? field)
216227
{

Cpp2IL.Core/Model/Contexts/AssemblyAnalysisContext.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public class AssemblyAnalysisContext : HasCustomAttributesAndName
3030
/// </summary>
3131
public IEnumerable<TypeAnalysisContext> TopLevelTypes => Types.Where(t => t.DeclaringType == null);
3232

33+
/// <summary>
34+
/// The analysis context object for the manifest module of the assembly.
35+
/// </summary>
36+
public ModuleAnalysisContext ManifestModule { get; }
37+
3338
/// <summary>
3439
/// The analysis context objects for all types exported by this assembly.
3540
/// </summary>
@@ -185,6 +190,8 @@ public AssemblyAnalysisContext(Il2CppAssemblyDefinition? assemblyDefinition, App
185190

186191
Definition = assemblyDefinition;
187192

193+
ManifestModule = new(this);
194+
188195
if (AppContext.MetadataVersion >= 24.2f)
189196
CodeGenModule = AppContext.Binary.GetCodegenModuleByName(Definition.Image.Name!);
190197

Cpp2IL.Core/Model/Contexts/HasCustomAttributes.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,23 +279,20 @@ private void AnalyzeCustomAttributeDataV29()
279279

280280
//Diagnostic data
281281
var startOfData = blobStream.Position;
282-
var perAttributeStartOffsets = new Dictionary<Il2CppMethodDefinition, long>();
282+
var perAttributeStartOffsets = new Dictionary<MethodAnalysisContext, long>();
283283

284284
CustomAttributes = [];
285285
foreach (var constructor in constructors)
286286
{
287287
perAttributeStartOffsets[constructor] = blobStream.Position;
288288

289-
var attributeTypeContext = AppContext.ResolveContextForType(constructor.DeclaringType!) ?? throw new($"Unable to find type {constructor.DeclaringType!.FullName}");
290-
var attributeMethodContext = attributeTypeContext.GetMethod(constructor) ?? throw new($"Unable to find method {constructor.Name} in type {attributeTypeContext.Definition?.FullName}");
291-
292289
try
293290
{
294-
CustomAttributes.Add(V29AttributeUtils.ReadAttribute(blobStream, attributeMethodContext, AppContext));
291+
CustomAttributes.Add(V29AttributeUtils.ReadAttribute(blobStream, constructor, AppContext));
295292
}
296293
catch (Exception e)
297294
{
298-
Logger.ErrorNewline($"Failed to read attribute data for {constructor}, which has parameters {string.Join(", ", constructor.Parameters!.Select(p => p.Type))}", "CA Restore");
295+
Logger.ErrorNewline($"Failed to read attribute data for {constructor}, which has parameters {string.Join(", ", constructor.Parameters.Select(p => p.ParameterType))}", "CA Restore");
299296
Logger.ErrorNewline($"This member ({ToString()}) has {RawIl2CppCustomAttributeData.Length} bytes of data starting at 0x{GetV29BlobOffsets()!.Value.blobStart:X}", "CA Restore");
300297
Logger.ErrorNewline($"The post-constructor data started at 0x{startOfData:X} bytes into our blob", "CA Restore");
301298
Logger.ErrorNewline($"Data for this constructor started at 0x{perAttributeStartOffsets[constructor]:X} bytes into our blob, we are now 0x{blobStream.Position:X} bytes into the blob", "CA Restore");
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace Cpp2IL.Core.Model.Contexts;
2+
3+
/// <summary>
4+
/// Represents a single Module that was converted using IL2CPP.
5+
/// </summary>
6+
public class ModuleAnalysisContext : HasCustomAttributesAndName
7+
{
8+
private AssemblyAnalysisContext _assemblyContext;
9+
10+
/// <inheritdoc />
11+
override protected int CustomAttributeIndex => -1;
12+
/// <inheritdoc />
13+
public override AssemblyAnalysisContext CustomAttributeAssembly => _assemblyContext;
14+
/// <inheritdoc />
15+
public override string DefaultName => _assemblyContext.Definition!.Image.Name!;
16+
17+
public ModuleAnalysisContext(AssemblyAnalysisContext asmCtx) : base(asmCtx.Definition?.ModuleToken ?? 1, asmCtx.AppContext)
18+
{
19+
_assemblyContext = asmCtx;
20+
21+
InitCustomAttributeData();
22+
}
23+
}

Cpp2IL.Core/ProcessingLayers/AttributeAnalysisProcessingLayer.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ public override void Process(ApplicationAnalysisContext appContext, Action<int,
1414
{
1515
var total = appContext.Assemblies.Count + appContext.AllTypes.Select(t => 1 + t.Events.Count + t.Fields.Count + t.Methods.Count + t.Properties.Count).Sum();
1616

17-
int count = 0;
18-
appContext.Assemblies.ForEach(a => AnalyzeAndRaise(a, ref count, total, progressCallback));
17+
var count = 0;
18+
foreach (var a in appContext.Assemblies)
19+
{
20+
AnalyzeAndRaise(a, ref count, total, progressCallback);
21+
AnalyzeAndRaise(a.ManifestModule, ref count, total, progressCallback);
22+
}
1923

2024
//TODO look into making this parallel
2125
foreach (var type in appContext.AllTypes)

Cpp2IL.Core/Utils/AsmResolver/AsmResolverAssemblyPopulator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,9 @@ public static void PopulateCustomAttributes(AssemblyAnalysisContext asmContext)
261261
try
262262
#endif
263263
{
264-
CopyCustomAttributes(asmContext, asmContext.GetExtraData<AssemblyDefinition>("AsmResolverAssembly")!.CustomAttributes);
264+
var assembly = asmContext.GetExtraData<AssemblyDefinition>("AsmResolverAssembly")!;
265+
CopyCustomAttributes(asmContext, assembly.CustomAttributes);
266+
CopyCustomAttributes(asmContext.ManifestModule, assembly.ManifestModule!.CustomAttributes);
265267

266268
foreach (var type in asmContext.Types)
267269
{

Cpp2IL.Core/Utils/V29AttributeUtils.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Cpp2IL.Core.Utils;
1414

1515
public static class V29AttributeUtils
1616
{
17-
public static Il2CppMethodDefinition[] ReadConstructors(Stream stream, uint count, ApplicationAnalysisContext context)
17+
public static MethodAnalysisContext[] ReadConstructors(Stream stream, uint count, ApplicationAnalysisContext context)
1818
{
1919
using var reader = new BinaryReader(stream, Encoding.UTF8, true);
2020
var indices = new uint[count];
@@ -25,7 +25,10 @@ public static Il2CppMethodDefinition[] ReadConstructors(Stream stream, uint coun
2525
if (ClassReadingBinaryReader.EnableReadableSizeInformation)
2626
context.Metadata.TrackRead<AnalyzedCustomAttribute>((int)(4 * count), trackIfFinishedReading: true);
2727

28-
return indices.Select(i => context.Metadata.methodDefs[i]).ToArray(); //TODO DynWidth: Validate against v105 CA blob once we have one.
28+
if (context.Metadata.MetadataVersion >= 104)
29+
return indices.Select(i => context.ResolveContextForMethod(MetadataUsage.DecodeMetadataUsage(i, 0, context.LibCpp2IlContext)!)).ToArray();
30+
else
31+
return indices.Select(i => context.ResolveContextForMethod(context.Metadata.methodDefs[i])!).ToArray();
2932
}
3033

3134
public static AnalyzedCustomAttribute ReadAttribute(Stream stream, MethodAnalysisContext constructor, ApplicationAnalysisContext context)
@@ -83,8 +86,14 @@ private static T ResolveMemberFromIndex<T>(Stream stream, MethodAnalysisContext
8386
memberIndex = -(memberIndex + 1);
8487

8588
//Resolve type
86-
var typeDef = context.Metadata.GetTypeDefinitionFromIndex(Il2CppVariableWidthIndex<Il2CppTypeDefinition>.MakeTemporaryForFixedWidthUsage((int)typeIndex)); //DynWidth: typeIndex is already compressed, they didn't make it dynamic
87-
var typeContext = context.ResolveContextForType(typeDef) ?? throw new("Unable to find type " + typeDef);
89+
TypeAnalysisContext typeContext;
90+
if (context.Metadata.MetadataVersion >= 104)
91+
typeContext = constructor.DeclaringType!.DeclaringAssembly.ResolveIl2CppType(context.Binary.GetType(Il2CppVariableWidthIndex<Il2CppType>.MakeTemporaryForFixedWidthUsage((int)typeIndex)));
92+
else
93+
{
94+
var typeDef = context.Metadata.GetTypeDefinitionFromIndex(Il2CppVariableWidthIndex<Il2CppTypeDefinition>.MakeTemporaryForFixedWidthUsage((int)typeIndex)); //DynWidth: typeIndex is already compressed, they didn't make it dynamic
95+
typeContext = context.ResolveContextForType(typeDef) ?? throw new("Unable to find type " + typeDef);
96+
}
8897

8998
//Get member
9099
member = memberListGetter(typeContext)[memberIndex];

0 commit comments

Comments
 (0)