Skip to content

Commit 8f41b21

Browse files
committed
Make missing IL2CPP exports throw errors only when invoked
1 parent 4cc0074 commit 8f41b21

File tree

4 files changed

+43
-46
lines changed

4 files changed

+43
-46
lines changed

lib/exports.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -527,15 +527,26 @@ namespace Il2Cpp {
527527
getter(Il2Cpp, "memorySnapshotExports", () => new CModule($inline_file("cmodules/memory-snapshot.c")), lazy);
528528

529529
function r<R extends NativeFunctionReturnType, A extends NativeFunctionArgumentType[] | []>(exportName: `il2cpp_${string}`, retType: R, argTypes: A) {
530-
const handle = Il2Cpp.$config.exports?.[exportName]?.() ?? Il2Cpp.module.findExportByName(exportName) ?? memorySnapshotExports[exportName];
531-
532-
const target = new NativeFunction(handle ?? raise(`couldn't resolve export ${exportName}`), retType, argTypes);
533-
534-
if (target.isNull()) {
535-
raise(`export ${exportName} points to NULL IL2CPP library has likely been stripped, obfuscated, or customized`);
536-
}
537-
538-
return target;
530+
const handle: NativePointer | null | undefined =
531+
Il2Cpp.$config.exports?.[exportName]?.() ?? Il2Cpp.module.findExportByName(exportName) ?? memorySnapshotExports[exportName];
532+
533+
const target = new NativeFunction(handle ?? NULL, retType, argTypes);
534+
535+
return target.isNull()
536+
? new Proxy(target, {
537+
get(value: typeof target, name: keyof typeof target) {
538+
const property = value[name];
539+
return typeof property === "function" ? property.bind(value) : property;
540+
},
541+
apply() {
542+
if (handle == null) {
543+
raise(`couldn't resolve export ${exportName}`);
544+
} else if (handle.isNull()) {
545+
raise(`export ${exportName} points to NULL IL2CPP library has likely been stripped, obfuscated, or customized`);
546+
}
547+
}
548+
})
549+
: target;
539550
}
540551

541552
declare const $inline_file: typeof import("ts-transformer-inline-file").$INLINE_FILE;

lib/structs/assembly.ts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,27 @@ namespace Il2Cpp {
33
export class Assembly extends NativeStruct {
44
/** Gets the image of this assembly. */
55
get image(): Il2Cpp.Image {
6-
let get = function (this: Il2Cpp.Assembly) {
7-
return new Il2Cpp.Image(Il2Cpp.exports.assemblyGetImage(this));
8-
};
9-
10-
try {
11-
Il2Cpp.exports.assemblyGetImage;
12-
} catch (_) {
13-
get = function (this: Il2Cpp.Assembly) {
14-
// We need to get the System.Reflection.Module of the current assembly;
15-
// System.Reflection.Assembly::GetModulesInternal, for some reason,
16-
// throws a NullReferenceExceptionin Unity 5.3.8f1, so we must rely on
17-
// System.Type::get_Module instead.
18-
// Now we need to get any System.Type of this assembly.
19-
// We cannot use System.Reflection.Assembly::GetTypes because it may
20-
// return an empty array; hence we use System.Reflection.Assembly::GetType
21-
// to retrieve <Module>, a class/type that seems to be always present
22-
// (despite being excluded from System.Reflection.Assembly::GetTypes).
23-
return new Il2Cpp.Image(
24-
this.object
25-
.method<Il2Cpp.Object>("GetType", 1)
26-
.invoke(Il2Cpp.string("<Module>"))
27-
.method<Il2Cpp.Object>("get_Module")
28-
.invoke()
29-
.field<NativePointer>("_impl").value
30-
);
31-
};
6+
if (Il2Cpp.exports.assemblyGetImage.isNull()) {
7+
// We need to get the System.Reflection.Module of the current assembly;
8+
// System.Reflection.Assembly::GetModulesInternal, for some reason,
9+
// throws a NullReferenceExceptionin Unity 5.3.8f1, so we must rely on
10+
// System.Type::get_Module instead.
11+
// Now we need to get any System.Type of this assembly.
12+
// We cannot use System.Reflection.Assembly::GetTypes because it may
13+
// return an empty array; hence we use System.Reflection.Assembly::GetType
14+
// to retrieve <Module>, a class/type that seems to be always present
15+
// (despite being excluded from System.Reflection.Assembly::GetTypes).
16+
return new Il2Cpp.Image(
17+
this.object
18+
.method<Il2Cpp.Object>("GetType", 1)
19+
.invoke(Il2Cpp.string("<Module>"))
20+
.method<Il2Cpp.Object>("get_Module")
21+
.invoke()
22+
.field<NativePointer>("_impl").value
23+
);
3224
}
3325

34-
getter(Il2Cpp.Assembly.prototype, "image", get, lazy);
35-
36-
return this.image;
26+
return new Il2Cpp.Image(Il2Cpp.exports.assemblyGetImage(this));
3727
}
3828

3929
/** Gets the name of this assembly. */

lib/structs/thread.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,7 @@ namespace Il2Cpp {
133133
/** Gets the attached threads. */
134134
export declare const attachedThreads: Il2Cpp.Thread[];
135135
getter(Il2Cpp, "attachedThreads", () => {
136-
try {
137-
Il2Cpp.exports.threadGetAttachedThreads;
138-
} catch (error: any) {
139-
if (error.name != "Il2CppError") throw error;
140-
136+
if (Il2Cpp.exports.threadGetAttachedThreads.isNull()) {
141137
const currentThreadHandle = Il2Cpp.currentThread?.handle ?? raise("Current thread is not attached to IL2CPP");
142138
const pattern = currentThreadHandle.toMatchPattern();
143139

lib/structs/type.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,11 @@ namespace Il2Cpp {
161161
}
162162

163163
is(other: Il2Cpp.Type): boolean {
164-
try {
165-
return !!Il2Cpp.exports.typeEquals(this, other);
166-
} catch (_) {
164+
if (Il2Cpp.exports.typeEquals.isNull()) {
167165
return this.object.method<boolean>("Equals").invoke(other.object);
168166
}
167+
168+
return !!Il2Cpp.exports.typeEquals(this, other);
169169
}
170170

171171
/** */

0 commit comments

Comments
 (0)