mirror of
https://github.com/rizinorg/jsdec.git
synced 2026-11-12 19:03:54 -10:00
227 lines
6.2 KiB
JavaScript
227 lines
6.2 KiB
JavaScript
// SPDX-FileCopyrightText: 2018-2023 Giovanni Dante Grazioli <[email protected]>
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
import _call_common from '../db/macros.js';
|
|
import Long from '../long.js';
|
|
|
|
/**
|
|
* Types size
|
|
* @type {Object}
|
|
*/
|
|
const _standard_types = {
|
|
'void': 0,
|
|
'char': 8,
|
|
'short': 16,
|
|
'long': 32,
|
|
'float': 32,
|
|
'long long': 64,
|
|
'double': 64,
|
|
};
|
|
|
|
const _magic_math_values = {
|
|
"0x069c16bd": 'if there is a right shift of 0, then it\'s a division by 665/25756',
|
|
"0x10624dd3": 'if there is a right shift of 4, then it\'s a division by 1/250',
|
|
"0x2aaaaaab": 'if there is a right shift of 0, then it\'s a division by 1/6',
|
|
"0x30c30c31": 'if there is a right shift of 3, then it\'s a division by 1/42',
|
|
"0x38e38e39": 'if there is a right shift of 1, then it\'s a division by 1/9',
|
|
"0x4ec4ec4f": 'if there is a right shift of 3, then it\'s a division by 1/26',
|
|
"0x51eb851f": 'if there is a right shift of 5, then it\'s a division by 1/100',
|
|
"0x55555556": 'if there is a right shift of 0, then it\'s a division by 1/3',
|
|
"0x66666667": 'if there is a right shift of 1, then it\'s a division by 1/5',
|
|
"0x6bca1af3": 'if there is a right shift of 5, then it\'s a division by 1/76',
|
|
"0x88888889": 'if there is a right shift of 8, then it\'s a division by 1/480',
|
|
"0x92492493": 'if there is a right shift of 3, then it\'s a division by 1/14',
|
|
"0xa0a0a0a1": 'if there is a right shift of 7, then it\'s a division by 1/204',
|
|
"0xaaaaaaab": 'if there is a right shift of 1, then it\'s a division by 1/3',
|
|
"0xae147ae1": 'if there is a right shift of 5, then it\'s a division by 17/800',
|
|
"0xb21642c9": 'if there is a right shift of 5, then it\'s a division by 1/46',
|
|
"0xb60b60b7": 'if there is a right shift of 5, then it\'s a division by 1/45',
|
|
"0xba2e8ba3": 'if there is a right shift of 3, then it\'s a division by 1/11',
|
|
"0xea0ea0eb": 'if there is a right shift of 0, then it\'s a division by 32/35',
|
|
};
|
|
|
|
var _align_address = function(x) {
|
|
var zeros32 = '00000000';
|
|
var c = x.toString(16);
|
|
if (c.length > zeros32.length) {
|
|
return '0x' + c;
|
|
}
|
|
return '0x' + zeros32.substr(c.length, zeros32.length) + c;
|
|
};
|
|
|
|
/**
|
|
* Is helpers
|
|
* @type {Object}
|
|
*/
|
|
const _is = {
|
|
string: function(s) {
|
|
return typeof s == 'string';
|
|
},
|
|
number: function(s) {
|
|
return typeof s == 'number';
|
|
},
|
|
array: function(s) {
|
|
return Array.isArray(s);
|
|
},
|
|
inObject: function(object, value) {
|
|
for (var k in object) {
|
|
if (object[k] == value) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* To helpers
|
|
* @type {Object}
|
|
*/
|
|
const _to = {
|
|
type: function(bits, signed) {
|
|
if (bits == 0 || !bits) {
|
|
return 'void';
|
|
}
|
|
return (signed ? 'int' : 'uint') + bits + '_t';
|
|
},
|
|
bits: function(type) {
|
|
var bits = Global().evars.archbits;
|
|
type = type.replace(/[un]?signed\s?/, '');
|
|
if (type.length == 0) {
|
|
type = bits < 32 ? 'int16_t' : 'int32_t';
|
|
}
|
|
if (_standard_types[type]) {
|
|
return _standard_types[type];
|
|
}
|
|
if (type == 'int') {
|
|
return bits < 32 ? 16 : 32;
|
|
}
|
|
return parseInt(type.replace(/[intu_]/g, ''));
|
|
},
|
|
array: function(object) {
|
|
var a = [];
|
|
for (var key in object) {
|
|
a.push(object[key]);
|
|
}
|
|
return a;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Find helpers
|
|
* @type {Object}
|
|
*/
|
|
const _find = {
|
|
arguments_number: function(name) {
|
|
name = _replace.call(name);
|
|
if (_call_common[name]) {
|
|
return _call_common[name].required;
|
|
} else if (Global().argdb) {
|
|
var db = Global().argdb;
|
|
for (var k in db) {
|
|
if (_replace.call(db[k].name.replace(/^_+/, '')) == name) {
|
|
if (db[k].count) {
|
|
return parseInt(db[k].count.toString());
|
|
}
|
|
return db[k].args.length;
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
},
|
|
call_additional: function(name) {
|
|
name = _replace.call(name);
|
|
if (_call_common[name]) {
|
|
return !!_call_common[name].varargs;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Replace helpers
|
|
* @type {Object}
|
|
*/
|
|
const _replace = {
|
|
call: function(name) {
|
|
if (typeof name != 'string' || name.startsWith('0x')) {
|
|
return name;
|
|
}
|
|
if (name.startsWith('sym.imp.')) {
|
|
name = name.substring('sym.imp.'.length).replace(/^_+/, '');
|
|
} else if (name.startsWith('sym.')) {
|
|
name = name.substring('sym.'.length).replace(/^_+/, '');
|
|
} else if (name.startsWith('imp.')) {
|
|
name = name.substring('imp.'.length).replace(/^_+/, '');
|
|
//} else if (name.startsWith('fcn.')) {
|
|
// name = name.substring('fcn.'.length);
|
|
//} else if (name.startsWith('func.')) {
|
|
// name = name.substring('func.'.length);
|
|
}
|
|
if (name.startsWith('reloc.')) {
|
|
name = name.substring('reloc.'.length).replace(/^_+/, '');
|
|
}
|
|
name = name.replace(/^sub\./, '');
|
|
if (name.match(/^[\w]+\.dll_/)) {
|
|
name = name.replace(/[\w]+\.dll_/, '');
|
|
}
|
|
name = name.replace(/[Mm][Ss][Vv][Cc][Rr][Tt]\.[Dd][Ll][Ll]_/, '');
|
|
name = name.replace(/\./g, '_');
|
|
return name.replace(/(\w|^):(\w|$)/g, '$1_$2').replace(/_+/g, '_');
|
|
},
|
|
object: function(name) {
|
|
if (typeof name != 'string' || name.startsWith('0x')) {
|
|
return name;
|
|
}
|
|
if (name.startsWith('sym.imp.')) {
|
|
name = name.substring('sym.imp.'.length);
|
|
} else if (name.startsWith('sym.')) {
|
|
name = name.substring('sym.'.length);
|
|
} else if (name.startsWith('imp.')) {
|
|
name = name.substring('imp.'.length);
|
|
//} else if (name.startsWith('fcn.')) {
|
|
// name = name.substring('fcn.'.length);
|
|
//} else if (name.startsWith('func.')) {
|
|
// name = name.substring('func.'.length);
|
|
} else if (name.startsWith('reloc.')) {
|
|
name = name.substring('reloc.'.length);
|
|
}
|
|
if (name.startsWith('L') || name.startsWith('[L')) {
|
|
// java object
|
|
name = name.replace(/\.<init>\(.+$|\(.+$|\._init_.+V$|_L.+$/, '');
|
|
name = name.substr(name.startsWith('L') ? 1 : 2).replace(/\/|;->/g, '.').replace(/\s.+$|;$/, '');
|
|
if (name.indexOf('_L') > 0) {
|
|
name = name.substring(0, name.indexOf('_L'));
|
|
}
|
|
}
|
|
return name;
|
|
}
|
|
};
|
|
|
|
const _tryas = {
|
|
int: function(x) {
|
|
try {
|
|
return Long.from(x.trim(), false, (x.trim().indexOf('0x') == 0 ? 16 : 10));
|
|
} catch (e) {}
|
|
return x;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Extra object
|
|
* @return {Function} - Extra object
|
|
*/
|
|
export default {
|
|
tryas: _tryas,
|
|
is: _is,
|
|
to: _to,
|
|
find: _find,
|
|
replace: _replace,
|
|
align_address: _align_address,
|
|
magic_math: function(address) {
|
|
if (typeof address != 'string') {
|
|
address = '0x' + address.toString(16);
|
|
}
|
|
return _magic_math_values[address];
|
|
}
|
|
}; |