Skip to content

Commit

Permalink
Merge pull request #1 from sentioxyz/dev/pc/add_call_trce
Browse files Browse the repository at this point in the history
Add a multiple function test and call trace struct
  • Loading branch information
Poytr1 authored Sep 14, 2023
2 parents a06d270 + ad4d64d commit e88f881
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ mod mutated_accounts_tests;
mod nested_loop_tests;
mod regression_tests;
mod return_value_tests;
mod multi_func_tests;
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright (c) The Diem Core Contributors
// Copyright (c) The Move Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::compiler::{as_module, compile_units};
use move_binary_format::errors::VMResult;
use move_core_types::{
account_address::AccountAddress,
identifier::Identifier,
language_storage::{ModuleId, TypeTag},
value::{MoveTypeLayout, MoveValue},
};
use move_vm_runtime::{move_vm::MoveVM, session::SerializedReturnValues};
use move_vm_test_utils::InMemoryStorage;
use move_vm_types::gas::UnmeteredGasMeter;

const TEST_ADDR: AccountAddress = AccountAddress::new([42; AccountAddress::LENGTH]);

fn run(
ty_args: Vec<TypeTag>,
args: Vec<MoveValue>,
) -> VMResult<Vec<Vec<u8>>> {
let code = r#"
module {{ADDR}}::M {
public fun foo(v1: u64): u64 {
bar(v1)
}
public fun bar(v1: u64): u64 {
1 + v1
}
}
"#;
let code = code.replace("{{ADDR}}", &format!("0x{}", TEST_ADDR.to_hex()));

let mut units = compile_units(&code).unwrap();
let m = as_module(units.pop().unwrap());
let mut blob = vec![];
m.serialize(&mut blob).unwrap();

let mut storage = InMemoryStorage::new();
let module_id = ModuleId::new(TEST_ADDR, Identifier::new("M").unwrap());
storage.publish_or_overwrite_module(module_id.clone(), blob);

let vm = MoveVM::new(vec![]).unwrap();
let mut sess = vm.new_session(&storage);

let fun_name = Identifier::new("foo").unwrap();

let args: Vec<_> = args
.into_iter()
.map(|val| val.simple_serialize().unwrap())
.collect();

let SerializedReturnValues {
return_values,
mutable_reference_outputs: _,
} = sess.execute_function_bypass_visibility(
&module_id,
&fun_name,
ty_args,
args,
&mut UnmeteredGasMeter,
)?;

Ok(return_values
.into_iter()
.map(|(bytes, _layout)| bytes)
.collect())
}

fn expect_success(
ty_args: Vec<TypeTag>,
args: Vec<MoveValue>,
expected_layouts: &[MoveTypeLayout],
) {
let return_vals = run(ty_args, args).unwrap();
assert!(return_vals.len() == expected_layouts.len());

for (blob, layout) in return_vals.iter().zip(expected_layouts.iter()) {
MoveValue::simple_deserialize(blob, layout).unwrap();
}
}

#[test]
fn multi_func() {
expect_success(vec![], vec![MoveValue::U64(6)], &[
MoveTypeLayout::U64,
])
}
49 changes: 48 additions & 1 deletion third_party/move/move-vm/runtime/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ pub(crate) struct Interpreter {
call_stack: CallStack,
/// Whether to perform a paranoid type safety checks at runtime.
paranoid_type_checks: bool,

call_traces: CallTraces,
}

struct TypeWithLoader<'a, 'b> {
Expand Down Expand Up @@ -97,6 +99,7 @@ impl Interpreter {
operand_stack: Stack::new(),
call_stack: CallStack::new(),
paranoid_type_checks: loader.vm_config().paranoid_type_checks,
call_traces: CallTraces::new(),
}
.execute_main(
loader, data_store, gas_meter, extensions, function, ty_args, args,
Expand All @@ -120,21 +123,35 @@ impl Interpreter {
args: Vec<Value>,
) -> VMResult<Vec<Value>> {
let mut locals = Locals::new(function.local_count());
let mut args_1 = vec![];
for (i, value) in args.into_iter().enumerate() {
locals
.store_loc(
i,
value,
value.copy_value().unwrap(),
loader
.vm_config()
.enable_invariant_violation_check_in_swap_loc,
)
.map_err(|e| self.set_location(e))?;
args_1.push(value);
}

let mut current_frame = self
.make_new_frame(loader, function, ty_args, locals)
.map_err(|err| self.set_location(err))?;
self.call_traces.push(CallTrace {
pc: current_frame.pc,
module_id: "".to_string(),
func_name: current_frame.function.name().to_string(),
inputs: args_1,
outputs: vec![],
type_args: current_frame.ty_args.clone(),
}).map_err(|_e| {
let err = PartialVMError::new(StatusCode::ABORTED);
let err = set_err_info!(current_frame, err);
self.maybe_core_dump(err, &current_frame)
})?;
loop {
let resolver = current_frame.resolver(loader);
let exit_code =
Expand Down Expand Up @@ -1000,6 +1017,27 @@ impl CallStack {
}
}

struct CallTraces(Vec<CallTrace>);

impl CallTraces {
fn new() -> Self {
CallTraces(vec![])
}

fn push(&mut self, trace: CallTrace) -> Result<(), CallTrace> {
if self.0.len() < CALL_STACK_SIZE_LIMIT {
self.0.push(trace);
Ok(())
} else {
Err(trace)
}
}

fn pop(&mut self) -> Option<CallTrace> {
self.0.pop()
}
}

fn check_depth_of_type(resolver: &Resolver, ty: &Type) -> PartialVMResult<()> {
// Start at 1 since we always call this right before we add a new node to the value's depth.
let max_depth = match resolver.loader().vm_config().max_value_nest_depth {
Expand Down Expand Up @@ -1096,6 +1134,15 @@ struct Frame {
local_tys: Vec<Type>,
}

struct CallTrace {
pc: u16,
module_id: String,
func_name: String,
inputs: Vec<Value>,
outputs: Vec<Value>,
type_args: Vec<Type>,
}

/// An `ExitCode` from `execute_code_unit`.
#[derive(Debug)]
enum ExitCode {
Expand Down

0 comments on commit e88f881

Please sign in to comment.