Add FieldRva MetadataUsage type and fix current heuristic

This commit is contained in:
LukeFZ
2023-11-30 05:15:01 +01:00
parent ab841ccb2b
commit a4528e5f55
4 changed files with 96 additions and 137 deletions

View File

@@ -4,6 +4,7 @@
All rights reserved.
*/
using Il2CppInspector.Utils;
using NoisyCowStudios.Bin2Object;
using System;
using System.Collections.Generic;
@@ -184,70 +185,30 @@ namespace Il2CppInspector
var encodedToken = (uint)metadataValue;
var usage = MetadataUsage.FromEncodedIndex(this, encodedToken);
if (usage.Type > 0
&& usage.Type <= MetadataUsageType.MethodRef
&& metadataValue == (((uint)usage.Type << 29) | ((uint)usage.SourceIndex << 1)) + 1
if (CheckMetadataUsageSanity(usage)
&& BinaryImage.TryMapFileOffsetToVA(i * ((uint)BinaryImage.Bits / 8), out var va))
{
usages.Add(MetadataUsage.FromEncodedIndex(this, encodedToken, va));
usage.SetAddress(va);
usages.Add(usage);
}
}
}
return usages;
/*BinaryImage.Position = 0;
var sequenceLength = 0;
var threshold = 6000; // current versions of mscorlib generate about 6000-7000 metadata usages
var usagesCount = 0;
var words = BinaryImage.ReadArray<ulong>(0, (int) BinaryImage.Length / (BinaryImage.Bits / 8));
// Scan the image looking for a sequential block of at least 'threshold' valid metadata tokens
int pos;
for (pos = 0; pos < words.Length && (usagesCount == 0 || sequenceLength > 0); pos++) {
var word = words[pos];
if (word % 2 != 1 || word >> 32 != 0) {
sequenceLength = 0;
continue;
bool CheckMetadataUsageSanity(MetadataUsage usage)
{
return usage.Type switch
{
MetadataUsageType.TypeInfo or MetadataUsageType.Type => TypeReferences.Count > usage.SourceIndex,
MetadataUsageType.MethodDef => Methods.Length > usage.SourceIndex,
MetadataUsageType.FieldInfo or MetadataUsageType.FieldRva => FieldRefs.Length > usage.SourceIndex,
MetadataUsageType.StringLiteral => StringLiterals.Length > usage.SourceIndex,
MetadataUsageType.MethodRef => MethodSpecs.Length > usage.SourceIndex,
_ => false,
};
}
var potentialUsage = MetadataUsage.FromEncodedIndex(this, (uint) word);
switch (potentialUsage.Type) {
case MetadataUsageType.Type:
case MetadataUsageType.TypeInfo:
case MetadataUsageType.MethodDef:
case MetadataUsageType.MethodRef:
case MetadataUsageType.FieldInfo:
case MetadataUsageType.StringLiteral:
sequenceLength++;
if (sequenceLength >= threshold)
usagesCount = sequenceLength;
break;
default:
sequenceLength = 0;
break;
}
}
// If we found a block, read all the tokens and map them with their VAs to MetadataUsage objects
if (usagesCount > 0) {
var wordSize = BinaryImage.Bits / 8;
var pMetadataUsages = (uint) (pos * wordSize - (usagesCount + 1) * wordSize);
var pMetadataUsagesVA = BinaryImage.MapFileOffsetToVA(pMetadataUsages);
var usageTokens = BinaryImage.ReadWordArray(pMetadataUsages, usagesCount);
var usages = usageTokens.Zip(Enumerable.Range(0, usagesCount)
.Select(a => pMetadataUsagesVA + (ulong) (a * wordSize)), (t, a) => MetadataUsage.FromEncodedIndex(this, (uint) t, a));
Console.WriteLine("Late binding metadata usage block found successfully for metadata v27");
return usages.ToList();
}
Console.WriteLine("Late binding metadata usage block could not be auto-detected - metadata usage references will not be available for this project");
return null;*/
}
// Thumb instruction pointers have the bottom bit set to signify a switch from ARM to Thumb when jumping
private ulong getDecodedAddress(ulong addr) {

View File

@@ -1,56 +1,57 @@
/*
Copyright (c) 2019-2020 Carter Bush - https://github.com/carterbush
Copyright (c) 2020-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
Copyright 2020 Robert Xiao - https://robertxiao.ca
All rights reserved.
*/
namespace Il2CppInspector
{
public enum MetadataUsageType
{
TypeInfo = 1,
Type = 2,
MethodDef = 3,
FieldInfo = 4,
StringLiteral = 5,
MethodRef = 6,
}
public class MetadataUsage
{
public MetadataUsageType Type { get; }
public int SourceIndex { get; }
public ulong VirtualAddress { get; private set; }
public MetadataUsage(MetadataUsageType type, int sourceIndex, ulong virtualAddress = 0) {
Type = type;
SourceIndex = sourceIndex;
VirtualAddress = virtualAddress;
}
public static MetadataUsage FromEncodedIndex(Il2CppInspector package, uint encodedIndex, ulong virtualAddress = 0) {
uint index;
MetadataUsageType usageType;
if (package.Version < 19) {
/* These encoded indices appear only in vtables, and are decoded by IsGenericMethodIndex/GetDecodedMethodIndex */
var isGeneric = encodedIndex & 0x80000000;
index = package.Binary.VTableMethodReferences[encodedIndex & 0x7FFFFFFF];
usageType = (isGeneric != 0) ? MetadataUsageType.MethodRef : MetadataUsageType.MethodDef;
} else {
/* These encoded indices appear in metadata usages, and are decoded by GetEncodedIndexType/GetDecodedMethodIndex */
var encodedType = encodedIndex & 0xE0000000;
usageType = (MetadataUsageType)(encodedType >> 29);
index = encodedIndex & 0x1FFFFFFF;
// From v27 the bottom bit is set to indicate the usage token hasn't been replaced with a pointer at runtime yet
if (package.Version >= 27)
index >>= 1;
}
return new MetadataUsage(usageType, (int)index, virtualAddress);
}
public void SetAddress(ulong virtualAddress) => VirtualAddress = virtualAddress;
}
/*
Copyright (c) 2019-2020 Carter Bush - https://github.com/carterbush
Copyright (c) 2020-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
Copyright 2020 Robert Xiao - https://robertxiao.ca
All rights reserved.
*/
namespace Il2CppInspector
{
public enum MetadataUsageType
{
TypeInfo = 1,
Type = 2,
MethodDef = 3,
FieldInfo = 4,
StringLiteral = 5,
MethodRef = 6,
FieldRva = 7
}
public class MetadataUsage
{
public MetadataUsageType Type { get; }
public int SourceIndex { get; }
public ulong VirtualAddress { get; private set; }
public MetadataUsage(MetadataUsageType type, int sourceIndex, ulong virtualAddress = 0) {
Type = type;
SourceIndex = sourceIndex;
VirtualAddress = virtualAddress;
}
public static MetadataUsage FromEncodedIndex(Il2CppInspector package, uint encodedIndex, ulong virtualAddress = 0) {
uint index;
MetadataUsageType usageType;
if (package.Version < 19) {
/* These encoded indices appear only in vtables, and are decoded by IsGenericMethodIndex/GetDecodedMethodIndex */
var isGeneric = encodedIndex & 0x80000000;
index = package.Binary.VTableMethodReferences[encodedIndex & 0x7FFFFFFF];
usageType = (isGeneric != 0) ? MetadataUsageType.MethodRef : MetadataUsageType.MethodDef;
} else {
/* These encoded indices appear in metadata usages, and are decoded by GetEncodedIndexType/GetDecodedMethodIndex */
var encodedType = encodedIndex & 0xE0000000;
usageType = (MetadataUsageType)(encodedType >> 29);
index = encodedIndex & 0x1FFFFFFF;
// From v27 the bottom bit is set to indicate the usage token hasn't been replaced with a pointer at runtime yet
if (package.Version >= 27)
index >>= 1;
}
return new MetadataUsage(usageType, (int)index, virtualAddress);
}
public void SetAddress(ulong virtualAddress) => VirtualAddress = virtualAddress;
}
}