Files
reverse-engineering-anything/src/gpu/CudaFatbinary.ts
T
morluto 25aa298c61 fix(gpu): preserve parameter and target declarations
Decode observed V2 CUDA parameters, retain qualified PTX parameter names and entry resource counts, and preserve family and feature target declarations through selection and consistency checks.

Fixes #6624
Fixes #6625
Fixes #6626
Fixes #6618
Fixes #6613
Fixes #6606
2026-10-23 19:07:46 +08:00

88 lines
3.3 KiB
TypeScript

import type { GpuObject } from "../domain/gpu/gpuCodeObjects.js";
import { assertArtifactReadActive } from "../artifacts/ArtifactFileOperation.js";
import {
gpuCount,
nextGpuContainerOffset,
rejectGpu,
type GpuSource,
} from "./GpuSource.js";
import { gpuObject } from "./GpuObject.js";
export async function* readCudaFatbinary(
source: GpuSource,
signal?: AbortSignal,
): AsyncGenerator<GpuObject> {
let base = 0;
while (base < source.size) {
const header = await source.read(base, 16);
if (header.readUInt32LE(0) !== 0xba55ed50)
rejectGpu("Unexpected bytes between CUDA fatbinary records");
if (header.readUInt16LE(4) !== 1 || header.readUInt16LE(6) < 16)
rejectGpu("Unsupported CUDA fatbinary header");
const start = base + header.readUInt16LE(6),
length = gpuCount(header.readBigUInt64LE(8));
if (start > source.size || length > source.size - start)
rejectGpu("CUDA fatbinary extent is truncated");
const end = start + length;
for (let position = start; position < end;) {
assertArtifactReadActive(signal);
if (end - position < 64) rejectGpu("CUDA entry header is truncated");
const h = await source.read(position, 64);
const kind = h.readUInt16LE(0),
version = h.readUInt16LE(2),
width = h.readUInt32LE(4);
const padded = gpuCount(h.readBigUInt64LE(8)),
encoded = h.readUInt32LE(16),
flags = h.readBigUInt64LE(40);
if (
width < 64 ||
width > end - position ||
padded > end - position - width ||
encoded > padded
)
rejectGpu("CUDA entry extent is invalid");
const compressed = (flags & 0xa000n) !== 0n;
const row = gpuObject(source, {
offset: position + width,
size: compressed ? encoded : padded,
kind: kind === 1 ? "ptx" : kind === 2 ? "cubin" : "unknown",
metadata: { offset: position, size: width },
});
const architectureSuffix =
(flags & 0x100000n) !== 0n
? "a"
: (flags & 0x200000n) !== 0n
? "f"
: "";
row.target = `sm_${h.readUInt32LE(28)}${architectureSuffix}`;
row.raw_flags = `0x${flags.toString(16)}`;
row.compression =
(flags & 0x8000n) !== 0n && (flags & 0x2000n) === 0n
? "zstd"
: (flags & 0x2000n) !== 0n && (flags & 0x8000n) === 0n
? "lz4"
: compressed
? "unsupported"
: "none";
row.compression_id = compressed ? `cuda-flags:${row.raw_flags}` : null;
row.decoded_size = compressed ? gpuCount(h.readBigUInt64LE(56)) : padded;
if (compressed && (encoded === 0 || row.decoded_size === 0))
rejectGpu("Compressed CUDA entry has an empty declared extent");
if (version !== 0x101) {
row.compression = "unsupported";
row.target = null;
row.decoded_size = null;
row.limitations.push(
`CUDA entry version 0x${version.toString(16)} is not decoded`,
);
}
if (row.compression === "unsupported")
row.limitations.push(
"This CUDA compression/version is not supported; original encoded bytes and target declarations remain located",
);
yield row;
position += width + padded;
}
base = await nextGpuContainerOffset(source, end);
}
}