codeResolver and codeUtils updated

pull/5370/head
aniket-engg 4 years ago committed by Aniket
parent 763000ebaa
commit 18525f620d
  1. 91
      libs/remix-debug/src/code/codeResolver.ts
  2. 103
      libs/remix-debug/src/code/codeUtils.ts

@ -1,56 +1,61 @@
'use strict' 'use strict'
const codeUtils = require('./codeUtils') const codeUtils = require('./codeUtils')
function CodeResolver ({getCode}) { export class CodeResolver {
this.getCode = getCode
getCode
this.bytecodeByAddress = {} // bytes code by contract addesses bytecodeByAddress
this.instructionsByAddress = {} // assembly items instructions list by contract addesses instructionsByAddress
this.instructionsIndexByBytesOffset = {} // mapping between bytes offset and instructions index. instructionsIndexByBytesOffset
}
constructor({getCode}) {
CodeResolver.prototype.clear = function () { this.getCode = getCode
this.bytecodeByAddress = {} this.bytecodeByAddress = {} // bytes code by contract addesses
this.instructionsByAddress = {} this.instructionsByAddress = {} // assembly items instructions list by contract addesses
this.instructionsIndexByBytesOffset = {} this.instructionsIndexByBytesOffset = {} // mapping between bytes offset and instructions index.
} }
CodeResolver.prototype.resolveCode = async function (address) { clear () {
const cache = this.getExecutingCodeFromCache(address) this.bytecodeByAddress = {}
if (cache) { this.instructionsByAddress = {}
return cache this.instructionsIndexByBytesOffset = {}
} }
const code = await this.getCode(address) async resolveCode (address) {
return this.cacheExecutingCode(address, code) const cache = this.getExecutingCodeFromCache(address)
} if (cache) {
return cache
}
CodeResolver.prototype.cacheExecutingCode = function (address, hexCode) { const code = await this.getCode(address)
const codes = this.formatCode(hexCode) return this.cacheExecutingCode(address, code)
this.bytecodeByAddress[address] = hexCode }
this.instructionsByAddress[address] = codes.code
this.instructionsIndexByBytesOffset[address] = codes.instructionsIndexByBytesOffset
return this.getExecutingCodeFromCache(address)
}
CodeResolver.prototype.formatCode = function (hexCode) { cacheExecutingCode (address, hexCode) {
const [code, instructionsIndexByBytesOffset] = codeUtils.nameOpCodes(Buffer.from(hexCode.substring(2), 'hex')) const codes = this.formatCode(hexCode)
return {code, instructionsIndexByBytesOffset} this.bytecodeByAddress[address] = hexCode
} this.instructionsByAddress[address] = codes.code
this.instructionsIndexByBytesOffset[address] = codes.instructionsIndexByBytesOffset
return this.getExecutingCodeFromCache(address)
}
CodeResolver.prototype.getExecutingCodeFromCache = function (address) { formatCode (hexCode) {
if (!this.instructionsByAddress[address]) { const [code, instructionsIndexByBytesOffset] = codeUtils.nameOpCodes(Buffer.from(hexCode.substring(2), 'hex'))
return null return {code, instructionsIndexByBytesOffset}
} }
return {
instructions: this.instructionsByAddress[address], getExecutingCodeFromCache (address) {
instructionsIndexByBytesOffset: this.instructionsIndexByBytesOffset[address], if (!this.instructionsByAddress[address]) {
bytecode: this.bytecodeByAddress[address] return null
}
return {
instructions: this.instructionsByAddress[address],
instructionsIndexByBytesOffset: this.instructionsIndexByBytesOffset[address],
bytecode: this.bytecodeByAddress[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

@ -1,66 +1,65 @@
'use strict' 'use strict'
const opcodes = require('./opcodes') const opcodes = require('./opcodes')
module.exports = { export function nameOpCodes (raw) {
nameOpCodes: function (raw) { let pushData = ''
let pushData = '' const codeMap = {}
const codeMap = {} const code = []
const code = []
for (let i = 0; i < raw.length; i++) { for (let i = 0; i < raw.length; i++) {
const pc = i const pc = i
const curOpCode = opcodes(raw[pc], false).name const curOpCode = opcodes(raw[pc], false).name
codeMap[i] = code.length codeMap[i] = code.length
// no destinations into the middle of PUSH // no destinations into the middle of PUSH
if (curOpCode.slice(0, 4) === 'PUSH') { if (curOpCode.slice(0, 4) === 'PUSH') {
const jumpNum = raw[pc] - 0x5f const jumpNum = raw[pc] - 0x5f
pushData = raw.slice(pc + 1, pc + jumpNum + 1) pushData = raw.slice(pc + 1, pc + jumpNum + 1)
i += jumpNum i += jumpNum
} }
const data = pushData.toString('hex') !== '' ? ' ' + pushData.toString('hex') : '' const data = pushData.toString() !== '' ? ' ' + pushData.toString() : ''
code.push(this.pad(pc, this.roundLog(raw.length, 10)) + ' ' + curOpCode + data) code.push(this.pad(pc, this.roundLog(raw.length, 10)) + ' ' + curOpCode + data)
pushData = '' pushData = ''
} }
return [ code, codeMap ] return [ code, codeMap ]
}, }
/** /**
* Parses code as a list of integers into a list of objects containing * Parses code as a list of integers into a list of objects containing
* information about the opcode. * information about the opcode.
*/ */
parseCode: function (raw) { export function parseCode (raw) {
const code = [] const code = []
for (let i = 0; i < raw.length; i++) { for (let i = 0; i < raw.length; i++) {
const opcode = opcodes(raw[i], true) const opcode = opcodes(raw[i], true)
if (opcode.name.slice(0, 4) === 'PUSH') { if (opcode.name.slice(0, 4) === 'PUSH') {
const length = raw[i] - 0x5f const length = raw[i] - 0x5f
opcode.pushData = raw.slice(i + 1, i + length + 1) opcode.pushData = raw.slice(i + 1, i + length + 1)
// in case pushdata extends beyond code // in case pushdata extends beyond code
if (i + 1 + length > raw.length) { if (i + 1 + length > raw.length) {
for (let j = opcode.pushData.length; j < length; j++) { for (let j = opcode.pushData.length; j < length; j++) {
opcode.pushData.push(0) opcode.pushData.push(0)
}
} }
i += length
} }
code.push(opcode) i += length
} }
return code code.push(opcode)
}, }
return code
}
pad: function (num, size) { export function pad (num, size) {
let s = num + '' let s = num + ''
while (s.length < size) s = '0' + s while (s.length < size) s = '0' + s
return s return s
}, }
log: function (num, base) { export function log (num, base) {
return Math.log(num) / Math.log(base) return Math.log(num) / Math.log(base)
}, }
roundLog: function (num, base) { export function roundLog (num, base) {
return Math.ceil(this.log(num, base)) return Math.ceil(this.log(num, base))
}
} }

Loading…
Cancel
Save