-
Notifications
You must be signed in to change notification settings - Fork 314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracing API #32
Tracing API #32
Changes from all commits
91065ca
2c7ad06
d2ac75f
9e31e93
59dc54e
17d95f2
e93da0e
9bda457
a3cb335
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,7 @@ extern "C" { | |
enum | ||
{ | ||
/** The EVMC ABI version number of the interface declared in this file. */ | ||
EVMC_ABI_VERSION = 2 | ||
EVMC_ABI_VERSION = 3 | ||
}; | ||
|
||
/** | ||
|
@@ -675,18 +675,18 @@ enum evmc_revision | |
|
||
|
||
/** | ||
* Generates and executes machine code for given EVM bytecode. | ||
* | ||
* All the fun is here. This function actually does something useful. | ||
* | ||
* @param instance A EVM instance. | ||
* @param context The pointer to the Host execution context to be passed | ||
* to callback functions. @see ::evmc_context. | ||
* @param rev Requested EVM specification revision. | ||
* @param msg Call parameters. @see ::evmc_message. | ||
* @param code Reference to the bytecode to be executed. | ||
* @param code_size The length of the bytecode. | ||
* @return All execution results. | ||
* Executes the given EVM bytecode using the input in the message | ||
* | ||
* This function MAY be invoked multiple times for a single EVM instance. | ||
* | ||
* @param instance The EVM instance. | ||
* @param context The pointer to the Client execution context to be passed | ||
* to the callback functions. @see ::evmc_context. | ||
* @param rev Requested EVM specification revision. | ||
* @param msg Call parameters. @see ::evmc_message. | ||
* @param code Reference to the bytecode to be executed. | ||
* @param code_size The length of the bytecode. | ||
* @return All execution results. | ||
*/ | ||
typedef struct evmc_result (*evmc_execute_fn)(struct evmc_instance* instance, | ||
struct evmc_context* context, | ||
|
@@ -696,6 +696,77 @@ typedef struct evmc_result (*evmc_execute_fn)(struct evmc_instance* instance, | |
size_t code_size); | ||
|
||
|
||
/** The opaque type representing a Client-side tracer object. */ | ||
struct evmc_tracer_context; | ||
|
||
/** | ||
* The callback to trace instructions execution in an EVM. | ||
* | ||
* This function informs the Client what instruction has been executed in the EVM implementation | ||
* and what are the results of executing this particular instruction. | ||
* The message level information (like call depth, destination address, etc.) are not provided here. | ||
* This piece of information can be acquired by inspecting messages being sent to the EVM in | ||
* ::evmc_execute_fn and the results of the messages execution. | ||
* | ||
* @param context The pointer to the Client-side tracing context. This allows to | ||
* implement the tracer in OOP manner. | ||
* @param code_offset The current instruction position in the code. | ||
* @param status_code The status code of the instruction execution. | ||
* @param gas_left The amount of the gas left after the instruction execution. | ||
* @param stack_num_items The current EVM stack height after the instruction execution. | ||
* @param pushed_stack_item The top EVM stack item pushed as the result of the instruction | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So based on these two the client needs to apply the stack changes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any comments? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the tracer want to know what's on stack it has to track the changes. This is even more complicated when you consider SWAP and DUP instructions - the tracer would have to reapply SWAP and DUP semantics. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure there aren't ever going to be instructions pushing more than one item? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In theory we have them now in form of DUP and SWAP. |
||
* execution. This value is null when the instruction does not push | ||
* anything to the stack. | ||
* @param memory_size The size of the EVM memory after the instruction execution. | ||
* @param changed_memory_offset The offset in number of bytes of the beginning of the memory area | ||
* modified as the result of the instruction execution. | ||
* The Client MAY use this information together with | ||
* @p changed_memory_size and @p changed_memory to incrementally | ||
* update the copy of the full VM's memory. | ||
* @param changed_memory_size The size of the memory area modified as the result of | ||
* the instruction execution. | ||
* @param changed_memory The pointer to the memory area modified as the result of | ||
* the instruction execution. | ||
* The Client MAY access the pointed memory area | ||
* (limited by the @p changed_memory_size) only during the current | ||
* execution of the evmc_trace_callback(). | ||
* The pointer MUST NOT be stored by the Client. | ||
* The Client MUST NOT assume that | ||
* `changed_memory - changed_memory_offset` is a valid base pointer | ||
* of the VM memory. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm glad we discussed these on Gitter, much more cleaner now. |
||
*/ | ||
typedef void (*evmc_trace_callback)(struct evmc_tracer_context* context, | ||
size_t code_offset, | ||
enum evmc_status_code status_code, | ||
int64_t gas_left, | ||
size_t stack_num_items, | ||
const struct evmc_uint256be* pushed_stack_item, | ||
size_t memory_size, | ||
size_t changed_memory_offset, | ||
size_t changed_memory_size, | ||
const uint8_t* changed_memory); | ||
|
||
/** | ||
* Sets the EVM instruction tracer. | ||
* | ||
* When the tracer is set in the EVM instance, the EVM SHOULD call back the tracer with information | ||
* about instructions execution in the EVM. | ||
* @see ::evmc_trace_callback. | ||
* | ||
* This will overwrite the previous settings (the callback and the context). | ||
* | ||
* @param instance The EVM instance. | ||
* @param callback The tracer callback function. This argument MAY be NULL to disable previously | ||
* set tracer. | ||
* @param context The Client-side tracer context. This argument MAY be NULL in case the tracer | ||
* does not require any context. This argument MUST be NULL if the callback | ||
* argument is NULL. | ||
*/ | ||
typedef void (*evmc_set_tracer_fn)(struct evmc_instance* instance, | ||
evmc_trace_callback callback, | ||
struct evmc_tracer_context* context); | ||
|
||
|
||
/** | ||
* The EVM instance. | ||
* | ||
|
@@ -731,6 +802,13 @@ struct evmc_instance | |
/** Pointer to function executing a code by the EVM instance. */ | ||
evmc_execute_fn execute; | ||
|
||
/** | ||
* Optional pointer to function setting the EVM instruction tracer. | ||
* | ||
* If the EVM does not support this feature the pointer can be NULL. | ||
*/ | ||
evmc_set_tracer_fn set_tracer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be unset after its being set? I don't fully remember (and seemingly our documentation isn't clear enough): can an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. Answered in the latest commit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That commit looks good. |
||
|
||
/** | ||
* Optional pointer to function modifying VM's options. | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be useful to have another callback to allow the EVM to log text back to the client.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of a separate callback, actually it could just be added as an additional parameter to
evmc_trace_callback
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, EVM can just do this via stderr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The C++
std::cerr
works. We could add a logger method to capture VM logs nicely on the Host side. But that is different feature and should be done independently.