overhaul codebase

This commit is contained in:
Reece Wilson 2019-11-01 07:49:22 +00:00
parent 5d1e8ba4b3
commit fd99d06b3d
13 changed files with 445 additions and 390 deletions

37
T6Constants.js Normal file
View File

@ -0,0 +1,37 @@
function Constants(ctx, method) {
this.ctx = ctx;
this.method = method;
this.objs = [];
}
Constants.prototype.read = function() {
var size = this.ctx.reader.readMachine();
for (var i = 0; i < size; i++) {
//console.log("reading constant at " + this.ctx.reader.index);
var id = this.ctx.reader.readUByte();
var type = consts.byId[id];
if (!type) {
console.log("illegal constant type " + id);
return false;
}
var inst = new type();
inst.undump(this.ctx.reader, this.ctx);
this.objs.push(inst);
}
return true;
}
Constants.prototype.write = function() {
this.ctx.writer.writeMachine(this.objs.length);
this.objs.forEach((obj) => {
this.ctx.writer.writeUByte(obj.id);
obj.dump(this.ctx.writer, this.ctx);
});
}
module.exports = Constants;

50
T6Debug.js Normal file
View File

@ -0,0 +1,50 @@
function Debug(ctx, method) {
this.ctx = ctx;
this.method = method;
this.type = 0;
this.data = {};
}
Debug.prototype.read = function() {
this.type = this.ctx.reader.readInteger();
if (this.type == 1) {
this.data["unknown"] = this.ctx.reader.readInteger();
} else if (this.type == 0) {
} else if (this.type == 40) { //implemented in t6
//TODO:
} else if (this.type == 0x48) {
/*
hks::BytecodeWriter::dumpInt(this, 0x48);
hks::BytecodeWriter::dumpInt(v6, v5->m_debug->line_defined);
hks::BytecodeWriter::dumpInt(v6, v5->m_debug->last_line_defined);
if ( v4 )
v8 = 0i64;
else
v8 = v5->m_debug->source;
hks::BytecodeWriter::dumpString(v6, v8);
hks::BytecodeWriter::dumpString(v6, v5->m_debug->name);
hks::BytecodeWriter::dumpVector<hksInstruction>(v6, 0i64, 0i64, 0);
hks::BytecodeWriter::dumpInt(v6, 0);
hks::BytecodeWriter::dumpInt(v6, 0);
*/
}
}
Debug.prototype.write = function() {
this.ctx.writer.writeInteger(this.type);
if (this.type == 1) {
this.ctx.writer.writeInteger(this.data["unknown"]);
} else if (this.type == 0) {
return;
} else if (this.type == 40) { //implemented in t6 - but seemingly unused
//TODO:
} else if (this.type == 0x48) {
//TODO:
}
}
module.exports = Debug;

83
T6Header.js Normal file
View File

@ -0,0 +1,83 @@
function Header(ctx) {
this.magic = undefined;
this.version = 0;
//this.nonCompliant = true;
this.isLE = true;
this.intSize = 4;
this.instructionSize = 4;
this.machineSize = 4;
this.numberSize = 4;
this.platformFlags = 0;
this.numOfTypes = 13;
this.sharingMode = 0; // sharing mode (0 - none, 1 - shared, 2 - secure) ? 1 : 0
this.ctx = ctx;
}
Header.prototype.read = function() {
var buffer = this.ctx.reader.readBytes(false, 14);
this.magic = buffer.readUInt32LE();
this.version = buffer.readUInt8(4);
this.platformFlags = buffer.readUInt8(12); // extensions etc
this.intSize = buffer.readUInt8(7); // sizeOfInt
this.machineSize = buffer.readUInt8(8); // sizeOfSize
this.instructionSize = buffer.readUInt8(9); // sizeOfLuaN
this.numberSize = buffer.readUInt8(10); // sizeOfNumber
var idk = buffer.readUInt8(5); //??
this.isLE = buffer.readUInt8(6) ? true : false;
this.sharingMode = buffer.readUInt8(13) ? true : false;
this.numOfTypes = this.ctx.reader.readInteger();
if (this.numOfTypes != 13) {
console.log("There should only be 13 types");
return false;
}
for (var i in this.ctx.types.list) {
var type = this.ctx.types.list[i];
var id = this.ctx.reader.readInteger();
if (id != type.id)
{
console.log(fmt("illegal type index %i expected: %s (%i)", id, type.id, type.name));
return false;
}
var str = this.ctx.reader.readCString();
if (str != type.tname)
{
console.log(fmt("illegal type name %s expected: %s", str, type.tname));
return false;
}
}
return true;
}
Header.prototype.write = function(ctx) {
this.ctx.writer.writeUByte(0x1B);
this.ctx.writer.writeUByte(0x4C); //L
this.ctx.writer.writeUByte(0x75); //U
this.ctx.writer.writeUByte(0x61); //A
this.ctx.writer.writeUByte(this.version);
this.ctx.writer.writeUByte(13); // ???
this.ctx.writer.writeUByte(this.isLE ? 1 : 0);
this.ctx.writer.writeUByte(this.intSize);
this.ctx.writer.writeUByte(this.machineSize);
this.ctx.writer.writeUByte(this.instructionSize);
this.ctx.writer.writeUByte(this.numberSize);
this.ctx.writer.writeUByte(0); //TODO
this.ctx.writer.writeUByte(this.platformFlags);
this.ctx.writer.writeUByte(this.sharingMode ? 1 : 0);
this.ctx.writer.writeInteger(this.numOfTypes);
this.ctx.types.list.forEach((type) => {
this.ctx.writer.writeInteger(type.id);
this.ctx.writer.writeCString(type.tname);
});
}
module.exports = Header;

105
T6Method.js Normal file
View File

@ -0,0 +1,105 @@
const decoder = require("./instructions/instructionDecoder.js");
const ops = require("./instructions/instructions.js");
const fmt = require("util").format;
const Constants = require("./T6Constants.js");
const Debug = require("./T6Debug.js");
function Method(ctx) {
this.ctx = ctx;
this.debug = new Debug(ctx, this);
this.constants = new Constants(ctx, this);
this.upvals = 0;
this.params = 0;
this.flags = 0;
this.registers = 0;
this.code = [];
this.decoded = [];
this.closures = [];
}
Method.prototype.read = function() {
this.upvals = this.ctx.reader.readInteger();
this.params = this.ctx.reader.readInteger();
this.flags = this.ctx.reader.readUByte();
this.registers = this.ctx.reader.readInteger();
if (this.ctx.header.sharingMode) {
console.log("illegal sharing mode");
return;
}
this.code = this.ctx.reader.readVectorDWORD();
this.parseInstructions();
this.constants.read();
this.debug.read();
var items = this.ctx.reader.readInteger();
for (var i = 0; i < items; i++){
var methods = new Method(this.ctx);
this.closures.push(methods);
methods.read();
}
}
Method.prototype.write = function() {
this.ctx.writer.writeInteger(this.upvals);
this.ctx.writer.writeInteger(this.params);
this.ctx.writer.writeUByte(this.flags);
this.ctx.writer.writeInteger(this.registers);
if (this.ctx.header.sharingMode) {
console.log("illegal sharing mode");
return;
}
this.ctx.writer.writeVectorDWORD(this.code);
this.constants.write();
this.debug.write();
this.ctx.writer.writeInteger(this.closures.length);
this.closures.forEach((closure) => {
closure.write();
});
}
Method.prototype.parseInstructions = function() {
this.code.forEach((code) => {
var data = {};
var instruction;
var I = decoder.getOp(code);
if (!(instruction = ops.instructionById[I])) {
console.log(fmt("WTF... ILLEGAL INSTRUCTION [index: %i]", I));
return;
}
data.I = I;
data.instruction = instruction;
if (instruction.type == decoder.instructionTypes.iABC) {
var temp = decoder.decodeABC(code);
data.a = temp.a;
data.b = temp.b;
data.c = temp.c;
} else if (instruction.type == decoder.instructionTypes.iABx) {
var temp = decoder.decodeABx(code);
data.a = temp.a;
data.b = temp.b;
} else if (instruction.type == decoder.instructionTypes.iAsBx) {
var temp = decoder.decodeAsBx(code);
data.a = temp.a;
data.b = temp.b;
} else {
console.log("WTF... ILLEGAL INSTRUCTION");
}
this.decoded.push(data);
});
}
module.exports = Method;

View File

@ -1,19 +1,20 @@
const consts = require("./../constants.js");
const insts = require("./../instructions.js");
const fmt = require("util").format;
const consts = require("./../constants.js");
const insts = require("./../instructions/instructions.js");
const decoder = require("./../instructions/instructionDecoder.js");
const fmt = require("util").format;
function parseLine(line) {
var ret = [];
if (line.indexOf(';') != -1)
line = line.substring(0, line.indexOf(';'));
//if (line.indexOf(';') != -1)
// line = line.substring(0, line.indexOf(';'));
var objs = line.split("\t").join(" ") // convert tabs into spaces
.split(",").join(" ") // convert ,'s into spaces
.split(",").join(" ") // convert ,'s into spaces
.split(":").join("") // get rid of optional :'s
.split("(").join("") // get rid of optional brackets
.split(")").join("") // get rid of optional brackets
.split(" "); // split
.split(" "); // split
var hack = false;
@ -38,7 +39,6 @@ function parseLine(line) {
if (obj.length == 0) return;
if (parseFloat(obj)) {
parsed.number.present = true;
parsed.number.value = parseFloat(obj);
@ -49,7 +49,8 @@ function parseLine(line) {
parsed.bool.value = obj == "true";
}
if (obj.charAt(0) == '{' && line.charAt(line.length - 1)) {
if (obj.charAt(0) == '{' && line.charAt(line.length - 1) == '}') {
var json = line.substring(line.indexOf("{"));
parsed.raw = json;
parsed.JSON.present = true;
@ -58,6 +59,12 @@ function parseLine(line) {
hack = true;
}
if (obj.charAt(0) == '"' && line.charAt(line.length - 1) == '"') {
parsed.raw = line.substring(line.indexOf('"') + 1, line.length - 1).replace('""', "");
ret.push(parsed);
hack = true;
}
if (!hack)
ret.push(parsed);
});
@ -97,6 +104,7 @@ function readBlock(buffer, context, title, callback, data) {
var start = "START_" + title;
var end = "END_" + title;
var temp;
var shouldLoop;
temp = buffer.nextKey();
if (temp != start) {
@ -104,7 +112,10 @@ function readBlock(buffer, context, title, callback, data) {
return false;
}
callback(buffer, context, data);
do
{
shouldLoop = callback(buffer, context, data);
} while (shouldLoop);
temp = buffer.nextKey();
if (temp != end) {
@ -116,100 +127,120 @@ function readBlock(buffer, context, title, callback, data) {
}
function handleHeader(buffer, context) {
if (buffer.peakKey() == "START_NUMBER_SIZES") {
readBlock(buffer, context, "NUMBER_SIZES", handleHeaderNumberics);
return handleHeader(buffer, context);
return true;
}
if (buffer.peakKey() == "VERSION") {
//TODO assert
context.header.version = buffer.next()[1].number.value;
return handleHeader(buffer, context);
return true;
}
if (buffer.peakKey() == "LENDIAN") {
//TODO assert
context.header.isLE = buffer.next()[1].bool.value;
return handleHeader(buffer, context);
return true;
}
if (buffer.peakKey() == "UNK") {
//TODO assert
// DEPRECATED
//context.header.unkByte = buffer.next()[1].number.value;
return handleHeader(buffer, context);
return true;
}
if (buffer.peakKey() == "FLAGS") {
//TODO assert
context.header.platformFlags = buffer.next()[1].number.value;
return handleHeader(buffer, context);
return true;
}
if (buffer.peakKey() == "TYPES") {
//TODO assert
context.header.numOfTypes = buffer.next()[1].number.value;
return handleHeader(buffer, context);
return true;
}
if (buffer.peakKey() == "SHARE") {
//TODO assert
context.header.share = buffer.next()[1].bool.value;
return handleHeader(buffer, context);
return true;
}
return undefined;
}
function handleHeaderNumberics(buffer, context) {
if (buffer.peakKey() == "NUMBER") {
//TODO assert
context.header.numberSize = buffer.next()[1].number.value;
return handleHeaderNumberics(buffer, context);
return true;
}
if (buffer.peakKey() == "INTEGER") {
//TODO assert
context.header.intSize = buffer.next()[1].number.value;
return handleHeaderNumberics(buffer, context);
return true;
}
if (buffer.peakKey() == "INSTRUCTION") {
//TODO assert
context.header.instructionSize = buffer.next()[1].number.value;
return handleHeaderNumberics(buffer, context);
return true;
}
if (buffer.peakKey() == "SIZE_T") {
//TODO assert
context.header.machineSize = buffer.next()[1].number.value;
return handleHeaderNumberics(buffer, context);
return true;
}
return false;
}
function handleMethodDebug(buffer, context, dbg ) {
if (buffer.peakKey() == "TYPE") {
//TODO assert
dbg.type = buffer.next()[1].number.value;
return handleMethodDebug(buffer, context, dbg);
return true;
}
if (buffer.peakKey() == "DATA") {
//TODO assert
dbg.data = buffer.next()[1].JSON.value;
return handleMethodDebug(buffer, context, dbg);
return true;
}
return true;
return false;
}
function handleMethodConstants(buffer, context, constants) {
if (buffer.peakKey() == "END_CONSTANTS") return true;
if (buffer.peakKey() == "END_CONSTANTS")
return false;
for (let Type of consts.list) {
if (Type.tname == buffer.peakKey()) {
var type = new Type();
var ahh = buffer.next();
if (ahh[1])
type.fromString(ahh[1].raw);
else if (Type.tname == "TSTRING")
type.value = "";
constants.objs.push(type);
return handleMethodConstants(buffer, context, constants);
}
if (Type.tname != buffer.peakKey())
continue;
var type = new Type();
var readValue = buffer.next();
if (readValue[1])
type.fromString(readValue[1].raw);
else if (Type.tname == "TSTRING")
type.value = "";
constants.objs.push(type);
return true;
}
return false;
}
@ -217,91 +248,93 @@ function handleMethodCode(buffer, context, opcodes) {
while (buffer.peakKey() != "END_CODE") {
var nxt = buffer.next();
if (Object.keys(insts.instructionTypes).indexOf(nxt[0].raw) != -1)
if (Object.keys(decoder.instructionTypes).indexOf(nxt[0].raw) != -1)
nxt.shift();
var instruction = insts.instructionByName[nxt[0].raw];
nxt.shift();
if (instruction.type == insts.instructionTypes.iABC) {
opcodes.push(insts.encodeABC(instruction.opcode, nxt[0].number.value, nxt[1].number.value, nxt[2].number.value));
} else if (instruction.type == insts.instructionTypes.iABx) {
opcodes.push(insts.encodeABx(instruction.opcode, nxt[0].number.value, nxt[1].number.value));
} else if (instruction.type == insts.instructionTypes.iAsBx) {
opcodes.push(insts.encodeAsBx(instruction.opcode, nxt[0].number.value, nxt[1].number.value));
if (instruction.type == decoder.instructionTypes.iABC) {
opcodes.push(decoder.encodeABC(instruction.opcode, nxt[0].number.value, nxt[1].number.value, nxt[2].number.value));
} else if (instruction.type == decoder.instructionTypes.iABx) {
opcodes.push(decoder.encodeABx(instruction.opcode, nxt[0].number.value, nxt[1].number.value));
} else if (instruction.type == decoder.instructionTypes.iAsBx) {
opcodes.push(decoder.encodeAsBx(instruction.opcode, nxt[0].number.value, nxt[1].number.value));
}
}
return false;
}
function handleClosure(buffer, context, data) {
var id = data.id;
var newMethod = new (require("./../index.js").Method)(context);
var newMethod = new context.MethodType(context);
readBlock(buffer, context, "METHOD", handleMethod, newMethod);
data.parent.closures.push(newMethod);
return false;
}
function handleMethod(buffer, context, method) {
if (buffer.peakKey() == "START_DBG") {
if (!readBlock(buffer, context, "DBG", handleMethodDebug, method.debug))
return false;
return handleMethod(buffer, context, method);
return readBlock(buffer, context, "DBG", handleMethodDebug, method.debug);
}
if (buffer.peakKey() == "START_CONSTANTS") {
if (!readBlock(buffer, context, "CONSTANTS", handleMethodConstants, method.constants))
return false;
return handleMethod(buffer, context, method);
return readBlock(buffer, context, "CONSTANTS", handleMethodConstants, method.constants);
}
if (buffer.peakKey() == "START_CODE") {
if (!readBlock(buffer, context, "CODE", handleMethodCode, method.code))
return false;
method.parseInstructions();
return handleMethod(buffer, context, method);
return true;
}
if (buffer.peakKey() == "START_CLOSURE") {
if (!readBlock(buffer, context, "CLOSURE", handleClosure, {parent: method, id: buffer.peak()[1].number.value}))
return false;
return handleMethod(buffer, context, method);
return readBlock(buffer, context, "CLOSURE", handleClosure, {parent: method, id: buffer.peak()[1].number.value});
}
if (buffer.peakKey() == "FLAGS") {
//TODO assert
method.flags = buffer.next()[1].number.value;
return handleMethod(buffer, context, method);
return true;
}
if (buffer.peakKey() == "PARAMS") {
//TODO assert
method.params = buffer.next()[1].number.value;
return handleMethod(buffer, context, method);
return true;
}
if (buffer.peakKey() == "UPVALS") {
//TODO assert
method.upvals = buffer.next()[1].number.value;
return handleMethod(buffer, context, method);
return true;
}
if (buffer.peakKey() == "REGCNT") {
//TODO assert
method.registers = buffer.next()[1].number.value;
return handleMethod(buffer, context, method);
return true;
}
return true;
return false;
}
function handleScript(buffer, context) {
if (buffer.peakKey() == "START_HEADER") {
readBlock(buffer, context, "HEADER", handleHeader);
return handleScript(buffer, context);
return true;
}
if (buffer.peakKey() == "START_METHOD") {
readBlock(buffer, context, "METHOD", handleMethod, context.mainMethod);
return handleScript(buffer, context);
return true;
}
return false;
}
function asmContext(string, context) {

View File

@ -1,5 +1,5 @@
const consts = require("./../constants.js");
const insts = require("./../instructions.js");
const insts = require("./../instructions/instructions.js");
const fmt = require("util").format;
function append(_, level, str) {

View File

@ -1,5 +1,3 @@
const iset = require("./instructions.js");
function Reader(buffer, ctx) {
this.buffer = buffer;
this.index = 0;
@ -64,45 +62,50 @@ Reader.prototype.readNumber = function(peak) {
}
Reader.prototype.readMachine = function(peak) {
if (this.ctx.header.machineSize == 4) {
var i = this.ctx.header.isLE ? this.buffer.readUInt32LE(this.index) : this.buffer.readUInt32BE(this.index);
if (peak)
return i;
this.index += 4;
return i;
}
//TODO:
console.log("int64 not supported");
return -203;
if (this.ctx.header.machineSize == 4) {
return this.consumeInt32(peak);
} else if (this.ctx.header.machineSize == 8) {
return this.consumeInt64(peak);
} else {
return -420;
}
}
Reader.prototype.readInstruction = function(peak) {
if (this.ctx.header.instructionSize == 4) {
var i = this.ctx.header.isLE ? this.buffer.readUInt32LE(this.index) : this.buffer.readUInt32BE(this.index);
if (peak)
return i;
this.index += 4;
return i;
}
//TODO:
console.log("int64 not supported");
return -203;
if (this.ctx.header.instructionSize == 4) {
return this.consumeInt32(peak);
} else if (this.ctx.header.instructionSize == 8) {
return this.consumeInt64(peak);
} else {
return -420;
}
}
Reader.prototype.readInteger = function(peak) {
if (this.ctx.header.intSize == 4) {
var i = this.ctx.header.isLE ? this.buffer.readInt32LE(this.index) : this.buffer.readInt32BE(this.index);
if (peak)
return i;
this.index += 4;
return i;
}
return this.consumeInt32(peak);
} else if (this.ctx.header.intSize == 8) {
return this.consumeInt64(peak);
} else {
return -420;
}
}
//TODO:
console.log("int64 not supported");
return -203;
Reader.prototype.consumeInt64 = function(peak) {
var lo = this.buffer.readInt32LE(this.index);
this.index += 4;
var hi = this.buffer.readInt32LE(this.index);
this.index += 4;
if (peak)
this.index -= 8;
return BigInt(hi) << 32n | lo;
}
Reader.prototype.consumeInt32 = function(peak) {
var lo = this.ctx.header.isLE ? this.buffer.readUInt32LE(this.index) : this.buffer.readUInt32BE(this.index);
if (!peak)
this.index += 4;
return lo;
}
Reader.prototype.readVectorDWORD = function(peak) {
@ -114,5 +117,4 @@ Reader.prototype.readVectorDWORD = function(peak) {
return buffer;
}
module.exports = Reader;

281
index.js
View File

@ -1,276 +1,23 @@
const StreamReader = require("./streamReader.js");
const StreamWriter = require("./streamWriter.js");
const StreamReader = require("./bin/streamReader.js");
const StreamWriter = require("./bin/streamWriter.js");
const fio = require("fs");
const consts = require("./constants.js");
const insts = require("./instructions.js");
const fmt = require("util").format;
const process = require("process");
const dasm = require("./asm/disassembler.js");
const asm = require("./asm/assembler.js");
function Header(ctx) {
this.magic = undefined;
this.version = 0;
//this.nonCompliant = true;
this.isLE = true;
this.intSize = 4;
this.instructionSize = 4;
this.machineSize = 4;
this.numberSize = 4;
this.platformFlags = 0;
this.numOfTypes = 13;
this.sharingMode = 0; // sharing mode (0 - none, 1 - shared, 2 - secure) ? 1 : 0
this.ctx = ctx;
}
const instructions = require("./instructions/instructions.js");
Header.prototype.read = function() {
var buffer = this.ctx.reader.readBytes(false, 14);
this.magic = buffer.readUInt32LE();
this.version = buffer.readUInt8(4);
this.platformFlags = buffer.readUInt8(12); // extensions etc
this.intSize = buffer.readUInt8(7); // sizeOfInt
this.machineSize = buffer.readUInt8(8); // sizeOfSize
this.instructionSize = buffer.readUInt8(9); // sizeOfLuaN
this.numberSize = buffer.readUInt8(10); // sizeOfNumber
var idk = buffer.readUInt8(5); //??
this.isLE = buffer.readUInt8(6) ? true : false;
this.sharingMode = buffer.readUInt8(13) ? true : false;
this.numOfTypes = this.ctx.reader.readInteger();
if (this.numOfTypes != 13) {
console.log("There should only be 13 types");
return false;
}
for (var i in consts.list) {
var type = consts.list[i];
var id = this.ctx.reader.readInteger();
if (id != type.id)
{
console.log(fmt("illegal type index %i expected: %s (%i)", id, type.id, type.name));
return false;
}
var str = this.ctx.reader.readCString();
if (str != type.tname)
{
console.log(fmt("illegal type name %s expected: %s", str, type.tname));
return false;
}
}
return true;
}
Header.prototype.write = function(ctx) {
this.ctx.writer.writeUByte(0x1B);
this.ctx.writer.writeUByte(0x4C); //L
this.ctx.writer.writeUByte(0x75); //U
this.ctx.writer.writeUByte(0x61); //A
this.ctx.writer.writeUByte(this.version);
this.ctx.writer.writeUByte(13); // ???
this.ctx.writer.writeUByte(this.isLE ? 1 : 0);
this.ctx.writer.writeUByte(this.intSize);
this.ctx.writer.writeUByte(this.machineSize);
this.ctx.writer.writeUByte(this.instructionSize);
this.ctx.writer.writeUByte(this.numberSize);
this.ctx.writer.writeUByte(0); //TODO
this.ctx.writer.writeUByte(this.platformFlags);
this.ctx.writer.writeUByte(this.sharingMode ? 1 : 0);
this.ctx.writer.writeInteger(this.numOfTypes);
consts.list.forEach((type) => {
this.ctx.writer.writeInteger(type.id);
this.ctx.writer.writeCString(type.tname);
});
}
function Debug(ctx, method) {
this.ctx = ctx;
this.method = method;
this.type = 0;
this.data = {};
}
Debug.prototype.read = function() {
this.type = this.ctx.reader.readInteger();
if (this.type == 1) {
this.data["unknown"] = this.ctx.reader.readInteger();
} else if (this.type == 0) {
} else if (this.type == 40) { //implemented in t6
//TODO:
} else if (this.type == 0x48) {
/*
hks::BytecodeWriter::dumpInt(this, 0x48);
hks::BytecodeWriter::dumpInt(v6, v5->m_debug->line_defined);
hks::BytecodeWriter::dumpInt(v6, v5->m_debug->last_line_defined);
if ( v4 )
v8 = 0i64;
else
v8 = v5->m_debug->source;
hks::BytecodeWriter::dumpString(v6, v8);
hks::BytecodeWriter::dumpString(v6, v5->m_debug->name);
hks::BytecodeWriter::dumpVector<hksInstruction>(v6, 0i64, 0i64, 0);
hks::BytecodeWriter::dumpInt(v6, 0);
hks::BytecodeWriter::dumpInt(v6, 0);
*/
}
}
Debug.prototype.write = function() {
this.ctx.writer.writeInteger(this.type);
if (this.type == 1) {
this.ctx.writer.writeInteger(this.data["unknown"]);
} else if (this.type == 0) {
return;
} else if (this.type == 40) { //implemented in t6 - but seemingly unused
//TODO:
} else if (this.type == 0x48) {
//TODO:
}
}
function Constants(ctx, method) {
this.ctx = ctx;
this.method = method;
this.objs = [];
}
Constants.prototype.read = function() {
var size = this.ctx.reader.readMachine();
for (var i = 0; i < size; i++) {
//console.log("reading constant at " + this.ctx.reader.index);
var id = this.ctx.reader.readUByte();
var type = consts.byId[id];
if (!type) {
console.log("illegal constant type " + id);
return false;
}
var inst = new type();
inst.undump(this.ctx.reader, this.ctx);
this.objs.push(inst);
}
return true;
}
Constants.prototype.write = function() {
this.ctx.writer.writeMachine(this.objs.length);
this.objs.forEach((obj) => {
this.ctx.writer.writeUByte(obj.id);
obj.dump(this.ctx.writer, this.ctx);
});
}
function Method(ctx) {
this.ctx = ctx;
this.debug = new Debug(ctx, this);
this.constants = new Constants(ctx, this);
this.upvals = 0;
this.params = 0;
this.flags = 0;
this.registers = 0;
this.code = [];
this.decoded = [];
this.closures = [];
}
Method.prototype.read = function() {
this.upvals = this.ctx.reader.readInteger();
this.params = this.ctx.reader.readInteger();
this.flags = this.ctx.reader.readUByte();
this.registers = this.ctx.reader.readInteger();
if (this.ctx.header.sharingMode) {
console.log("illegal sharing mode");
return;
}
this.code = this.ctx.reader.readVectorDWORD();
this.parseInstructions();
this.constants.read();
this.debug.read();
var items = this.ctx.reader.readInteger();
for (var i = 0; i < items; i++){
var methods = new Method(this.ctx);
this.closures.push(methods);
methods.read();
}
}
Method.prototype.write = function() {
this.ctx.writer.writeInteger(this.upvals);
this.ctx.writer.writeInteger(this.params);
this.ctx.writer.writeUByte(this.flags);
this.ctx.writer.writeInteger(this.registers);
if (this.ctx.header.sharingMode) {
console.log("illegal sharing mode");
return;
}
this.ctx.writer.writeVectorDWORD(this.code);
this.constants.write();
this.debug.write();
this.ctx.writer.writeInteger(this.closures.length);
this.closures.forEach((closure) => {
closure.write();
});
}
Method.prototype.parseInstructions = function() {
this.code.forEach((code) => {
var data = {};
var I = insts.getOp(code);
var instruction = insts.instructionById[I];
if (!instruction) {
console.log(fmt("WTF... ILLEGAL INSTRUCTION [index: %i]", I));
return;
}
data.I = I;
data.instruction = instruction;
if (instruction.type == insts.instructionTypes.iABC) {
var temp = insts.decodeABC(code);
data.a = temp.a;
data.b = temp.b;
data.c = temp.c;
} else if (instruction.type == insts.instructionTypes.iABx) {
var temp = insts.decodeABx(code);
data.a = temp.a;
data.b = temp.b;
} else if (instruction.type == insts.instructionTypes.iAsBx) {
var temp = insts.decodeAsBx(code);
data.a = temp.a;
data.b = temp.b;
} else {
console.log("WTF... ILLEGAL INSTRUCTION");
}
this.decoded.push(data);
});
}
const T6Header = require("./T6Header.js");
const T6Method = require("./T6Method.js");
function Context() {
this.types = consts;
this.header = new Header(this);
this.mainMethod = new Method(this);
this.header = new T6Header(this);
this.mainMethod = new T6Method(this);
this.HeaderType = T6Header;
this.MethodType = T6Method;
this.reader = undefined;
this.writer = undefined;
}
@ -315,11 +62,7 @@ Context.prototype.assembleFile = function(file) {
}
module.exports = {
Context: Context,
Method: Method,
Constants: Constants,
Debug: Debug,
Header: Header,
constants: consts,
instructions: insts
T6Context: Context,
types: consts,
instructions: instructions
}

View File

@ -1,5 +1,3 @@
const opcodes = require("./instructions_a.js");
const e_iABC = 0;
const e_iABx = 1;
const e_iAsBx = 2;
@ -8,17 +6,6 @@ const itypes = { "iABC": e_iABC,
"iABx": e_iABx,
"iAsBx": e_iAsBx };
var instructionById = {};
var instructionByName = {};
opcodes.forEach((obj) => {
instructionById[obj.opcode] = obj;
});
opcodes.forEach((obj) => {
instructionByName[obj.name] = obj;
});
function getOp(code) {
return (code >>> 25) & 0x7f;
}
@ -66,15 +53,12 @@ function decodeAsBx(code) {
}
module.exports = {
getOp: getOp,
encodeABC: encodeABC,
decodeABC: decodeABC,
encodeABx: encodeABx,
decodeABx: decodeABx,
encodeAsBx: encodeAsBx,
decodeAsBx: decodeAsBx,
instructions: opcodes,
instructionById: instructionById,
instructionByName: instructionByName,
instructionTypes: itypes
getOp: getOp,
encodeABC: encodeABC,
decodeABC: decodeABC,
encodeABx: encodeABx,
decodeABx: decodeABx,
encodeAsBx: encodeAsBx,
decodeAsBx: decodeAsBx,
instructionTypes: itypes
};

View File

@ -0,0 +1,18 @@
const opcodes = require("./instructionsT6.js");
var instructionById = {};
var instructionByName = {};
opcodes.forEach((obj) => {
instructionById[obj.opcode] = obj;
});
opcodes.forEach((obj) => {
instructionByName[obj.name] = obj;
});
module.exports = {
instructions: opcodes,
instructionById: instructionById,
instructionByName: instructionByName
};

View File