Created
October 7, 2015 01:25
-
-
Save yurydelendik/0c9898b3b9063dbd29f8 to your computer and use it in GitHub Desktop.
ELF format parser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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