Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
54581749
Commit
54581749
authored
Nov 07, 2016
by
chriseth
Committed by
GitHub
Nov 07, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #132 from ethereum/functionFromPC
retrieve function from PC
parents
0fdf5d6a
51a34de0
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
198 additions
and
54 deletions
+198
-54
package.json
package.json
+2
-1
codeManager.js
src/code/codeManager.js
+80
-23
sourceMappingDecoder.js
src/util/sourceMappingDecoder.js
+84
-30
sourceMappingDecoder.js
test/sourceMappingDecoder.js
+31
-0
tests.js
test/tests.js
+1
-0
No files found.
package.json
View file @
54581749
...
...
@@ -29,7 +29,8 @@
"
tape
"
:
"^4.6.0"
,
"
web3
"
:
"^0.15.3"
,
"
yo-yo
"
:
"^1.2.1"
,
"
yo-yoify
"
:
"^3.1.0"
"
yo-yoify
"
:
"^3.1.0"
,
"
solc
"
:
"^0.4.3"
},
"scripts"
:
{
"start_node"
:
"./runNode.sh"
,
...
...
src/code/codeManager.js
View file @
54581749
...
...
@@ -2,13 +2,12 @@
var
traceHelper
=
require
(
'../helpers/traceHelper'
)
var
codeResolver
=
require
(
'./codeResolver'
)
var
EventManager
=
require
(
'../lib/eventManager'
)
var
SourceMappingDecoder
=
require
(
'../util/sourceMappingDecoder'
)
/*
resolve contract code referenced by vmtrace in order to be used by asm listview.
events:
- indexChanged: triggered when an item is selected
- codeChanged: triggered when an item (in a different context) is selected
- loadingCode: triggerred when loading new code
- changed: triggered when an item is selected
- resolvingStep: when CodeManager resolves code/selected instruction of a new step
*/
...
...
@@ -19,34 +18,35 @@ function CodeManager (_traceManager) {
this
.
codeResolver
=
codeResolver
}
/**
* resolve the code of the given @arg stepIndex and trigger appropriate event
*
* @param {String} stepIndex - vm trace step
* @param {Object} tx - transaction (given by web3)
*/
CodeManager
.
prototype
.
resolveStep
=
function
(
stepIndex
,
tx
)
{
if
(
stepIndex
<
0
)
return
this
.
event
.
trigger
(
'resolvingStep'
)
var
self
=
this
if
(
stepIndex
===
0
)
{
self
.
retrieveCodeAndTrigger
(
tx
.
to
,
stepIndex
,
tx
)
retrieveCodeAndTrigger
(
self
,
tx
.
to
,
stepIndex
,
tx
)
}
else
{
this
.
traceManager
.
getCurrentCalledAddressAt
(
stepIndex
,
function
(
error
,
address
)
{
if
(
error
)
{
console
.
log
(
error
)
}
else
{
self
.
retrieveCodeAndTrigger
(
address
,
stepIndex
,
tx
)
retrieveCodeAndTrigger
(
self
,
address
,
stepIndex
,
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
)
}
})
}
/**
* Retrieve the code located at the given @arg address
*
* @param {String} address - address of the contract to get the code from
* @param {Function} cb - callback function, return the bytecode
*/
CodeManager
.
prototype
.
getCode
=
function
(
address
,
cb
)
{
if
(
traceHelper
.
isContractCreation
(
address
))
{
var
codes
=
codeResolver
.
getExecutingCodeFromCache
(
address
)
...
...
@@ -67,27 +67,84 @@ CodeManager.prototype.getCode = function (address, cb) {
}
}
CodeManager
.
prototype
.
retrieveIndexAndTrigger
=
function
(
address
,
step
,
code
)
{
/**
* Retrieve the called function for the current vm step for the given @arg address
*
* @param {String} stepIndex - vm trace step
* @param {String} sourceMap - source map given byt the compilation result
* @param {Object} ast - ast given by the compilation result
* @return {Object} return the ast node of the function
*/
CodeManager
.
prototype
.
getFunctionFromStep
=
function
(
stepIndex
,
sourceMap
,
ast
)
{
var
self
=
this
this
.
getInstructionIndex
(
address
,
step
,
function
(
error
,
result
)
{
if
(
!
error
)
{
self
.
event
.
trigger
(
'changed'
,
[
code
,
address
,
result
])
}
else
{
this
.
traceManager
.
getCurrentCalledAddressAt
(
stepIndex
,
function
(
error
,
address
)
{
if
(
error
)
{
console
.
log
(
error
)
return
{
error
:
'Cannot retrieve current address for '
+
stepIndex
}
}
else
{
self
.
traceManager
.
getCurrentPC
(
stepIndex
,
function
(
error
,
pc
)
{
if
(
error
)
{
console
.
log
(
error
)
return
{
error
:
'Cannot retrieve current PC for '
+
stepIndex
}
}
else
{
return
self
.
getFunctionFromPC
(
address
,
pc
,
sourceMap
,
ast
)
}
})
}
})
}
/**
* Retrieve the instruction index of the given @arg step
*
* @param {String} address - address of the current context
* @param {String} step - vm trace step
* @param {Function} callback - instruction index
*/
CodeManager
.
prototype
.
getInstructionIndex
=
function
(
address
,
step
,
callback
)
{
this
.
traceManager
.
getCurrentPC
(
step
,
function
(
error
,
instIndex
)
{
this
.
traceManager
.
getCurrentPC
(
step
,
function
(
error
,
pc
)
{
if
(
error
)
{
console
.
log
(
error
)
callback
(
'Cannot retrieve current PC for '
+
step
,
null
)
}
else
{
var
itemIndex
=
codeResolver
.
getInstructionIndex
(
address
,
instIndex
)
var
itemIndex
=
codeResolver
.
getInstructionIndex
(
address
,
pc
)
callback
(
null
,
itemIndex
)
}
})
}
/**
* Retrieve the called function for the given @arg pc and @arg address
*
* @param {String} address - address of the current context (used to resolve instruction index)
* @param {String} pc - pc that point to the instruction index
* @param {String} sourceMap - source map given byt the compilation result
* @param {Object} ast - ast given by the compilation result
* @return {Object} return the ast node of the function
*/
CodeManager
.
prototype
.
getFunctionFromPC
=
function
(
address
,
pc
,
sourceMap
,
ast
)
{
var
instIndex
=
codeResolver
.
getInstructionIndex
(
address
,
pc
)
return
SourceMappingDecoder
.
findNodeAtInstructionIndex
(
'FunctionDefinition'
,
instIndex
,
sourceMap
,
ast
)
}
function
retrieveCodeAndTrigger
(
codeMananger
,
address
,
stepIndex
,
tx
)
{
codeMananger
.
getCode
(
address
,
function
(
error
,
result
)
{
if
(
!
error
)
{
retrieveIndexAndTrigger
(
codeMananger
,
address
,
stepIndex
,
result
.
instructions
)
}
else
{
console
.
log
(
error
)
}
})
}
function
retrieveIndexAndTrigger
(
codeMananger
,
address
,
step
,
code
)
{
codeMananger
.
getInstructionIndex
(
address
,
step
,
function
(
error
,
result
)
{
if
(
!
error
)
{
codeMananger
.
event
.
trigger
(
'changed'
,
[
code
,
address
,
result
])
}
else
{
console
.
log
(
error
)
}
})
}
module
.
exports
=
CodeManager
src/util/sourceMappingDecoder.js
View file @
54581749
'use strict'
var
util
=
require
(
'../helpers/util'
)
var
AstWalker
=
require
(
'./astWalker'
)
/**
* Decompress the source mapping given by solc-bin.js
...
...
@@ -15,36 +16,7 @@ function SourceMappingDecoder () {
* @param {String} mapping - compressed source mapping given by solc-bin
* @return {Object} returns the decompressed source mapping for the given index {start, length, file, jump}
*/
SourceMappingDecoder
.
prototype
.
atIndex
=
function
(
index
,
mapping
)
{
var
ret
=
{}
var
map
=
mapping
.
split
(
';'
)
if
(
index
>=
map
.
length
)
{
index
=
map
.
length
-
1
}
for
(
var
k
=
index
;
k
>=
0
;
k
--
)
{
var
current
=
map
[
k
]
if
(
!
current
.
length
)
{
continue
}
current
=
current
.
split
(
':'
)
if
(
ret
.
start
===
undefined
&&
current
[
0
]
&&
current
[
0
].
length
)
{
ret
.
start
=
parseInt
(
current
[
0
])
}
if
(
ret
.
length
===
undefined
&&
current
[
1
]
&&
current
[
1
].
length
)
{
ret
.
length
=
parseInt
(
current
[
1
])
}
if
(
ret
.
file
===
undefined
&&
current
[
2
]
&&
current
[
2
].
length
)
{
ret
.
file
=
parseInt
(
current
[
2
])
}
if
(
ret
.
jump
===
undefined
&&
current
[
3
]
&&
current
[
3
].
length
)
{
ret
.
jump
=
current
[
3
]
}
if
(
ret
.
start
!==
undefined
&&
ret
.
length
!==
undefined
&&
ret
.
file
!==
undefined
&&
ret
.
jump
!==
undefined
)
{
break
}
}
return
ret
}
SourceMappingDecoder
.
prototype
.
atIndex
=
atIndex
/**
* Decode the source mapping for the given compressed mapping
...
...
@@ -103,6 +75,16 @@ SourceMappingDecoder.prototype.convertOffsetToLineColumn = function (sourceLocat
}
}
/**
* Retrieve the first @arg astNodeType that include the source map at arg instIndex
*
* @param {String} astNodeType - node type that include the source map instIndex
* @param {String} instIndex - instruction index used to retrieve the source map
* @param {String} sourceMap - source map given by the compilation result
* @param {Object} ast - ast given by the compilation result
*/
SourceMappingDecoder
.
prototype
.
findNodeAtInstructionIndex
=
findNodeAtInstructionIndex
function
convertFromCharPosition
(
pos
,
lineBreakPositions
)
{
var
line
=
util
.
findLowerBound
(
pos
,
lineBreakPositions
)
if
(
lineBreakPositions
[
line
]
!==
pos
)
{
...
...
@@ -116,4 +98,76 @@ function convertFromCharPosition (pos, lineBreakPositions) {
}
}
function
sourceLocationFromAstNode
(
astNode
)
{
if
(
astNode
.
src
)
{
var
split
=
astNode
.
src
.
split
(
':'
)
return
{
start
:
parseInt
(
split
[
0
]),
length
:
parseInt
(
split
[
1
]),
file
:
parseInt
(
split
[
2
])
}
}
return
null
}
function
findNodeAtInstructionIndex
(
astNodeType
,
instIndex
,
sourceMap
,
ast
)
{
var
sourceLocation
=
atIndex
(
instIndex
,
sourceMap
)
return
findNodeAtSourceLocation
(
astNodeType
,
sourceLocation
,
ast
)
}
function
findNodeAtSourceLocation
(
astNodeType
,
sourceLocation
,
ast
)
{
var
astWalker
=
new
AstWalker
()
var
callback
=
{}
var
found
=
null
callback
[
'*'
]
=
function
(
node
)
{
var
nodeLocation
=
sourceLocationFromAstNode
(
node
)
if
(
!
nodeLocation
)
{
return
true
}
if
(
nodeLocation
.
start
<=
sourceLocation
.
start
&&
nodeLocation
.
start
+
nodeLocation
.
length
>=
sourceLocation
.
start
+
sourceLocation
.
length
)
{
if
(
astNodeType
===
node
.
name
)
{
found
=
node
return
false
}
else
{
return
true
}
}
else
{
return
false
}
}
astWalker
.
walk
(
ast
.
AST
,
callback
)
return
found
}
function
atIndex
(
index
,
mapping
)
{
var
ret
=
{}
var
map
=
mapping
.
split
(
';'
)
if
(
index
>=
map
.
length
)
{
index
=
map
.
length
-
1
}
for
(
var
k
=
index
;
k
>=
0
;
k
--
)
{
var
current
=
map
[
k
]
if
(
!
current
.
length
)
{
continue
}
current
=
current
.
split
(
':'
)
if
(
ret
.
start
===
undefined
&&
current
[
0
]
&&
current
[
0
].
length
)
{
ret
.
start
=
parseInt
(
current
[
0
])
}
if
(
ret
.
length
===
undefined
&&
current
[
1
]
&&
current
[
1
].
length
)
{
ret
.
length
=
parseInt
(
current
[
1
])
}
if
(
ret
.
file
===
undefined
&&
current
[
2
]
&&
current
[
2
].
length
)
{
ret
.
file
=
parseInt
(
current
[
2
])
}
if
(
ret
.
jump
===
undefined
&&
current
[
3
]
&&
current
[
3
].
length
)
{
ret
.
jump
=
current
[
3
]
}
if
(
ret
.
start
!==
undefined
&&
ret
.
length
!==
undefined
&&
ret
.
file
!==
undefined
&&
ret
.
jump
!==
undefined
)
{
break
}
}
return
ret
}
module
.
exports
=
SourceMappingDecoder
test/sourceMappingDecoder.js
0 → 100644
View file @
54581749
'use strict'
var
tape
=
require
(
'tape'
)
var
SourceMappingDecoder
=
require
(
'../src/util/sourceMappingDecoder'
)
var
compiler
=
require
(
'solc'
)
tape
(
'SourceMappingDecoder'
,
function
(
t
)
{
t
.
test
(
'SourceMappingDecoder.findNodeAtInstructionIndex'
,
function
(
st
)
{
var
output
=
compiler
.
compile
(
contracts
,
0
)
var
sourceMappingDecoder
=
new
SourceMappingDecoder
()
var
node
=
sourceMappingDecoder
.
findNodeAtInstructionIndex
(
'FunctionDefinition'
,
2
,
output
.
contracts
[
'test'
].
srcmapRuntime
,
output
.
sources
[
''
])
st
.
equal
(
node
,
null
)
node
=
sourceMappingDecoder
.
findNodeAtInstructionIndex
(
'FunctionDefinition'
,
37
,
output
.
contracts
[
'test'
].
srcmapRuntime
,
output
.
sources
[
''
])
st
.
notEqual
(
node
,
null
)
if
(
node
)
{
st
.
equal
(
node
.
attributes
.
name
,
'f1'
)
}
st
.
end
()
})
})
var
contracts
=
`contract test {
function f1() returns (uint) {
uint t = 4;
return t;
}
function f2() {
}
}
`
test/tests.js
View file @
54581749
...
...
@@ -6,3 +6,4 @@ require('./util.js')
require
(
'./astwalker.js'
)
require
(
'./disassembler.js'
)
require
(
'./eventManager.js'
)
require
(
'./sourceMappingDecoder.js'
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment