Skip to content

Instantly share code, notes, and snippets.

@yurydelendik
Created October 7, 2015 01:25
Show Gist options
  • Save yurydelendik/0c9898b3b9063dbd29f8 to your computer and use it in GitHub Desktop.
Save yurydelendik/0c9898b3b9063dbd29f8 to your computer and use it in GitHub Desktop.
ELF format parser
// ELF binary format parser
// See http://refspecs.linuxbase.org/elf/elf.pdf
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['exports'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports);
} else {
factory((root.elf = {}));
}
}(this, function (exports) {
var EI_NIDENT = 16;
var EI_MAG = 0x7F454C46;
var ELFDATA2LSB = 1;
var ELFDATA2MSB = 2;
var ELFCLASS32 = 1;
var ELFCLASS64 = 2;
var EV_CURRENT = 1;
function readProgramHeader(data, le, offset, count, entrySize) {
var result = [];
for (var i = 0; i < count; i++) {
var header = {
type: data.getUint32(offset, le),
offset: data.getUint32(offset + 4, le),
vaddr: data.getUint32(offset + 8, le),
paddr: data.getUint32(offset + 12, le),
filesz: data.getUint32(offset + 16, le),
memsz: data.getUint32(offset + 20, le),
flags: data.getUint32(offset + 24, le),
align: data.getUint32(offset + 28, le),
};
result.push(header);
offset += entrySize;
}
return result;
}
function readSectionHeader(data, le, offset, count, entrySize) {
var result = [];
for (var i = 0; i < count; i++) {
var header = {
nameIdx: data.getUint32(offset, le),
type: data.getUint32(offset + 4, le),
flags: data.getUint32(offset + 8, le),
addr: data.getUint32(offset + 12, le),
offset: data.getUint32(offset + 16, le),
size: data.getUint32(offset + 20, le),
link: data.getUint32(offset + 24, le),
info: data.getUint32(offset + 28, le),
addalign: data.getUint32(offset + 32, le),
entsize: data.getUint32(offset + 36, le),
};
result.push(header);
offset += entrySize;
}
return result;
}
function getName(stringTable, nameIdx) {
if (!stringTable) {
return null;
}
var offset = nameIdx;
var i = offset;
while (i < stringTable.length && stringTable[i]) {
i++;
}
return String.fromCharCode.apply(null, stringTable.subarray(offset, i));
}
function parseElf(buffer) {
var data = new DataView(buffer);
var mag = data.getUint32(0, false);
if (mag !== EI_MAG) {
throw new Error('Invalid magic number');
}
var ident = {
fileClass: data.getUint8(4),
dataEncoging: data.getUint8(5),
version: data.getUint8(6)
};
if (ident.fileClass !== ELFCLASS32 && ident.fileClass !== ELFCLASS64) {
throw new Error('Invalid file class value');
}
if (ident.dataEncoging !== ELFDATA2LSB && ident.dataEncoging !== ELFDATA2LMSB) {
throw new Error('Invalid data encoding value');
}
if (ident.version !== EV_CURRENT) {
throw new Error('Invalid version value');
}
var le = ident.dataEncoging === ELFDATA2LSB;
var header = {
ident: ident,
type: data.getUint16(EI_NIDENT, le),
machine: data.getUint16(EI_NIDENT + 2, le),
version: data.getUint32(EI_NIDENT + 4, le),
entry: data.getUint32(EI_NIDENT + 8, le),
phoff: data.getUint32(EI_NIDENT + 12, le),
shoff: data.getUint32(EI_NIDENT + 16, le),
flags: data.getUint32(EI_NIDENT + 20, le),
ehsize: data.getUint16(EI_NIDENT + 24, le),
phentsize: data.getUint16(EI_NIDENT + 26, le),
phnum: data.getUint16(EI_NIDENT + 28, le),
shentsize: data.getUint16(EI_NIDENT + 30, le),
shnum: data.getUint16(EI_NIDENT + 32, le),
shstrndx: data.getUint16(EI_NIDENT + 34, le)
};
var programHeader = null;
if (header.phoff) {
programHeader = readProgramHeader(data, le, header.phoff, header.phnum, header.phentsize);
}
var sectionHeader = null;
if (header.shoff) {
sectionHeader = readSectionHeader(data, le, header.shoff, header.shnum, header.shentsize);
}
var stringTable = null;
if (header.shstrndx) {
var stringTableSection = sectionHeader[header.shstrndx];
stringTable = new Uint8Array(buffer, stringTableSection.offset, stringTableSection.size);
}
if (sectionHeader && stringTable) {
sectionHeader.forEach(function (sectionHeader) {
});
}
return {
header: header,
program: programHeader && programHeader.map(function (p) {
return {
header: p,
data: new Uint8Array(buffer, p.offset, p.filesz)
};
}),
section: sectionHeader && sectionHeader.map(function (s) {
return {
header: s,
name: getName(stringTable, s.nameIdx),
data: new Uint8Array(buffer, s.offset, s.size)
};
})
};
}
exports.parseElf = parseElf;
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment