ts-capstone
Version:
This module provides bindings for the Capstone disassembly framework.
220 lines (210 loc) • 5.4 kB
text/typescript
import { Wrapper } from './capstone';
type native_t =
| 'i8'
| 'int8_t'
| 'i16'
| 'int16_t'
| 'i32'
| 'int32_t'
| 'i64'
| 'int64_t'
| 'byte'
| 'short'
| 'long'
| 'int'
| 'double'
| 'u8'
| 'uint8_t'
| 'u16'
| 'uint16_t'
| 'u32'
| 'uint32_t'
| 'u64'
| 'uint64_t'
| 'ubyte'
| 'ushort'
| 'ulong'
| 'uint'
| 'float'
| 'f32'
| 'f64'
| '*'
| 'ptr'
| 'void*'
| 'i8*'
| 'bool'
| 'char'
| 'char*'
| 'boolean';
type arr_t<T extends native_t> = `${T}[${number}]`;
type pointer_t<T extends any> = number;
export namespace Memory {
export const allocations: Set<pointer_t<any>> = new Set<pointer_t<any>>();
export const nullptr: pointer_t<0> = 0;
export function malloc(size: number): pointer_t<any> {
const pointer: pointer_t<any> = Wrapper._malloc(size);
allocations.add(pointer);
return pointer;
}
export function free(
mem: pointer_t<any> | Set<pointer_t<any>> | pointer_t<any>[],
): void {
if (mem instanceof Set || Array.isArray(mem)) {
for (const pointer of mem) {
allocations.delete(pointer);
Wrapper._free(pointer);
}
} else {
allocations.delete(mem);
Wrapper._free(mem);
}
}
export function clean(): void {
free(allocations);
}
export function write(
pointer: pointer_t<any>,
value: any,
type: native_t | arr_t<native_t>,
): void {
switch (type) {
case 'char*':
const utf8_bytes = [];
if (!/\0/.test(value)) value += '\0';
for (let i = 0; i < value.length; ++i) {
const charCode = value.charCodeAt(i);
if (charCode < 128) {
utf8_bytes.push(charCode);
} else if (charCode < 2048) {
utf8_bytes.push((charCode >> 6) | 192);
utf8_bytes.push((charCode & 63) | 128);
} else {
utf8_bytes.push((charCode >> 12) | 224);
utf8_bytes.push(((charCode >> 6) & 63) | 128);
utf8_bytes.push((charCode & 63) | 128);
}
}
for (let i = 0; i < utf8_bytes.length; ++i) {
Wrapper.setValue(pointer + i, utf8_bytes[i], 'i8');
}
break;
case 'bool':
case 'boolean':
Wrapper.setValue(pointer, +value, 'i8');
break;
case 'u8':
case 'uint8_t':
case 'int8_t':
case 'ubyte':
case 'i8':
case 'byte':
Wrapper.setValue(pointer, value, 'i8');
break;
case 'u16':
case 'uint16_t':
case 'int16_t':
case 'ushort':
case 'i16':
case 'short':
Wrapper.setValue(pointer, value, 'i16');
break;
case 'u32':
case 'uint32_t':
case 'int32_t':
case 'uint':
case 'i32':
case 'int':
Wrapper.setValue(pointer, value, 'i32');
break;
case 'i64':
case 'u64':
case 'uint64_t':
case 'int64_t':
case 'long':
case 'ulong':
/*Wrapper.HEAP32[pointer >> 2] = value; // Low 32 bits
Wrapper.HEAP32[(pointer + 4) >> 2] = Math.floor(value / 4294967295); // High 32 bits
*/
let tmp_double, tmp_i64;
(tmp_i64 = [
value >>> 0,
((tmp_double = value),
+Math.abs(tmp_double) >= +1
? tmp_double > +0
? (Math.min(+Math.floor(tmp_double / +4294967296), +4294967295) |
0) >>>
0
: ~~+Math.ceil(
(tmp_double - +(~~tmp_double >>> 0)) / +4294967296,
) >>> 0
: 0),
]),
(Wrapper.HEAP32[pointer >> 2] = tmp_i64[0]),
(Wrapper.HEAP32[(pointer + 4) >> 2] = tmp_i64[1]);
break;
case 'float':
Wrapper.HEAPF32[pointer >> 2] = value;
break;
case 'i8*':
case '*':
case 'float':
case 'double':
Wrapper.setValue(pointer, value, type);
break;
default:
throw new Error(`Unknown type: ${type}`);
}
}
export function read(pointer: pointer_t<any>, type: native_t): any {
let value;
switch (type) {
case 'char':
case 'char*':
value = Wrapper.UTF8ToString(pointer);
break;
case 'bool':
case 'boolean':
value = Boolean(Wrapper.getValue(pointer, 'i8'));
break;
case 'u8':
case 'ubyte':
case 'i8':
case 'byte':
value = Wrapper.getValue(pointer, 'i8');
if (type.startsWith('u')) value = value & 0xff;
break;
case 'u16':
case 'ushort':
case 'i16':
case 'short':
value = Wrapper.getValue(pointer, 'i16');
break;
case 'u32':
case 'uint':
case 'i32':
case 'int':
value = Wrapper.getValue(pointer, 'i32');
break;
case 'i64':
case 'u64':
case 'long':
case 'ulong':
/*
const low = Wrapper.HEAP32[pointer >> 2]; // Low 32 bits
const high = Wrapper.HEAP32[(pointer + 4) >> 2]; // High 32 bits
value = low + high * 4294967296; // Combine high and low bits
*/
value = Wrapper.HEAP32[pointer >> 2];
break;
case 'i8*':
case '*':
case 'float':
case 'double':
value = Wrapper.getValue(pointer, type);
break;
default:
throw new Error(`Unknown type: ${type}`);
}
return value;
}
}