|
|
@ -1,21 +1,27 @@ |
|
|
|
'use strict' |
|
|
|
'use strict' |
|
|
|
const codeUtils = require('./codeUtils') |
|
|
|
const codeUtils = require('./codeUtils') |
|
|
|
|
|
|
|
|
|
|
|
function CodeResolver ({getCode}) { |
|
|
|
export class CodeResolver { |
|
|
|
this.getCode = getCode |
|
|
|
|
|
|
|
|
|
|
|
getCode |
|
|
|
|
|
|
|
bytecodeByAddress |
|
|
|
|
|
|
|
instructionsByAddress |
|
|
|
|
|
|
|
instructionsIndexByBytesOffset |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor({getCode}) { |
|
|
|
|
|
|
|
this.getCode = getCode |
|
|
|
this.bytecodeByAddress = {} // bytes code by contract addesses
|
|
|
|
this.bytecodeByAddress = {} // bytes code by contract addesses
|
|
|
|
this.instructionsByAddress = {} // assembly items instructions list by contract addesses
|
|
|
|
this.instructionsByAddress = {} // assembly items instructions list by contract addesses
|
|
|
|
this.instructionsIndexByBytesOffset = {} // mapping between bytes offset and instructions index.
|
|
|
|
this.instructionsIndexByBytesOffset = {} // mapping between bytes offset and instructions index.
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CodeResolver.prototype.clear = function () { |
|
|
|
clear () { |
|
|
|
this.bytecodeByAddress = {} |
|
|
|
this.bytecodeByAddress = {} |
|
|
|
this.instructionsByAddress = {} |
|
|
|
this.instructionsByAddress = {} |
|
|
|
this.instructionsIndexByBytesOffset = {} |
|
|
|
this.instructionsIndexByBytesOffset = {} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CodeResolver.prototype.resolveCode = async function (address) { |
|
|
|
async resolveCode (address) { |
|
|
|
const cache = this.getExecutingCodeFromCache(address) |
|
|
|
const cache = this.getExecutingCodeFromCache(address) |
|
|
|
if (cache) { |
|
|
|
if (cache) { |
|
|
|
return cache |
|
|
|
return cache |
|
|
@ -25,7 +31,7 @@ CodeResolver.prototype.resolveCode = async function (address) { |
|
|
|
return this.cacheExecutingCode(address, code) |
|
|
|
return this.cacheExecutingCode(address, code) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CodeResolver.prototype.cacheExecutingCode = function (address, hexCode) { |
|
|
|
cacheExecutingCode (address, hexCode) { |
|
|
|
const codes = this.formatCode(hexCode) |
|
|
|
const codes = this.formatCode(hexCode) |
|
|
|
this.bytecodeByAddress[address] = hexCode |
|
|
|
this.bytecodeByAddress[address] = hexCode |
|
|
|
this.instructionsByAddress[address] = codes.code |
|
|
|
this.instructionsByAddress[address] = codes.code |
|
|
@ -33,12 +39,12 @@ CodeResolver.prototype.cacheExecutingCode = function (address, hexCode) { |
|
|
|
return this.getExecutingCodeFromCache(address) |
|
|
|
return this.getExecutingCodeFromCache(address) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CodeResolver.prototype.formatCode = function (hexCode) { |
|
|
|
formatCode (hexCode) { |
|
|
|
const [code, instructionsIndexByBytesOffset] = codeUtils.nameOpCodes(Buffer.from(hexCode.substring(2), 'hex')) |
|
|
|
const [code, instructionsIndexByBytesOffset] = codeUtils.nameOpCodes(Buffer.from(hexCode.substring(2), 'hex')) |
|
|
|
return {code, instructionsIndexByBytesOffset} |
|
|
|
return {code, instructionsIndexByBytesOffset} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CodeResolver.prototype.getExecutingCodeFromCache = function (address) { |
|
|
|
getExecutingCodeFromCache (address) { |
|
|
|
if (!this.instructionsByAddress[address]) { |
|
|
|
if (!this.instructionsByAddress[address]) { |
|
|
|
return null |
|
|
|
return null |
|
|
|
} |
|
|
|
} |
|
|
@ -49,8 +55,7 @@ CodeResolver.prototype.getExecutingCodeFromCache = function (address) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CodeResolver.prototype.getInstructionIndex = function (address, pc) { |
|
|
|
getInstructionIndex (address, pc) { |
|
|
|
return this.getExecutingCodeFromCache(address).instructionsIndexByBytesOffset[pc] |
|
|
|
return this.getExecutingCodeFromCache(address).instructionsIndexByBytesOffset[pc] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
module.exports = CodeResolver |
|
|
|
|
|
|
|