Merge pull request #101 from yann300/sourceMappingDecoder

source location tracker
pull/7/head
chriseth 8 years ago committed by GitHub
commit 3f146dc921
  1. 28
      src/code/codeManager.js
  2. 19
      src/code/codeResolver.js
  3. 58
      src/code/sourceLocationTracker.js
  4. 6
      src/ui/Ethdebugger.js
  5. 7
      src/web3Provider/web3Providers.js

@ -25,39 +25,45 @@ CodeManager.prototype.resolveStep = function (stepIndex, tx) {
this.trigger('resolvingStep')
var self = this
if (stepIndex === 0) {
self.getCode(tx.to, stepIndex, tx)
self.retrieveCodeAndTrigger(tx.to, stepIndex, tx)
} else {
this.traceManager.getCurrentCalledAddressAt(stepIndex, function (error, address) {
if (error) {
console.log(error)
} else {
self.getCode(address, stepIndex, tx)
self.retrieveCodeAndTrigger(address, stepIndex, tx)
}
})
}
}
CodeManager.prototype.getCode = function (address, currentStep, tx) {
CodeManager.prototype.retrieveCodeAndTrigger = function (address, stepIndex, tx) {
var self = this
this.getCode(address, function (error, result) {
if (!error) {
self.retrieveIndexAndTrigger(address, stepIndex, result.instructions)
} else {
console.log(error)
}
})
}
CodeManager.prototype.getCode = function (address, cb) {
if (traceHelper.isContractCreation(address)) {
var codes = codeResolver.getExecutingCodeFromCache(address)
if (!codes) {
this.traceManager.getContractCreationCode(address, function (error, hexCode) {
// contract creation
if (error) {
console.log(error)
} else {
if (!error) {
codes = codeResolver.cacheExecutingCode(address, hexCode)
self.retrieveIndexAndTrigger(address, currentStep, codes.code)
cb(null, codes)
}
})
} else {
self.retrieveIndexAndTrigger(address, currentStep, codes.code)
cb(null, codes)
}
} else {
codeResolver.resolveCode(address, function (address, code) {
// resoling code from stack
self.retrieveIndexAndTrigger(address, currentStep, code)
cb(null, code)
})
}
}

@ -3,19 +3,20 @@ var codeUtils = require('./codeUtils')
var util = require('../helpers/global')
module.exports = {
codes: {}, // assembly items instructions list by contract addesses
bytecodeByAddress: {}, // bytes code by contract addesses
instructionsByAddress: {}, // assembly items instructions list by contract addesses
instructionsIndexByBytesOffset: {}, // mapping between bytes offset and instructions index.
resolveCode: function (address, callBack) {
var cache = this.getExecutingCodeFromCache(address)
if (cache) {
callBack(address, cache.code)
callBack(address, cache)
return
}
var self = this
this.loadCode(address, function (code) {
callBack(address, self.cacheExecutingCode(address, code).code)
callBack(address, self.cacheExecutingCode(address, code))
})
},
@ -32,9 +33,10 @@ module.exports = {
cacheExecutingCode: function (address, hexCode) {
var codes = this.formatCode(hexCode)
this.codes[address] = codes.code
this.bytecodeByAddress[address] = hexCode
this.instructionsByAddress[address] = codes.code
this.instructionsIndexByBytesOffset[address] = codes.instructionsIndexByBytesOffset
return codes
return this.getExecutingCodeFromCache(address)
},
formatCode: function (hexCode) {
@ -46,10 +48,11 @@ module.exports = {
},
getExecutingCodeFromCache: function (address) {
if (this.codes[address]) {
if (this.instructionsByAddress[address]) {
return {
code: this.codes[address],
instructionsIndexByBytesOffset: this.instructionsIndexByBytesOffset[address]
instructions: this.instructionsByAddress[address],
instructionsIndexByBytesOffset: this.instructionsIndexByBytesOffset[address],
bytecode: this.bytecodeByAddress[address]
}
} else {
return null

@ -0,0 +1,58 @@
'use strict'
var EventManager = require('../lib/eventManager')
var util = require('../helpers/global')
var helper = require('../helpers/traceHelper')
var SourceMappingDecoder = require('../util/sourceMappingDecoder')
/**
* Process the source code location for the current executing bytecode
*/
function SourceLocationTracker (_codeManager) {
this.codeManager = _codeManager
util.extend(this, new EventManager())
this.sourceMappingDecoder = new SourceMappingDecoder()
}
/**
* Return the source location associated with the given @arg index
*
* @param {String} address - contract address from which the source location is retrieved
* @param {Int} index - index in the instruction list from where the source location is retrieved
* @param {Object} contractDetails - AST of compiled contracts
* @param {Function} cb - callback function
*/
SourceLocationTracker.prototype.getSourceLocation = function (address, index, contractsDetails, cb) {
var self = this
this.codeManager.getCode(address, function (error, result) {
if (!error) {
var sourceMap = getSourceMap(address, result.bytecode, contractsDetails)
if (sourceMap) {
cb(null, self.sourceMappingDecoder.atIndex(index, sourceMap))
} else {
cb('no srcmap associated with the code ' + address)
}
} else {
cb(error)
}
})
}
/**
* backwards compatibility - attribute name will certainly be changed
*/
function srcmapRuntime (contract) {
return contract.srcmapRuntime ? contract.srcmapRuntime : contract['srcmap-runtime']
}
function getSourceMap (address, code, contractsDetails) {
var isCreation = helper.isContractCreation(address)
var byteProp = isCreation ? 'bytecode' : 'runtimeBytecode'
for (var k in contractsDetails) {
if ('0x' + contractsDetails[k][byteProp] === code) {
return isCreation ? contractsDetails[k].srcmap : srcmapRuntime(contractsDetails[k])
}
}
return null
}
module.exports = SourceLocationTracker

@ -12,6 +12,7 @@ var ui = require('../helpers/ui')
var Web3Providers = require('../web3Provider/web3Providers')
var DummyProvider = require('../web3Provider/dummyProvider')
var CodeManager = require('../code/codeManager')
var SourceLocationTracker = require('../code/sourceLocationTracker')
function Ethdebugger () {
util.extend(this, new EventManager())
@ -26,6 +27,7 @@ function Ethdebugger () {
this.switchProvider('DUMMYWEB3')
this.traceManager = new TraceManager()
this.codeManager = new CodeManager(this.traceManager)
this.sourceLocationTracker = new SourceLocationTracker(this.codeManager)
var self = this
this.register('indexChanged', this, function (index) {
@ -72,7 +74,11 @@ Ethdebugger.prototype.switchProvider = function (type) {
}
Ethdebugger.prototype.debug = function (tx) {
if (tx instanceof Object) {
this.txBrowser.load(tx.hash)
} else if (tx instanceof String) {
this.txBrowser.load(tx)
}
}
Ethdebugger.prototype.render = function () {

@ -9,19 +9,16 @@ Web3Providers.prototype.addProvider = function (type, obj) {
if (type === 'INTERNAL') {
var web3 = init.loadWeb3()
this.addWeb3(type, web3)
} else if (type === 'EXTERNAL') {
init.extendWeb3(obj)
this.addWeb3(type, obj)
} else if (type === 'VM') {
} else if (type === 'vm') {
this.addVM(obj)
} else {
init.extendWeb3(obj)
this.addWeb3(type, obj)
}
}
Web3Providers.prototype.get = function (type, cb) {
if (this.modes[type]) {
this.currentMode = type
cb(null, this.modes[type])
} else {
cb('error: this provider has not been setup (' + type + ')', null)

Loading…
Cancel
Save