@tychosdk/disasm 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/disasm/fift.js +56 -45
- package/dist/disasm/structured.d.ts +11 -5
- package/dist/disasm/structured.js +47 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/wasm/tycho_disasm_bg.wasm +0 -0
- package/package.json +1 -1
package/dist/disasm/fift.js
CHANGED
|
@@ -1,48 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.disasmToFift = disasmToFift;
|
|
4
|
-
const core_1 = require("@ton/core");
|
|
5
4
|
const structured_1 = require("./structured");
|
|
6
5
|
async function disasmToFift(code, params = {}) {
|
|
7
6
|
const { root, items } = await (0, structured_1.disasmStructured)(code);
|
|
8
|
-
const codeCells = new CodeCells(code);
|
|
7
|
+
const codeCells = new structured_1.CodeCells(code);
|
|
9
8
|
const ctx = new Context(items, codeCells, {
|
|
10
9
|
tabWidth: params.tabWidth != null ? params.tabWidth : 2,
|
|
11
10
|
});
|
|
12
11
|
new State(ctx, 0).disasm(ctx.getCode(root));
|
|
13
12
|
return ctx.output;
|
|
14
13
|
}
|
|
15
|
-
class CodeCells {
|
|
16
|
-
constructor(code) {
|
|
17
|
-
this.hashToCell = new Map();
|
|
18
|
-
const stack = [];
|
|
19
|
-
if (code instanceof core_1.Cell) {
|
|
20
|
-
stack.push(code);
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
stack.push(core_1.Cell.fromBase64(code));
|
|
24
|
-
}
|
|
25
|
-
while (stack.length > 0) {
|
|
26
|
-
const cell = stack[stack.length - 1];
|
|
27
|
-
const reprHash = cell.hash(3).toString("hex");
|
|
28
|
-
if (this.hashToCell.has(reprHash)) {
|
|
29
|
-
stack.pop();
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
this.hashToCell.set(reprHash, cell);
|
|
33
|
-
for (const child of cell.refs) {
|
|
34
|
-
stack.push(child);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
getCell(hash) {
|
|
40
|
-
const res = this.hashToCell.get(hash);
|
|
41
|
-
if (res == null)
|
|
42
|
-
throw new Error("Unknown cell");
|
|
43
|
-
return res;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
14
|
class State {
|
|
47
15
|
constructor(ctx, depth) {
|
|
48
16
|
this.ctx = ctx;
|
|
@@ -50,22 +18,64 @@ class State {
|
|
|
50
18
|
}
|
|
51
19
|
disasm(block) {
|
|
52
20
|
while (true) {
|
|
21
|
+
let opcodeBits = 0;
|
|
22
|
+
let opcodeRefs = 0;
|
|
53
23
|
for (const opcode of block.opcodes) {
|
|
54
24
|
this.showOp(opcode);
|
|
25
|
+
opcodeBits += opcode.bits;
|
|
26
|
+
opcodeRefs += opcode.refs || 0;
|
|
55
27
|
}
|
|
56
28
|
if (block.tail == null) {
|
|
29
|
+
this.dict = undefined;
|
|
30
|
+
this.flushCont();
|
|
57
31
|
break;
|
|
58
32
|
}
|
|
59
33
|
else if (block.tail.type === "incomplete") {
|
|
60
|
-
this.
|
|
34
|
+
this.dict = undefined;
|
|
35
|
+
this.flushCont();
|
|
36
|
+
this.showIncompleteTail(block, opcodeBits, opcodeRefs);
|
|
61
37
|
break;
|
|
62
38
|
}
|
|
63
39
|
else {
|
|
64
40
|
block = this.ctx.getCode(block.tail.id);
|
|
65
41
|
}
|
|
66
42
|
}
|
|
67
|
-
|
|
68
|
-
|
|
43
|
+
}
|
|
44
|
+
showIncompleteTail(block, opcodeBits, opcodeRefs) {
|
|
45
|
+
const cell = this.ctx.getCell(block.cellHash);
|
|
46
|
+
const bits = cell
|
|
47
|
+
.asSlice()
|
|
48
|
+
.skip(block.offsetBits + opcodeBits)
|
|
49
|
+
.loadBits(block.bits - opcodeBits);
|
|
50
|
+
this.writeln(`Cannot disassemble: x{${bits.toString()}}`);
|
|
51
|
+
const stack = [];
|
|
52
|
+
if (opcodeRefs < block.refs) {
|
|
53
|
+
stack.push({
|
|
54
|
+
depth: 1,
|
|
55
|
+
refs: cell.refs.slice(block.offsetRefs + opcodeRefs, block.offsetRefs + block.refs),
|
|
56
|
+
index: block.offsetRefs + opcodeRefs,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const prevDepth = this.depth;
|
|
60
|
+
this.depth = 0;
|
|
61
|
+
outer: while (stack.length > 0) {
|
|
62
|
+
const item = stack[stack.length - 1];
|
|
63
|
+
while (item.index < item.refs.length) {
|
|
64
|
+
const child = item.refs[item.index++];
|
|
65
|
+
const indent = " ".repeat(item.depth);
|
|
66
|
+
this.writeln(`${indent}x{${child.bits.toString()}}`);
|
|
67
|
+
if (child.refs.length > 0) {
|
|
68
|
+
stack.push({
|
|
69
|
+
depth: item.depth + 1,
|
|
70
|
+
refs: child.refs,
|
|
71
|
+
index: 0,
|
|
72
|
+
});
|
|
73
|
+
continue outer;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
stack.pop();
|
|
77
|
+
}
|
|
78
|
+
this.depth = prevDepth;
|
|
69
79
|
}
|
|
70
80
|
showOp(opcode) {
|
|
71
81
|
// Track consequent dict ops.
|
|
@@ -384,20 +394,20 @@ class Context {
|
|
|
384
394
|
break;
|
|
385
395
|
}
|
|
386
396
|
case "library": {
|
|
387
|
-
cellHash = item.
|
|
397
|
+
cellHash = item.cellHash;
|
|
388
398
|
break;
|
|
389
399
|
}
|
|
390
|
-
case "
|
|
400
|
+
case "data": {
|
|
391
401
|
if (item.data.type !== "cell")
|
|
392
402
|
throw new Error("Unexpected slice");
|
|
393
|
-
cellHash =
|
|
403
|
+
cellHash = item.data.cellHash;
|
|
394
404
|
break;
|
|
395
405
|
}
|
|
396
406
|
case "jumpTable": {
|
|
397
407
|
throw new Error("Unexpected jump table");
|
|
398
408
|
}
|
|
399
409
|
}
|
|
400
|
-
return `(${cellHash})`;
|
|
410
|
+
return `(${cellHash.toUpperCase()})`;
|
|
401
411
|
}
|
|
402
412
|
case "slice": {
|
|
403
413
|
const item = this.items[arg.id];
|
|
@@ -412,12 +422,13 @@ class Context {
|
|
|
412
422
|
refCount = item.refs;
|
|
413
423
|
break;
|
|
414
424
|
}
|
|
415
|
-
case "
|
|
425
|
+
case "data": {
|
|
416
426
|
if (item.data.type !== "slice")
|
|
417
427
|
throw new Error("Unexpected cell");
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
428
|
+
const { data } = item;
|
|
429
|
+
const cell = this.getCell(data.cellHash);
|
|
430
|
+
bits = cell.asSlice().skip(data.offsetBits).loadBits(data.bits);
|
|
431
|
+
refCount = data.refs;
|
|
421
432
|
break;
|
|
422
433
|
}
|
|
423
434
|
case "jumpTable": {
|
|
@@ -432,7 +443,7 @@ class Context {
|
|
|
432
443
|
return `(${bits.toString()},${refCount})`;
|
|
433
444
|
}
|
|
434
445
|
else {
|
|
435
|
-
return bits.toString()
|
|
446
|
+
return `x{${bits.toString()}}`;
|
|
436
447
|
}
|
|
437
448
|
}
|
|
438
449
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Cell } from "@ton/core";
|
|
1
|
+
import { Cell, Slice } from "@ton/core";
|
|
2
2
|
/**
|
|
3
3
|
* All code parts are referenced by a numberic ID.
|
|
4
4
|
*/
|
|
@@ -18,7 +18,7 @@ export type Item = ({
|
|
|
18
18
|
type: "code";
|
|
19
19
|
} & CodeBlock) | ({
|
|
20
20
|
id: number;
|
|
21
|
-
type: "
|
|
21
|
+
type: "data";
|
|
22
22
|
} & DataBlock) | ({
|
|
23
23
|
id: number;
|
|
24
24
|
type: "library";
|
|
@@ -99,19 +99,25 @@ export type Data = ({
|
|
|
99
99
|
} & DataCell);
|
|
100
100
|
export type DataType = Data["type"];
|
|
101
101
|
export type DataSlice = {
|
|
102
|
+
cellHash: string;
|
|
102
103
|
offsetBits: number;
|
|
103
104
|
offsetRefs: number;
|
|
104
105
|
bits: number;
|
|
105
106
|
refs: number;
|
|
106
|
-
boc: string;
|
|
107
107
|
};
|
|
108
108
|
export type DataCell = {
|
|
109
|
-
|
|
109
|
+
cellHash: string;
|
|
110
110
|
};
|
|
111
111
|
export type Library = {
|
|
112
|
-
|
|
112
|
+
cellHash: string;
|
|
113
113
|
};
|
|
114
114
|
export declare function disasmStructured(code: Cell | string): Promise<Code>;
|
|
115
|
+
export declare class CodeCells {
|
|
116
|
+
private hashToCell;
|
|
117
|
+
constructor(code: Cell | string);
|
|
118
|
+
getCell(hash: DataCell | DataSlice | Library | JumpTable | CodeBlock | string): Cell;
|
|
119
|
+
getSlice(slice: DataSlice | CodeBlock): Slice;
|
|
120
|
+
}
|
|
115
121
|
export declare function expectJumpTable(item: Item): asserts item is {
|
|
116
122
|
id: ItemId;
|
|
117
123
|
type: "jumpTable";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CodeCells = void 0;
|
|
3
4
|
exports.disasmStructured = disasmStructured;
|
|
4
5
|
exports.expectJumpTable = expectJumpTable;
|
|
5
6
|
exports.expectCont = expectCont;
|
|
@@ -15,6 +16,7 @@ exports.expectSliceArg = expectSliceArg;
|
|
|
15
16
|
exports.expectContArg = expectContArg;
|
|
16
17
|
const core_1 = require("@ton/core");
|
|
17
18
|
const env_1 = require("../env");
|
|
19
|
+
const slice_1 = require("../util/slice");
|
|
18
20
|
async function disasmStructured(code) {
|
|
19
21
|
await (0, env_1.wasmLoaded)();
|
|
20
22
|
let boc;
|
|
@@ -28,6 +30,51 @@ async function disasmStructured(code) {
|
|
|
28
30
|
const parsed = JSON.parse(res);
|
|
29
31
|
return parsed;
|
|
30
32
|
}
|
|
33
|
+
class CodeCells {
|
|
34
|
+
constructor(code) {
|
|
35
|
+
this.hashToCell = new Map();
|
|
36
|
+
if (typeof code === "string") {
|
|
37
|
+
code = core_1.Cell.fromBase64(code);
|
|
38
|
+
}
|
|
39
|
+
const stack = [];
|
|
40
|
+
const addCell = (cell) => {
|
|
41
|
+
const reprHash = cell.hash(3).toString("hex");
|
|
42
|
+
if (this.hashToCell.has(reprHash)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
this.hashToCell.set(reprHash, cell);
|
|
46
|
+
if (cell.refs.length > 0) {
|
|
47
|
+
stack.push({ refs: cell.refs, index: 0 });
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
};
|
|
51
|
+
addCell(code);
|
|
52
|
+
outer: while (stack.length > 0) {
|
|
53
|
+
const item = stack[stack.length - 1];
|
|
54
|
+
while (item.index < item.refs.length) {
|
|
55
|
+
const child = item.refs[item.index++];
|
|
56
|
+
if (addCell(child)) {
|
|
57
|
+
continue outer;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
stack.pop();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
getCell(hash) {
|
|
64
|
+
if (typeof hash === "object") {
|
|
65
|
+
hash = hash.cellHash;
|
|
66
|
+
}
|
|
67
|
+
const res = this.hashToCell.get(hash);
|
|
68
|
+
if (res == null)
|
|
69
|
+
throw new Error("Unknown cell");
|
|
70
|
+
return res;
|
|
71
|
+
}
|
|
72
|
+
getSlice(slice) {
|
|
73
|
+
const cell = this.getCell(slice);
|
|
74
|
+
return (0, slice_1.makeSlice)(cell, slice.offsetBits, slice.offsetRefs, slice.bits, slice.refs);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.CodeCells = CodeCells;
|
|
31
78
|
// === Expect Item ===
|
|
32
79
|
function expectJumpTable(item) {
|
|
33
80
|
if (item.type !== "jumpTable")
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { disasmStructured, expectCellArg, expectCont, expectContArg, expectData, expectDataCell, expectDataSlice, expectIntArg, expectJumpTable, expectLibrary, expectRegArg, expectSliceArg, expectStackArg, Code, CodeBlock, CodeBlockTail, CodeBlockTailType, Data, DataBlock, DataCell, DataSlice, DataType, Item, ItemId, ItemType, JumpTable, Library, Opcode, OpcodeArg, OpcodeArgType, } from "./disasm/structured";
|
|
1
|
+
export { disasmStructured, expectCellArg, expectCont, expectContArg, expectData, expectDataCell, expectDataSlice, expectIntArg, expectJumpTable, expectLibrary, expectRegArg, expectSliceArg, expectStackArg, Code, CodeBlock, CodeBlockTail, CodeBlockTailType, CodeCells, Data, DataBlock, DataCell, DataSlice, DataType, Item, ItemId, ItemType, JumpTable, Library, Opcode, OpcodeArg, OpcodeArgType, } from "./disasm/structured";
|
|
2
2
|
export { disasmToFift } from "./disasm/fift";
|
|
3
3
|
export { makeSlice } from "./util/slice";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.makeSlice = exports.disasmToFift = exports.expectStackArg = exports.expectSliceArg = exports.expectRegArg = exports.expectLibrary = exports.expectJumpTable = exports.expectIntArg = exports.expectDataSlice = exports.expectDataCell = exports.expectData = exports.expectContArg = exports.expectCont = exports.expectCellArg = exports.disasmStructured = void 0;
|
|
3
|
+
exports.makeSlice = exports.disasmToFift = exports.CodeCells = exports.expectStackArg = exports.expectSliceArg = exports.expectRegArg = exports.expectLibrary = exports.expectJumpTable = exports.expectIntArg = exports.expectDataSlice = exports.expectDataCell = exports.expectData = exports.expectContArg = exports.expectCont = exports.expectCellArg = exports.disasmStructured = void 0;
|
|
4
4
|
var structured_1 = require("./disasm/structured");
|
|
5
5
|
Object.defineProperty(exports, "disasmStructured", { enumerable: true, get: function () { return structured_1.disasmStructured; } });
|
|
6
6
|
Object.defineProperty(exports, "expectCellArg", { enumerable: true, get: function () { return structured_1.expectCellArg; } });
|
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "expectLibrary", { enumerable: true, get: functio
|
|
|
15
15
|
Object.defineProperty(exports, "expectRegArg", { enumerable: true, get: function () { return structured_1.expectRegArg; } });
|
|
16
16
|
Object.defineProperty(exports, "expectSliceArg", { enumerable: true, get: function () { return structured_1.expectSliceArg; } });
|
|
17
17
|
Object.defineProperty(exports, "expectStackArg", { enumerable: true, get: function () { return structured_1.expectStackArg; } });
|
|
18
|
+
Object.defineProperty(exports, "CodeCells", { enumerable: true, get: function () { return structured_1.CodeCells; } });
|
|
18
19
|
var fift_1 = require("./disasm/fift");
|
|
19
20
|
Object.defineProperty(exports, "disasmToFift", { enumerable: true, get: function () { return fift_1.disasmToFift; } });
|
|
20
21
|
var slice_1 = require("./util/slice");
|
|
Binary file
|