refactor(elf): carry parsed header facts into native consumers

This commit is contained in:
morluto
2026-10-26 14:08:35 +08:00
parent 9fa5a87c73
commit ba7ac7908d
4 changed files with 22 additions and 12 deletions
+4 -6
View File
@@ -92,15 +92,13 @@ const baseLimitations = (): Limitations => [
];
const headerFacts = (
bytes: Buffer,
image: BinaryContainer,
image: Extract<BinaryContainer, { format: "elf" }>,
): Pick<Report, "format" | "byte_order" | "machine" | "type" | "type_name"> => {
const little = image.byte_order === "little";
const type = little ? bytes.readUInt16LE(16) : bytes.readUInt16BE(16);
const { type } = image.elf;
return {
format: image.bits === 64 ? "elf64" : "elf32",
byte_order: image.byte_order,
machine: image.format === "elf" ? image.elf.machine : null,
machine: image.elf.machine,
type,
type_name: elfObjectTypeName(type),
};
@@ -514,7 +512,7 @@ export const parseKernelModule = (
if (compression !== null)
return unsupportedCompression(artifact, compression);
const image = readElfImage(bytes);
const facts = headerFacts(bytes, image);
const facts = headerFacts(image);
if (facts.type !== 1) return notApplicable(artifact, facts);
const sections = image.sections.filter(
(section): section is ElfSection => section.format === "elf",
+1
View File
@@ -142,6 +142,7 @@ export type BinaryContainer = BinaryContainerFacts &
readonly format: "elf";
readonly elf: {
readonly machine: number;
readonly type: number;
readonly dynamicSegments: readonly ElfDynamicSegment[];
};
}
+8 -2
View File
@@ -13,7 +13,9 @@ import { elfArchitecture } from "../../domain/elfFixedHeader.js";
import { readElfDirectoryFromBuffer } from "./NativeSectionDirectory.js";
/** Read ELF sections and file-backed program mappings without interpreting language metadata. */
export const readElfImage = (bytes: Buffer): BinaryContainer => {
export const readElfImage = (
bytes: Buffer,
): Extract<BinaryContainer, { format: "elf" }> => {
const directory = readElfDirectoryFromBuffer(bytes);
const { bits } = directory;
const reader = new BinaryReader(bytes, directory.little);
@@ -86,7 +88,11 @@ export const readElfImage = (bytes: Buffer): BinaryContainer => {
}
return {
format: "elf",
elf: { machine: directory.machine, dynamicSegments },
elf: {
machine: directory.machine,
type: directory.elf_type,
dynamicSegments,
},
architecture: architectureForElfMachine(directory.machine),
bits,
byte_order: reader.little ? "little" : "big",
@@ -52,6 +52,11 @@ export interface NativeSectionDirectory {
readonly programs: readonly ElfProgramDeclaration[];
readonly sections: readonly NativeSection[];
}
type ElfSectionDirectory = NativeSectionDirectory & {
readonly format: "elf";
readonly elf_type: number;
};
const STRUCTURE_BYTES = 16 * 1024 * 1024;
const reject = (message: string): never => {
throw new BinaryFormatFailure("malformed", message);
@@ -85,7 +90,7 @@ const request = (
/** One ELF interpretation for in-memory images and bounded descriptor-backed inspections. */
export function* readElfSectionDirectory(
fileSize: number,
): Generator<NativeReadRequest, NativeSectionDirectory, Buffer> {
): Generator<NativeReadRequest, ElfSectionDirectory, Buffer> {
const prefix = yield request(fileSize, 0n, 16n);
const headerSize = prefix[4] === 1 ? 52 : 64;
const bytes = yield request(fileSize, 0n, BigInt(headerSize));
@@ -95,7 +100,6 @@ export function* readElfSectionDirectory(
const { elfClass: bits, byteOrder, machine } = header;
const little = byteOrder === "little";
const wide = bits === 64;
const r = new BinaryReader(bytes, little);
const {
offset: program_offset,
width: program_width,
@@ -247,10 +251,11 @@ export function* readElfSectionDirectory(
return {
format: "elf",
elf_os_abi: header.osAbi,
elf_type: header.type,
bits,
little,
machine,
flags: r.u32(wide ? 48 : 36),
flags: header.flags,
...(section_names_limitation === undefined
? {}
: { section_names_limitation }),
@@ -348,7 +353,7 @@ export function* readPeSectionDirectory(
/** Borrow ELF bytes; file drivers satisfy the identical requests without loading payloads. */
export const readElfDirectoryFromBuffer = (
bytes: Buffer,
): NativeSectionDirectory => {
): ElfSectionDirectory => {
const steps = readElfSectionDirectory(bytes.length);
let next = steps.next();
while (!next.done) {