Skip to content

Commit 0799bab

Browse files
committed
clanker's attempt
1 parent 25552e0 commit 0799bab

65 files changed

Lines changed: 725 additions & 714 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cpp2IL.Core/Cpp2IlApi.cs

Lines changed: 10 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static void ConfigureLib(bool allowUserToInputAddresses)
5151
LibCpp2IlMain.Settings.MetadataFixupFunc = Cpp2IlPluginManager.MetadataFixupFuncs is { } funcs ? (originalBytes, version) =>
5252
{
5353
Logger.InfoNewline("Received request for metadata fixup from LibCpp2Il. Calling registered plugin fixup functions...");
54-
54+
5555
foreach (var func in funcs)
5656
{
5757
try
@@ -68,7 +68,7 @@ public static void ConfigureLib(bool allowUserToInputAddresses)
6868
Logger.ErrorNewline($"Metadata fixup function threw an exception: {e}. Ignoring and trying next fixup function, if any...");
6969
}
7070
}
71-
71+
7272
//only get here if every fixup function returns null or throws.
7373
return null;
7474
} : null;
@@ -89,16 +89,15 @@ public static void InitializeLibCpp2Il(string assemblyPath, string metadataPath,
8989
try
9090
{
9191
#endif
92-
if (!LibCpp2IlMain.LoadFromFile(assemblyPath, metadataPath, unityVersion))
93-
throw new Exception("Initialization with LibCpp2Il failed");
92+
var context = LibCpp2IlMain.LoadFromFileAsContext(assemblyPath, metadataPath, unityVersion);
93+
OnLibInitialized(context);
9494
#if !DEBUG
9595
}
9696
catch (Exception e)
9797
{
9898
throw new LibCpp2ILInitializationException("Fatal Exception initializing LibCpp2IL!", e);
9999
}
100100
#endif
101-
OnLibInitialized();
102101
}
103102

104103
[MemberNotNull(nameof(CurrentAppContext))]
@@ -112,27 +111,24 @@ public static void InitializeLibCpp2Il(byte[] assemblyData, byte[] metadataData,
112111

113112
try
114113
{
115-
if (!LibCpp2IlMain.Initialize(assemblyData, metadataData, unityVersion))
116-
throw new Exception("Initialization with LibCpp2Il failed");
114+
var context = LibCpp2IlMain.InitializeAsContext(assemblyData, metadataData, unityVersion);
115+
OnLibInitialized(context);
117116
}
118117
catch (Exception e)
119118
{
120119
throw new LibCpp2ILInitializationException("Fatal Exception initializing LibCpp2IL!", e);
121120
}
122-
123-
OnLibInitialized();
124121
}
125122

126123
[MemberNotNull(nameof(CurrentAppContext))]
127-
private static void OnLibInitialized()
124+
private static void OnLibInitialized(LibCpp2IlContext libContext)
128125
{
129-
MiscUtils.Init();
130-
LibCpp2IlMain.Binary!.AllCustomAttributeGenerators.ToList()
126+
libContext.Binary.AllCustomAttributeGenerators.ToList()
131127
.ForEach(ptr => SharedState.AttributeGeneratorStarts.Add(ptr));
132128

133129
var start = DateTime.Now;
134130
Logger.InfoNewline("Creating application model...");
135-
CurrentAppContext = new(LibCpp2IlMain.Binary, LibCpp2IlMain.TheMetadata!);
131+
CurrentAppContext = new(libContext.Binary, libContext.Metadata);
136132
Logger.InfoNewline($"Application model created in {(DateTime.Now - start).TotalMilliseconds}ms");
137133
}
138134

@@ -144,38 +140,11 @@ public static void ResetInternalState()
144140

145141
AsmResolverUtils.Reset();
146142

147-
LibCpp2IlMain.Reset();
148-
149143
CurrentAppContext = null;
150144
}
151145

152-
// public static void PopulateConcreteImplementations()
153-
// {
154-
// CheckLibInitialized();
155-
//
156-
// Logger.InfoNewline("Populating Concrete Implementation Table...");
157-
//
158-
// foreach (var def in LibCpp2IlMain.TheMetadata!.typeDefs)
159-
// {
160-
// if (def.IsAbstract)
161-
// continue;
162-
//
163-
// var baseTypeReflectionData = def.BaseType;
164-
// while (baseTypeReflectionData != null)
165-
// {
166-
// if (baseTypeReflectionData.baseType == null)
167-
// break;
168-
//
169-
// if (baseTypeReflectionData.isType && baseTypeReflectionData.baseType.IsAbstract && !SharedState.ConcreteImplementations.ContainsKey(baseTypeReflectionData.baseType))
170-
// SharedState.ConcreteImplementations[baseTypeReflectionData.baseType] = def;
171-
//
172-
// baseTypeReflectionData = baseTypeReflectionData.baseType.BaseType;
173-
// }
174-
// }
175-
// }
176-
177146
private static bool IsLibInitialized()
178147
{
179-
return LibCpp2IlMain.Binary != null && LibCpp2IlMain.TheMetadata != null;
148+
return CurrentAppContext != null;
180149
}
181150
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
using System;
2-
using LibCpp2IL;
1+
using System;
32

43
namespace Cpp2IL.Core.Exceptions;
54

6-
public class UnsupportedInstructionSetException : Exception
5+
public class UnsupportedInstructionSetException(string? instructionSetId = null) : Exception
76
{
8-
public override string Message => $"This action is not supported on the {LibCpp2IlMain.Binary?.InstructionSetId} instruction set yet. If running the CLI, try adding the --skip-analysis argument.";
7+
public override string Message => $"This action is not supported on the {instructionSetId ?? "unknown"} instruction set yet. If running the CLI, try adding the --skip-analysis argument.";
98
}

Cpp2IL.Core/Graphs/Processors/MetadataProcessor.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using Cpp2IL.Core.ISIL;
33
using Cpp2IL.Core.Model.Contexts;
44
using Cpp2IL.Core.Utils;
5-
using LibCpp2IL;
65

76
namespace Cpp2IL.Core.Graphs.Processors;
87

@@ -26,11 +25,11 @@ public void Process(MethodAnalysisContext methodAnalysisContext, Block block)
2625
var memoryOp = (IsilMemoryOperand)instruction.Operands[1].Data;
2726
if (memoryOp.Base == null && memoryOp.Index == null && memoryOp.Scale == 0)
2827
{
29-
var val = LibCpp2IlMain.GetLiteralByAddress((ulong)memoryOp.Addend);
28+
var val = methodAnalysisContext.AppContext.LibCpp2IlContext?.GetLiteralByAddress((ulong)memoryOp.Addend);
3029
if (val == null)
3130
{
3231
// Try instead check if its type metadata usage
33-
var metadataUsage = LibCpp2IlMain.GetTypeGlobalByAddress((ulong)memoryOp.Addend);
32+
var metadataUsage = methodAnalysisContext.AppContext.LibCpp2IlContext?.GetTypeGlobalByAddress((ulong)memoryOp.Addend);
3433
if (metadataUsage != null && methodAnalysisContext.DeclaringType is not null)
3534
{
3635
var typeAnalysisContext = metadataUsage.ToContext(methodAnalysisContext.DeclaringType!.DeclaringAssembly);

Cpp2IL.Core/Il2CppApiFunctions/Arm64KeyFunctionAddresses.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ protected override ulong GetObjectIsInstFromSystemType()
208208
//The last call is to Object::IsInst
209209

210210
Logger.Verbose($"IsInstanceOfType found at 0x{typeIsInstanceOfType.MethodPointer:X}...");
211-
var instructions = Arm64Utils.GetArm64MethodBodyAtVirtualAddress(typeIsInstanceOfType.MethodPointer, false);
211+
var instructions = Arm64Utils.GetArm64MethodBodyAtVirtualAddress(_appContext, typeIsInstanceOfType.MethodPointer, false);
212212

213213
var lastCall = instructions.LastOrDefault(i => i.Mnemonic == "bl");
214214

@@ -258,7 +258,7 @@ protected override void AttemptInstructionAnalysisToFillGaps()
258258
if (arrayTypeDef.Methods!.FirstOrDefault(m => m.Name == "GetEnumerator") is { } methodDef)
259259
{
260260
var ptr = methodDef.MethodPointer;
261-
var body = Arm64Utils.GetArm64MethodBodyAtVirtualAddress(ptr);
261+
var body = Arm64Utils.GetArm64MethodBodyAtVirtualAddress(_appContext, ptr);
262262

263263
//Looking for adrp, ldr, ldr, bl. Probably more than one - the first will be initializing the method, second will be the constructor call
264264
var probableResult = 0L;

Cpp2IL.Core/Il2CppApiFunctions/BaseKeyFunctionAddresses.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public abstract class BaseKeyFunctionAddresses
5252

5353
public IEnumerable<KeyValuePair<string, ulong>> Pairs => resolvedAddressMap;
5454

55-
private ApplicationAnalysisContext _appContext = null!; //Always initialized before used
55+
protected ApplicationAnalysisContext _appContext = null!; //Always initialized before used
5656

5757
private readonly Dictionary<string, ulong> resolvedAddressMap = [];
5858
private readonly HashSet<ulong> resolvedAddressSet = [];
@@ -131,7 +131,7 @@ protected void TryGetInitMetadataFromException()
131131
{
132132
Logger.VerboseNewline($"\t\tTarget Method Located at {targetMethod.MethodPointer}. Taking first CALL as the (version-specific) metadata initialization function...");
133133

134-
var disasm = X86Utils.GetMethodBodyAtVirtAddressNew(targetMethod.MethodPointer, false);
134+
var disasm = X86Utils.GetMethodBodyAtVirtAddressNew(targetMethod.MethodPointer, false, _appContext.Binary);
135135
var calls = disasm.Where(i => i.Mnemonic == Mnemonic.Call).ToList();
136136

137137
if (calls.Count == 0)

Cpp2IL.Core/Il2CppApiFunctions/NewArm64KeyFunctionAddresses.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using Disarm;
55
using Cpp2IL.Core.Logging;
66
using Cpp2IL.Core.Utils;
7-
using LibCpp2IL;
87
using LibCpp2IL.Reflection;
98

109
namespace Cpp2IL.Core.Il2CppApiFunctions;
@@ -17,8 +16,9 @@ private List<Arm64Instruction> DisassembleTextSection()
1716
{
1817
if (_cachedDisassembledBytes == null)
1918
{
20-
var toDisasm = LibCpp2IlMain.Binary!.GetEntirePrimaryExecutableSection();
21-
_cachedDisassembledBytes = Disassembler.Disassemble(toDisasm, LibCpp2IlMain.Binary.GetVirtualAddressOfPrimaryExecutableSection(), new(true, true, false)).ToList();
19+
var binary = _appContext.Binary;
20+
var toDisasm = binary.GetEntirePrimaryExecutableSection();
21+
_cachedDisassembledBytes = Disassembler.Disassemble(toDisasm, binary.GetVirtualAddressOfPrimaryExecutableSection(), new(true, true, false)).ToList();
2222
}
2323

2424
return _cachedDisassembledBytes;
@@ -37,13 +37,14 @@ protected override IEnumerable<ulong> FindAllThunkFunctions(ulong addr, uint max
3737
if (addressesToIgnore.Contains(matchingJmp.Address)) continue;
3838

3939
//Find this instruction in the raw file
40-
var offsetInPe = (ulong)LibCpp2IlMain.Binary!.MapVirtualAddressToRaw(matchingJmp.Address);
41-
if (offsetInPe == 0 || offsetInPe == (ulong)(LibCpp2IlMain.Binary.RawLength - 1))
40+
var binary = _appContext.Binary;
41+
var offsetInPe = (ulong)binary.MapVirtualAddressToRaw(matchingJmp.Address);
42+
if (offsetInPe == 0 || offsetInPe == (ulong)(binary.RawLength - 1))
4243
continue;
4344

4445
//get next and previous bytes
45-
var previousByte = LibCpp2IlMain.Binary.GetByteAtRawAddress(offsetInPe - 1);
46-
var nextByte = LibCpp2IlMain.Binary.GetByteAtRawAddress(offsetInPe + 4);
46+
var previousByte = binary.GetByteAtRawAddress(offsetInPe - 1);
47+
var nextByte = binary.GetByteAtRawAddress(offsetInPe + 4);
4748

4849
//Double-cc = thunk
4950
if (previousByte == 0xCC && nextByte == 0xCC)
@@ -60,7 +61,7 @@ protected override IEnumerable<ulong> FindAllThunkFunctions(ulong addr, uint max
6061
//Move to next jmp
6162
break;
6263

63-
if (LibCpp2IlMain.Binary.GetByteAtRawAddress(offsetInPe - backtrack) == 0xCC)
64+
if (binary.GetByteAtRawAddress(offsetInPe - backtrack) == 0xCC)
6465
{
6566
yield return matchingJmp.Address - (backtrack - 1);
6667
break;
@@ -86,7 +87,7 @@ protected override ulong GetObjectIsInstFromSystemType()
8687
//The last call is to Object::IsInst
8788

8889
Logger.Verbose($"IsInstanceOfType found at 0x{typeIsInstanceOfType.MethodPointer:X}...");
89-
var instructions = NewArm64Utils.GetArm64MethodBodyAtVirtualAddress(typeIsInstanceOfType.MethodPointer, true);
90+
var instructions = NewArm64Utils.GetArm64MethodBodyAtVirtualAddress(_appContext.Binary, typeIsInstanceOfType.MethodPointer, true);
9091

9192
var lastCall = instructions.LastOrDefault(i => i.Mnemonic == Arm64Mnemonic.BL);
9293

@@ -102,7 +103,7 @@ protected override ulong GetObjectIsInstFromSystemType()
102103

103104
protected override ulong FindFunctionThisIsAThunkOf(ulong thunkPtr, bool prioritiseCall = false)
104105
{
105-
var instructions = NewArm64Utils.GetArm64MethodBodyAtVirtualAddress(thunkPtr, true);
106+
var instructions = NewArm64Utils.GetArm64MethodBodyAtVirtualAddress(_appContext.Binary, thunkPtr, true);
106107

107108
var target = prioritiseCall ? Arm64Mnemonic.BL : Arm64Mnemonic.B;
108109
var matchingCall = instructions.FirstOrDefault(i => i.Mnemonic == target);

Cpp2IL.Core/Il2CppApiFunctions/X86KeyFunctionAddresses.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using Cpp2IL.Core.Model.Contexts;
66
using Cpp2IL.Core.Utils;
77
using Iced.Intel;
8-
using LibCpp2IL;
98
using LibCpp2IL.Reflection;
109

1110
namespace Cpp2IL.Core.Il2CppApiFunctions;
@@ -18,8 +17,9 @@ private InstructionList DisassembleTextSection()
1817
{
1918
if (_cachedDisassembledBytes == null)
2019
{
21-
var toDisasm = LibCpp2IlMain.Binary!.GetEntirePrimaryExecutableSection();
22-
_cachedDisassembledBytes = X86Utils.Disassemble(toDisasm, LibCpp2IlMain.Binary.GetVirtualAddressOfPrimaryExecutableSection());
20+
var binary = _appContext.Binary;
21+
var toDisasm = binary.GetEntirePrimaryExecutableSection();
22+
_cachedDisassembledBytes = X86Utils.Disassemble(toDisasm, binary.GetVirtualAddressOfPrimaryExecutableSection(), binary.is32Bit);
2323
}
2424

2525
return _cachedDisassembledBytes;
@@ -45,13 +45,14 @@ protected override IEnumerable<ulong> FindAllThunkFunctions(ulong addr, uint max
4545
if (addressesToIgnore.Contains(matchingJmp.IP)) continue;
4646

4747
//Find this instruction in the raw file
48-
var offsetInPe = (ulong)LibCpp2IlMain.Binary!.MapVirtualAddressToRaw(matchingJmp.IP);
49-
if (offsetInPe == 0 || offsetInPe == (ulong)(LibCpp2IlMain.Binary!.RawLength - 1))
48+
var binary = _appContext.Binary;
49+
var offsetInPe = (ulong)binary.MapVirtualAddressToRaw(matchingJmp.IP);
50+
if (offsetInPe == 0 || offsetInPe == (ulong)(binary.RawLength - 1))
5051
continue;
5152

5253
//get next and previous bytes
53-
var previousByte = LibCpp2IlMain.Binary.GetByteAtRawAddress(offsetInPe - 1);
54-
var nextByte = LibCpp2IlMain.Binary.GetByteAtRawAddress(offsetInPe + (ulong)matchingJmp.Length);
54+
var previousByte = binary.GetByteAtRawAddress(offsetInPe - 1);
55+
var nextByte = binary.GetByteAtRawAddress(offsetInPe + (ulong)matchingJmp.Length);
5556

5657
//Double-cc = thunk
5758
if (previousByte == 0xCC && nextByte == 0xCC)
@@ -68,7 +69,7 @@ protected override IEnumerable<ulong> FindAllThunkFunctions(ulong addr, uint max
6869
//Move to next jmp
6970
break;
7071

71-
if (LibCpp2IlMain.Binary!.GetByteAtRawAddress(offsetInPe - backtrack) == 0xCC)
72+
if (binary.GetByteAtRawAddress(offsetInPe - backtrack) == 0xCC)
7273
{
7374
yield return matchingJmp.IP - (backtrack - 1);
7475
break;
@@ -94,7 +95,7 @@ protected override ulong GetObjectIsInstFromSystemType()
9495
//The last call is to Object::IsInst
9596

9697
Logger.Verbose($"IsInstanceOfType found at 0x{typeIsInstanceOfType.MethodPointer:X}...");
97-
var instructions = X86Utils.GetMethodBodyAtVirtAddressNew(typeIsInstanceOfType.MethodPointer, true);
98+
var instructions = X86Utils.GetMethodBodyAtVirtAddressNew(typeIsInstanceOfType.MethodPointer, true, _appContext.Binary);
9899

99100
var lastCall = instructions.LastOrDefault(i => i.Mnemonic == Mnemonic.Call);
100101

@@ -110,7 +111,7 @@ protected override ulong GetObjectIsInstFromSystemType()
110111

111112
protected override ulong FindFunctionThisIsAThunkOf(ulong thunkPtr, bool prioritiseCall = false)
112113
{
113-
var instructions = X86Utils.GetMethodBodyAtVirtAddressNew(thunkPtr, true);
114+
var instructions = X86Utils.GetMethodBodyAtVirtAddressNew(thunkPtr, true, _appContext.Binary);
114115

115116
var target = prioritiseCall ? Mnemonic.Call : Mnemonic.Jmp;
116117
var matchingCall = instructions.FirstOrDefault(i => i.Mnemonic == target);

Cpp2IL.Core/Il2CppArrayUtils.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Linq;
44
using LibCpp2IL;
@@ -7,7 +7,7 @@ namespace Cpp2IL.Core;
77

88
public static class Il2CppArrayUtils
99
{
10-
public static uint FirstItemOffset = (uint)(LibCpp2IlMain.Binary!.is32Bit ? 0x10 : 0x20);
10+
public static uint GetFirstItemOffset(Il2CppBinary binary) => (uint)(binary.is32Bit ? 0x10 : 0x20);
1111
//32-bit:
1212
//0x0: klass ptr
1313
//0x4: monitor ptr
@@ -23,21 +23,21 @@ public static class Il2CppArrayUtils
2323
new UsefulOffset("length", 0x18, typeof(int), false)
2424
];
2525

26-
public static string? GetOffsetName(uint offset)
26+
public static string? GetOffsetName(uint offset, Il2CppBinary binary)
2727
{
28-
var is32Bit = LibCpp2IlMain.Binary!.is32Bit;
28+
var is32Bit = binary.is32Bit;
2929

3030
return UsefulOffsets.FirstOrDefault(o => o.is32Bit == is32Bit && o.offset == offset)?.name;
3131
}
3232

33-
public static bool IsIl2cppLengthAccessor(uint offset)
33+
public static bool IsIl2cppLengthAccessor(uint offset, Il2CppBinary binary)
3434
{
35-
return GetOffsetName(offset) == "length";
35+
return GetOffsetName(offset, binary) == "length";
3636
}
3737

38-
public static bool IsAtLeastFirstItemPtr(uint offset)
38+
public static bool IsAtLeastFirstItemPtr(uint offset, Il2CppBinary binary)
3939
{
40-
return offset >= FirstItemOffset;
40+
return offset >= GetFirstItemOffset(binary);
4141
}
4242

4343
public class UsefulOffset(string name, uint offset, Type type, bool is32Bit)

0 commit comments

Comments
 (0)