Files
rea/src/il2cpp/Il2cppMetadataFormat.ts
T
JANG BYUNGKUN 52d1a72af0 feat(il2cpp): link native methods and export Ghidra seeds
Link IL2CPP metadata names to native addresses and types through shared CLI/MCP workflows, with bounded queries and atomic Ghidra seed export.

Preserve the original implementation by 8rulerstar and follow-up correctness, resource, provenance, and CI dependency repairs. Verified against real Windows/Android artifacts, independent references, actual Ghidra, and focused CLI/MCP tests.

Fixes #5112.
2026-10-20 21:56:54 +08:00

67 lines
2.0 KiB
TypeScript

/** Stable machine-readable reason for each rejected input. */
export const IL2CPP_METADATA_FAILURE_REASONS = {
unsupported: ["unrecognized-magic", "unsupported-version"],
corrupt: [
"truncated-header",
"unexpected-header-size",
"section-out-of-bounds",
"section-overlap",
"record-size-mismatch",
"type-index-width",
"index-out-of-range",
"nested-type-conflict",
"declaring-type-mismatch",
"image-range-overlap",
"invalid-string",
],
} as const;
export type Il2cppMetadataFailureKind =
keyof typeof IL2CPP_METADATA_FAILURE_REASONS;
export type Il2cppMetadataFailureReason =
(typeof IL2CPP_METADATA_FAILURE_REASONS)[Il2cppMetadataFailureKind][number];
/** Distinguish inputs outside decoder coverage from damaged metadata. */
export class Il2cppMetadataFormatFailure extends Error {
readonly kind: Il2cppMetadataFailureKind;
constructor(
readonly reason: Il2cppMetadataFailureReason,
message: string,
options?: ErrorOptions,
) {
super(`${reason}: ${message}`, options);
this.name = "Il2cppMetadataFormatFailure";
this.kind = (
IL2CPP_METADATA_FAILURE_REASONS.unsupported as readonly string[]
).includes(reason)
? "unsupported"
: "corrupt";
}
}
export const checkRange = (
label: string,
start: number,
length: number,
total: number,
) => {
if (length === 0 && start >= -1 && start <= total) return;
if (start < 0 || start + length > total)
throw new Il2cppMetadataFormatFailure(
"index-out-of-range",
`${label} range [${start}, ${start + length}) is outside the ${total} available entries`,
);
};
/** Read a serialized index; the all-ones value of narrow widths means -1. */
export const readIndex = (bytes: Buffer, offset: number, width: 1 | 2 | 4) => {
if (width === 1) {
const value = bytes.readUInt8(offset);
return value === 0xff ? -1 : value;
}
if (width === 2) {
const value = bytes.readUInt16LE(offset);
return value === 0xffff ? -1 : value;
}
return bytes.readInt32LE(offset);
};