fix(native): separate container facts from Go metadata admission

Move ELF, PE and Mach-O container parsing into a shared native owner. Go alone selects and validates Go build-info sections, so unrelated malformed Go metadata no longer blocks Rust dependency or IL2CPP inspection. Remove the superseded Go-specific container representation and migrate all consumers. Adapted from draft PR #5510 without asserting human PR readiness.

Validation: 51 compiled CLI/MCP acceptance tests across Rust, Go and IL2CPP; 186 shared-reader tests; full check:ci passed. Three public synthetic-file probes reproduce the baseline Rust refusal and validate the fixed SDK-advertised MCP output, artifact digests and unchanged bytes. The exact zero-address nonallocated ELF case now succeeds for Rust while Go still reports invalid_format. No target execution or real compiler-artifact qualification was performed; no performance improvement is claimed.

Closes #3398
This commit is contained in:
morluto
2026-10-21 11:58:15 +08:00
parent 08f4ba99ce
commit c19c2d6723
19 changed files with 876 additions and 420 deletions
+10 -10
View File
@@ -1,10 +1,10 @@
import {
GoBinaryFormatFailure,
BinaryFormatFailure,
mappedFileOffset,
isZeroFilledSpan,
type GoFileMapping,
type GoZeroFillMapping,
} from "../go/GoBinaryContainer.js";
type FileMapping,
type ZeroFillMapping,
} from "../native/metadata/BinaryContainer.js";
import { Il2cppBinaryFormatFailure } from "./Il2cppBinaryFormat.js";
const DT_RELA = 7n,
@@ -26,8 +26,8 @@ interface RelocatedImage {
}
interface RelocationSource {
readonly image: Buffer;
readonly mappings: readonly GoFileMapping[];
readonly zeroFills: readonly GoZeroFillMapping[];
readonly mappings: readonly FileMapping[];
readonly zeroFills: readonly ZeroFillMapping[];
readonly relative: number;
readonly unknownPointerKinds: ReadonlySet<number>;
}
@@ -101,14 +101,14 @@ function* dynamicTags(image: Buffer): Generator<void, Map<bigint, bigint>> {
}
const fileOffset = (
mappings: readonly GoFileMapping[],
mappings: readonly FileMapping[],
address: bigint,
size: number,
): number | null => {
try {
return mappedFileOffset(mappings, address, size);
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure) return null;
if (cause instanceof BinaryFormatFailure) return null;
throw cause;
}
};
@@ -178,8 +178,8 @@ function* applyRelaTable(
/** Materialize relative pointers in a private copy, preserving unknown and .bss facts. */
export function* applyElfRelativeRelocationsSteps(
image: Buffer,
mappings: readonly GoFileMapping[],
zeroFills: readonly GoZeroFillMapping[],
mappings: readonly FileMapping[],
zeroFills: readonly ZeroFillMapping[],
): Generator<void, RelocatedImage> {
if (image.length < 64) throw malformed("ELF header is truncated");
const kinds = RELOCATION_KINDS.get(image.readUInt16LE(18));
+17 -17
View File
@@ -3,13 +3,13 @@ import {
validateFatSlice,
} from "../domain/apple/machoContainer.js";
import {
GoBinaryFormatFailure,
GoBinaryResourceFailure,
BinaryFormatFailure,
BinaryResourceFailure,
mappedFileOffset,
isZeroFilledSpan,
type GoBinaryContainer,
} from "../go/GoBinaryContainer.js";
import { readGoBinaryContainer } from "../go/GoBinaryImage.js";
type BinaryContainer,
} from "../native/metadata/BinaryContainer.js";
import { readBinaryContainer } from "../native/metadata/readBinaryContainer.js";
import { applyElfRelativeRelocationsSteps } from "./ElfRelocations.js";
import { Il2cppBinaryFormatFailure } from "./Il2cppBinaryFormat.js";
const MACHO_CPU = new Map([
@@ -64,7 +64,7 @@ const selectImage = (
export interface NativeImage {
readonly bytes: Buffer;
readonly container: GoBinaryContainer;
readonly container: BinaryContainer;
readonly imageBase: bigint;
readonly unresolvedPointerSlots: ReadonlySet<bigint>;
readonly zeroFillPointers: ReadonlyMap<bigint, bigint>;
@@ -75,16 +75,16 @@ export function* openImageSteps(
architecture: string | undefined,
): Generator<void, NativeImage> {
let image = selectImage(bytes, architecture);
let container: GoBinaryContainer;
let container: BinaryContainer;
try {
container = readGoBinaryContainer(image);
container = readBinaryContainer(image);
} catch (cause) {
if (cause instanceof GoBinaryResourceFailure)
if (cause instanceof BinaryResourceFailure)
throw new Il2cppBinaryFormatFailure(
"native-index-capacity",
cause.message,
);
if (cause instanceof GoBinaryFormatFailure)
if (cause instanceof BinaryFormatFailure)
throw new Il2cppBinaryFormatFailure(
cause.kind === "unsupported"
? "unsupported-container"
@@ -121,7 +121,7 @@ export function* openImageSteps(
container.zero_fills,
);
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure)
if (cause instanceof BinaryFormatFailure)
throw new Il2cppBinaryFormatFailure("malformed-container", cause.message);
throw cause;
}
@@ -172,7 +172,7 @@ export const readPointer = (
);
return image.bytes.readBigUInt64LE(offset);
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure) return null;
if (cause instanceof BinaryFormatFailure) return null;
throw cause;
}
};
@@ -195,7 +195,7 @@ export const readUInt32 = (
),
);
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure) return null;
if (cause instanceof BinaryFormatFailure) return null;
throw cause;
}
};
@@ -205,7 +205,7 @@ export const isMapped = (image: NativeImage, address: bigint, size: number) => {
mappedFileOffset(image.container.mappings, address, size);
return true;
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure) return false;
if (cause instanceof BinaryFormatFailure) return false;
throw cause;
}
};
@@ -262,7 +262,7 @@ export const hasPointerArrayCoverage = (
);
}
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure) return false;
if (cause instanceof BinaryFormatFailure) return false;
throw cause;
}
cursor += BigInt(size);
@@ -284,7 +284,7 @@ export const isExecutable = (image: NativeImage, address: bigint): boolean => {
mappedFileOffset(image.container.executable_mappings ?? [], address, 1)
);
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure) return false;
if (cause instanceof BinaryFormatFailure) return false;
throw cause;
}
};
@@ -312,7 +312,7 @@ export const readSlot = (
try {
return isZeroFilled(image, address, 8) ? 0n : readPointer(image, address);
} catch (cause) {
if (cause instanceof GoBinaryFormatFailure)
if (cause instanceof BinaryFormatFailure)
throw new Il2cppBinaryFormatFailure("malformed-container", cause.message);
throw cause;
}