elflib
Version:
ELF file reader and writer
164 lines (163 loc) • 6.66 kB
JavaScript
import { decode } from './encoding.js';
import { HelperDataView } from './reader.js';
import * as ELF from './types/index.js';
export var RPL;
(function (RPL) {
function readFileInfoSection(section, endian) {
if (section.size < 0x60)
throw new Error('RPL_FILEINFO section is too small, must be at least 0x60 in size.');
const view = HelperDataView(new DataView(section.data.buffer), endian === ELF.Endian.Big);
const fileinfo = new ELF.RPLFileInfo();
let ix = 0;
const magic = view.readUInt16(ix).toString(16).toUpperCase();
if (magic !== 'CAFE')
throw new Error(`RPL_FILEINFO section magic number is invalid! Expected "CAFE", got "${magic}"`);
/*fileinfo.magic = magic;*/ ix += 2;
fileinfo.version = view.readUInt16(ix);
ix += 2;
fileinfo.textSize = view.readUInt32(ix);
ix += 4;
fileinfo.textAlign = view.readUInt32(ix);
ix += 4;
fileinfo.dataSize = view.readUInt32(ix);
ix += 4;
fileinfo.dataAlign = view.readUInt32(ix);
ix += 4;
fileinfo.loadSize = view.readUInt32(ix);
ix += 4;
fileinfo.loadAlign = view.readUInt32(ix);
ix += 4;
fileinfo.tempSize = view.readUInt32(ix);
ix += 4;
fileinfo.trampAdjust = view.readUInt32(ix);
ix += 4;
fileinfo.sdaBase = view.readUInt32(ix);
ix += 4;
fileinfo.sda2Base = view.readUInt32(ix);
ix += 4;
fileinfo.stackSize = view.readUInt32(ix);
ix += 4;
fileinfo.stringsOffset = view.readUInt32(ix);
ix += 4;
fileinfo.flags = view.readUInt32(ix);
ix += 4;
fileinfo.heapSize = view.readUInt32(ix);
ix += 4;
fileinfo.tagOffset = view.readUInt32(ix);
ix += 4;
fileinfo.minVersion = view.readUInt32(ix);
ix += 4;
fileinfo.compressionLevel = view.readSInt32(ix);
ix += 4;
fileinfo.trampAddition = view.readUInt32(ix);
ix += 4;
fileinfo.fileInfoPad = view.readUInt32(ix);
ix += 4;
fileinfo.cafeSdkVersion = view.readUInt32(ix);
ix += 4;
fileinfo.cafeSdkRevision = view.readUInt32(ix);
ix += 4;
fileinfo.tlsModuleIndex = view.readUInt16(ix);
ix += 2;
fileinfo.tlsAlignShift = view.readUInt16(ix);
ix += 2;
fileinfo.runtimeFileInfoSize = view.readUInt32(ix);
ix += 4;
fileinfo.strings = [];
// Section does not have strings
if (section.size === 0x60 || section.size <= fileinfo.stringsOffset)
return fileinfo;
const stringData = section.data.slice(fileinfo.stringsOffset);
const strings = {};
let strIx = 0;
for (let i = 0; i < section.size - fileinfo.stringsOffset; i++) {
if (stringData[i] === 0) {
const slen = i - strIx;
if (slen > 0)
strings[fileinfo.stringsOffset + strIx] = decode(stringData, strIx, slen);
if (slen === 0)
strings[fileinfo.stringsOffset + strIx] = '';
strIx = i + 1;
}
}
fileinfo.strings = strings;
return fileinfo;
}
RPL.readFileInfoSection = readFileInfoSection;
function isFileInfoSection(section) {
return section.type === ELF.SectionType.RPLFileInfo;
}
RPL.isFileInfoSection = isFileInfoSection;
async function packCrcSection(section, elf) {
let crcs = Buffer.alloc(elf.sections.length * section.entSize);
for (let i = 0; i < elf.sections.length; i++)
crcs.writeUInt32BE(await elf.sections[i].crc32Hash, i * section.entSize);
return crcs;
}
RPL.packCrcSection = packCrcSection;
function packFileInfoSection(section) {
const fileinfo = Buffer.alloc(section.size);
let ix = 0;
fileinfo.writeUInt16BE(section.fileinfo.magic, ix);
ix += 2;
fileinfo.writeUInt16BE(section.fileinfo.version, ix);
ix += 2;
fileinfo.writeUInt32BE(section.fileinfo.textSize, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.textAlign, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.dataSize, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.dataAlign, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.loadSize, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.loadAlign, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.tempSize, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.trampAdjust, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.sdaBase, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.sda2Base, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.stackSize, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.stringsOffset, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.flags, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.heapSize, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.tagOffset, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.minVersion, ix);
ix += 4;
fileinfo.writeInt32BE(section.fileinfo.compressionLevel, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.trampAddition, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.fileInfoPad, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.cafeSdkVersion, ix);
ix += 4;
fileinfo.writeUInt32BE(section.fileinfo.cafeSdkRevision, ix);
ix += 4;
fileinfo.writeUInt16BE(section.fileinfo.tlsModuleIndex, ix);
ix += 2;
fileinfo.writeUInt16BE(section.fileinfo.tlsAlignShift, ix);
ix += 2;
fileinfo.writeUInt32BE(section.fileinfo.runtimeFileInfoSize, ix);
ix += 4;
for (let key in section.fileinfo.strings) {
const str = section.fileinfo.strings[key];
if (fileinfo[ix] !== 0)
throw new Error(`Failed to pack ELF because of corrupt string section of index ${section.index}:\n` +
`\tString '${str}' at .strtab offset 0x${Number(key).toString(16).toUpperCase()} is overlapped by the previous string which is too long.`);
ix += fileinfo.write(str + '\0', ix);
}
return fileinfo;
}
RPL.packFileInfoSection = packFileInfoSection;
})(RPL || (RPL = {}));