UNPKG

@bugsplat/elfy

Version:

Tiny utility for parsing ELF/SELF files.

114 lines 4.92 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ElfFile = void 0; const promises_1 = require("node:fs/promises"); const file_header_1 = require("./file-header"); const section_header_1 = require("./section-header"); class ElfFile { constructor(fileHandle) { this.fileHandle = fileHandle; } static async create(path) { const fileHandle = await (0, promises_1.open)(path, 'r'); return new ElfFile(fileHandle); } [Symbol.dispose]() { this.dispose(); } dispose() { this.fileHandle?.close(); } async tryReadSection(name) { let section = undefined; let success = true; try { section = await this.readSection(name); } catch { success = false; } return { success, section, }; } async readSection(name) { if (!this.header) { this.header = await this.readFileHeader(); } if (!this.stringTable) { this.stringTable = await this.createStringTable(); } const index = this.stringTable.indexOf(name); const found = index !== -1; if (!found) { throw new Error(`Section ${name} not found`); } const header = await this.readSectionHeader(index); const { sectionOffset, sectionSize } = header; const { buffer, bytesRead } = await this.fileHandle.read(Buffer.alloc(Number(sectionSize)), 0, Number(sectionSize), Number(sectionOffset)); if (bytesRead !== Number(sectionSize)) { throw new Error(`Could not read section ${name}`); } return buffer; } async createStringTable() { const { stringTableIndex } = this.header; const stringTableHeader = await this.readSectionHeader(stringTableIndex); const { sectionOffset, sectionSize } = stringTableHeader; const { buffer, bytesRead } = await this.fileHandle.read(Buffer.alloc(Number(sectionSize)), 0, Number(sectionSize), Number(sectionOffset)); if (bytesRead !== Number(sectionSize)) { throw new Error('Could not read string table'); } const stringTable = []; // The section names in the strings table aren't necessarily in the same order as the corresponding sections. // Read all the section headers to find the true order of the sections. for (let i = 0; i < this.header.sectionHeaderEntryCount; i++) { const { sectionNameOffset } = await this.readSectionHeader(i); const nextNull = buffer.indexOf(0x00, sectionNameOffset); const name = buffer.subarray(sectionNameOffset, nextNull).toString('utf-8'); stringTable.push(name); } return stringTable; } async readSectionHeader(i) { const { sectionHeaderOffset, sectionHeaderEntrySize } = this.header; const headerStart = Number(sectionHeaderOffset) + i * sectionHeaderEntrySize; const { buffer, bytesRead } = await this.fileHandle.read(Buffer.alloc(sectionHeaderEntrySize), 0, sectionHeaderEntrySize, headerStart); if (bytesRead !== sectionHeaderEntrySize) { throw new Error('Could not read section header'); } const sectionNameOffset = buffer.readUInt32LE(0); const sectionType = buffer.readUInt32LE(4); const sectionFlags = buffer.readBigUInt64LE(8); const sectionLoadAddress = buffer.readBigUInt64LE(16); const sectionOffset = buffer.readBigUInt64LE(24); const sectionSize = buffer.readBigUInt64LE(32); const sectionLink = buffer.readUInt32LE(40); const sectionInfo = buffer.readUInt32LE(44); const sectionAlignment = buffer.readBigUInt64LE(48); const sectionEntrySize = buffer.readBigUInt64LE(56); return new section_header_1.ElfSectionHeader(sectionNameOffset, sectionType, sectionFlags, sectionLoadAddress, sectionOffset, sectionSize, sectionLink, sectionInfo, sectionAlignment, sectionEntrySize); } async readFileHeader() { const { buffer, bytesRead } = await this.fileHandle.read(Buffer.alloc(file_header_1.lengthOf64BitElfHeader), 0, file_header_1.lengthOf64BitElfHeader, 0); if (bytesRead !== file_header_1.lengthOf64BitElfHeader) { throw new Error('Could not read ELF header'); } return file_header_1.ElfFileHeader.parse(buffer); } } exports.ElfFile = ElfFile; function splitBuffer(buffer, delimiter) { const parts = []; let start = 0; let index = 0; // Believe it or not, according to elfsharp the first part is indeed empty while ((index = buffer.indexOf(delimiter, start)) !== -1) { parts.push(buffer.subarray(start, index)); start = index + 1; } parts.push(buffer.subarray(start)); return parts; } //# sourceMappingURL=elf.js.map