fix(il2cpp): preserve loader ownership and ABI field boundaries

Resolve pointer and scalar facts through their shared loader-aware owners before registration search or type rendering. Preserve unresolved names and attributes, read count fields at their declared width, and admit declared zero-fill registration tails without accepting unmapped bytes.

Cover relocation overlap and adjacency, loader-bound fields, ABI padding, nullable names, and CLI/MCP behavior; document format and verification limits.

Fixes #6881
Fixes #6873
Fixes #6871
This commit is contained in:
morluto committed 2026-10-24 04:42:09 +08:00
1 parent f2db494bfc
commit 52ca222bd0
14 files changed
+420 -59

No files matched your search

+21 -7
View File
@@ -1,6 +1,6 @@
import { Il2cppBinaryFormatFailure } from "./Il2cppBinaryFormat.js";
import {
readPointer,
readSlot,
readUInt32,
isMapped,
type NativeImage,
@@ -46,12 +46,26 @@ export const createTypeNamer = (
const fail = (message: string): never => {
throw new Il2cppBinaryFormatFailure("invalid-type", message);
};
const pointer = (address: bigint, label: string) =>
readPointer(image, address) ??
fail(`${label} at 0x${address.toString(16)} is not file mapped`);
const u32 = (address: bigint, label: string) =>
readUInt32(image, address) ??
fail(`${label} at 0x${address.toString(16)} is not file mapped`);
const unresolved = (address: bigint, label: string): never => {
throw new Il2cppBinaryFormatFailure(
"unsupported-pointer-encoding",
`${label} at 0x${address.toString(16)} is loader-unresolved; its stored bytes are not a resolved type value`,
);
};
const pointer = (address: bigint, label: string): bigint => {
const value = readSlot(image, address);
if (value === "unknown") return unresolved(address, label);
return (
value ?? fail(`${label} at 0x${address.toString(16)} is not file mapped`)
);
};
const u32 = (address: bigint, label: string): number => {
const value = readUInt32(image, address);
if (value === "unknown") return unresolved(address, label);
return (
value ?? fail(`${label} at 0x${address.toString(16)} is not file mapped`)
);
};
let cachedBytes = 0;
let work = 0;
const guard = (bytes: number) => {