mirror of
https://github.com/rizinorg/jsdec.git
synced 2026-11-11 04:21:27 -10:00
130 lines
3.4 KiB
JavaScript
130 lines
3.4 KiB
JavaScript
// SPDX-FileCopyrightText: 2018-2023 Giovanni Dante Grazioli <[email protected]>
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
import Long from '../long.js';
|
|
|
|
var Bounds = function(low, hi) {
|
|
this.low = low;
|
|
this.hi = hi;
|
|
this.gt = function(bound) {
|
|
return this.low.gt(bound.low);
|
|
};
|
|
this.isInside = function(addr) {
|
|
return addr ? (addr.gte(this.low) && addr.lte(this.hi)) : false;
|
|
};
|
|
this.isOutside = function(addr) {
|
|
return !this.isInside(addr);
|
|
};
|
|
};
|
|
|
|
Bounds.invalid = function() {
|
|
return new Bounds(Long.MAX_U64_VALUE, Long.MAX_U64_VALUE);
|
|
};
|
|
|
|
var _sort_extra = function(a, b) {
|
|
if (a.address.eq(b.address)) {
|
|
return 0;
|
|
}
|
|
return a.address.gt(b.address) ? 1 : -1;
|
|
};
|
|
|
|
var _fill_splitted_extra = function(oldblock, newblock, name) {
|
|
var e = oldblock[name][oldblock[name].length - 1];
|
|
while (e && e.address.gte(newblock.bounds.low)) {
|
|
newblock[name].push(oldblock[name].pop());
|
|
e = oldblock[name][oldblock[name].length - 1];
|
|
}
|
|
};
|
|
|
|
export default function _block(bounds) {
|
|
this.bounds = bounds || Bounds.invalid();
|
|
this.extraHead = [];
|
|
this.extraTail = [];
|
|
this.instructions = [];
|
|
this.addInstruction = function(instruction) {
|
|
this.instructions.push(instruction);
|
|
this.update();
|
|
};
|
|
this.addExtraHead = function(extra) {
|
|
this.extraHead.push(extra);
|
|
this.extraHead.sort(_sort_extra);
|
|
};
|
|
this.lastHead = function(extra) {
|
|
return this.extraHead.length > 0 ? this.extraHead[this.extraHead.length - 1] : null;
|
|
};
|
|
this.firstTail = function(extra) {
|
|
return this.extraTail.length > 0 ? this.extraTail[0] : null;
|
|
};
|
|
this.addExtraTail = function(extra) {
|
|
this.extraTail.unshift(extra);
|
|
this.extraTail.sort(_sort_extra);
|
|
};
|
|
this.update = function() {
|
|
var l = this.instructions.length;
|
|
if (l > 0) {
|
|
var first = this.instructions[0];
|
|
var last = this.instructions[l - 1];
|
|
this.bounds = new Bounds(first.location, last.location);
|
|
} else {
|
|
// invalidate this block if is empty..
|
|
this.bounds = Bounds.invalid();
|
|
}
|
|
};
|
|
this.split = function(from) {
|
|
if (from < 0 || from >= this.instructions.length) {
|
|
return null;
|
|
}
|
|
var i = this.instructions.splice(from, this.instructions.length);
|
|
var b = new _block(new Bounds(i[0].location, i[i.length - 1].location));
|
|
b.instructions = i;
|
|
|
|
_fill_splitted_extra(this, b, 'extraHead');
|
|
_fill_splitted_extra(this, b, 'extraTail');
|
|
|
|
this.update();
|
|
b.update();
|
|
return b;
|
|
};
|
|
this.ascomment = function() {
|
|
for (var i = 0; i < this.instructions.length; i++) {
|
|
this.instructions[i].ascomment();
|
|
}
|
|
};
|
|
this.ascodeline = function() {
|
|
for (var i = 0; i < this.instructions.length; i++) {
|
|
this.instructions[i].ascodeline();
|
|
}
|
|
};
|
|
this.hasPrintables = function() {
|
|
for (var i = 0; i < this.instructions.length; i++) {
|
|
if (this.instructions[i].valid && this.instructions[i].code) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
this.print = function() {
|
|
var h = 0;
|
|
var t = 0;
|
|
var i;
|
|
for (i = 0; i < this.instructions.length; i++) {
|
|
while (this.extraHead[h] && this.extraHead[h].address.lte(this.instructions[i].location)) {
|
|
this.extraHead[h].print();
|
|
h++;
|
|
}
|
|
this.instructions[i].print();
|
|
while (this.extraTail[t] && this.extraTail[t].address.eq(this.instructions[i].location)) {
|
|
this.extraTail[t].print();
|
|
t++;
|
|
}
|
|
}
|
|
//this one is bad, but it still require to be executed.
|
|
for (i = h; i < this.extraHead.length; i++) {
|
|
this.extraHead[i].print();
|
|
}
|
|
//this one is ok.
|
|
for (i = t; i < this.extraTail.length; i++) {
|
|
this.extraTail[i].print();
|
|
}
|
|
};
|
|
} |