UNPKG

sevm

Version:

A Symbolic Ethereum Virtual Machine (EVM) bytecode decompiler & analyzer library & CLI

212 lines 7.07 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _Local_memo; Object.defineProperty(exports, "__esModule", { value: true }); exports.mem = exports.inline0 = exports.reduce = exports.Locali = exports.Local = exports.Val = exports.MOD_256 = exports.Tag = exports.Require = exports.CallSite = exports.If = exports.Throw = exports.evalE = exports.isInst = exports.isExpr = void 0; const isExpr = (expr) => expr !== null && typeof expr === 'object' && 'tag' in expr; exports.isExpr = isExpr; const isInst = (inst) => inst !== null && typeof inst === 'object' && 'name' in inst; exports.isInst = isInst; const evalE = (expr) => expr.eval(); exports.evalE = evalE; class Throw { constructor(reason, opcode) { this.reason = reason; this.opcode = opcode; this.name = 'Throw'; } eval() { return this; } } exports.Throw = Throw; // export class Assign { // readonly name = 'Asign'; // constructor(readonly i: number, readonly phi: Phi) {} // eval() { // return this; // } // toString() { // return `local${this.i} = ${this.phi.toString()};`; // } // } class If { constructor(condition, trueBlock, falseBlock) { this.condition = condition; this.trueBlock = trueBlock; this.falseBlock = falseBlock; this.name = 'If'; } eval() { return new If(this.condition.eval(), this.trueBlock ? reduce(this.trueBlock) : undefined, this.falseBlock ? reduce(this.falseBlock) : undefined); } } exports.If = If; class CallSite { constructor(selector) { this.selector = selector; this.name = 'CallSite'; } eval() { return this; } } exports.CallSite = CallSite; class Require { constructor(condition, selector, args) { this.condition = condition; this.selector = selector; this.args = args; this.name = 'Require'; } eval() { return new Require(this.condition.eval(), this.selector, this.args.map(exports.evalE)); } } exports.Require = Require; class Tag { constructor(depth, count) { this.depth = depth; this.count = count; } isVal() { return this.tag === 'Val'; } isZero() { return this.isVal() && this.val === 0n; } isJumpDest() { return this.isVal() && this.jumpDest !== null; } children() { return Object.values(this).filter(value => value instanceof Tag); } unwrap() { return this; } } exports.Tag = Tag; exports.MOD_256 = 1n << 0x100n; class Val extends Tag { constructor(val, pushStateId) { if (val < 0 || val >= exports.MOD_256) throw new Error(`Val is a not a valid unsigned 256-word: ${val}`); super(0, 1); this.val = val; this.pushStateId = pushStateId; this.tag = 'Val'; this.jumpDest = null; } eval() { return new Val(this.val); } } exports.Val = Val; class Local extends Tag { constructor(index, value) { super(value.depth + 1, value.count + 1); this.index = index; this.value = value; this.tag = 'Local'; this.nrefs = 0; _Local_memo.set(this, undefined); } eval() { if (__classPrivateFieldGet(this, _Local_memo, "f") === undefined) __classPrivateFieldSet(this, _Local_memo, this.value.eval(), "f"); return __classPrivateFieldGet(this, _Local_memo, "f"); } unwrap() { return this.value; } } exports.Local = Local; _Local_memo = new WeakMap(); class Locali { constructor(local) { this.local = local; this.name = 'Local'; } eval() { return this; } } exports.Locali = Locali; function reduce(stmts) { return stmts?.flatMap(stmt => ['Local', 'MStore'].includes(stmt.name) ? [] : stmt.eval()); } exports.reduce = reduce; function inline0(stmts) { const reachable = new WeakSet(); const result = []; for (const stmt of stmts.reverse()) { if (stmt.name === 'MStore') { reach(stmt.location); reach(stmt.data); } else if (stmt.name === 'Local' && reachable.has(stmt.local)) { continue; } result.unshift(stmt); } return result; function reach(expr) { reachable.add(expr); expr.children().forEach(reach); } } exports.inline0 = inline0; function mem(stmts) { // const reachable = new WeakSet<Expr>(); const result = []; for (const stmt of stmts.reverse()) { if (stmt.name === 'MStore') { reach(stmt.location); reach(stmt.data); // } else if (stmt.name === 'Local' && reachable.has(stmt.local)) { // continue; } result.unshift(stmt); } return result; function reach(expr) { // reachable.add(expr); if (expr.tag === 'Local') { expr.nrefs--; } expr.children().forEach(reach); } } exports.mem = mem; __exportStar(require("./alu"), exports); __exportStar(require("./flow"), exports); __exportStar(require("./log"), exports); __exportStar(require("./memory"), exports); __exportStar(require("./special"), exports); __exportStar(require("./storage"), exports); __exportStar(require("./system"), exports); //# sourceMappingURL=index.js.map