mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-30 17:11:33 +00:00
Correctly handle more than 5 WASM function parameters when reading state of a LLVM context.
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
// https://llvm.org/docs/StackMaps.html#stackmap-section
|
// https://llvm.org/docs/StackMaps.html#stackmap-section
|
||||||
|
|
||||||
use byteorder::{LittleEndian, ReadBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt};
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, BTreeMap};
|
||||||
use std::io::{self, Cursor};
|
use std::io::{self, Cursor};
|
||||||
use wasmer_runtime_core::state::{
|
use wasmer_runtime_core::state::{
|
||||||
x64::{new_machine_state, X64Register, GPR},
|
x64::{new_machine_state, X64Register, GPR},
|
||||||
@ -128,6 +128,8 @@ impl StackmapEntry {
|
|||||||
let mut regs: Vec<(RegisterIndex, MachineValue)> = vec![];
|
let mut regs: Vec<(RegisterIndex, MachineValue)> = vec![];
|
||||||
let mut stack_constants: HashMap<usize, u64> = HashMap::new();
|
let mut stack_constants: HashMap<usize, u64> = HashMap::new();
|
||||||
|
|
||||||
|
let mut prev_frame_diff: BTreeMap<usize, Option<MachineValue>> = BTreeMap::new();
|
||||||
|
|
||||||
let mut wasm_locals: Vec<WasmAbstractValue> = vec![];
|
let mut wasm_locals: Vec<WasmAbstractValue> = vec![];
|
||||||
let mut wasm_stack: Vec<WasmAbstractValue> = vec![];
|
let mut wasm_stack: Vec<WasmAbstractValue> = vec![];
|
||||||
|
|
||||||
@ -227,7 +229,9 @@ impl StackmapEntry {
|
|||||||
== X64Register::GPR(GPR::RBP)
|
== X64Register::GPR(GPR::RBP)
|
||||||
);
|
);
|
||||||
if loc.offset_or_small_constant >= 0 {
|
if loc.offset_or_small_constant >= 0 {
|
||||||
// FIXME: parameters passed on stack?
|
assert!(loc.offset_or_small_constant >= 16); // (saved_rbp, return_address)
|
||||||
|
assert!(loc.offset_or_small_constant % 8 == 0);
|
||||||
|
prev_frame_diff.insert(((loc.offset_or_small_constant as usize - 16) / 8), Some(mv));
|
||||||
} else {
|
} else {
|
||||||
let stack_offset = ((-loc.offset_or_small_constant) / 4) as usize;
|
let stack_offset = ((-loc.offset_or_small_constant) / 4) as usize;
|
||||||
assert!(
|
assert!(
|
||||||
@ -280,6 +284,7 @@ impl StackmapEntry {
|
|||||||
last: None,
|
last: None,
|
||||||
stack_push: machine_stack_layout,
|
stack_push: machine_stack_layout,
|
||||||
stack_pop: 0,
|
stack_pop: 0,
|
||||||
|
prev_frame_diff,
|
||||||
reg_diff: regs,
|
reg_diff: regs,
|
||||||
wasm_stack_push: wasm_stack,
|
wasm_stack_push: wasm_stack,
|
||||||
wasm_stack_pop: 0,
|
wasm_stack_pop: 0,
|
||||||
|
@ -15,6 +15,8 @@ pub struct MachineState {
|
|||||||
pub stack_values: Vec<MachineValue>,
|
pub stack_values: Vec<MachineValue>,
|
||||||
pub register_values: Vec<MachineValue>,
|
pub register_values: Vec<MachineValue>,
|
||||||
|
|
||||||
|
pub prev_frame: BTreeMap<usize, MachineValue>,
|
||||||
|
|
||||||
pub wasm_stack: Vec<WasmAbstractValue>,
|
pub wasm_stack: Vec<WasmAbstractValue>,
|
||||||
pub wasm_stack_private_depth: usize,
|
pub wasm_stack_private_depth: usize,
|
||||||
|
|
||||||
@ -28,6 +30,8 @@ pub struct MachineStateDiff {
|
|||||||
pub stack_pop: usize,
|
pub stack_pop: usize,
|
||||||
pub reg_diff: Vec<(RegisterIndex, MachineValue)>,
|
pub reg_diff: Vec<(RegisterIndex, MachineValue)>,
|
||||||
|
|
||||||
|
pub prev_frame_diff: BTreeMap<usize, Option<MachineValue>>, // None for removal
|
||||||
|
|
||||||
pub wasm_stack_push: Vec<WasmAbstractValue>,
|
pub wasm_stack_push: Vec<WasmAbstractValue>,
|
||||||
pub wasm_stack_pop: usize,
|
pub wasm_stack_pop: usize,
|
||||||
pub wasm_stack_private_depth: usize, // absolute value; not a diff.
|
pub wasm_stack_private_depth: usize, // absolute value; not a diff.
|
||||||
@ -210,6 +214,22 @@ impl MachineState {
|
|||||||
.filter(|&(_, (a, b))| a != b)
|
.filter(|&(_, (a, b))| a != b)
|
||||||
.map(|(i, (a, _))| (RegisterIndex(i), a.clone()))
|
.map(|(i, (a, _))| (RegisterIndex(i), a.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
let prev_frame_diff: BTreeMap<usize, Option<MachineValue>> = self
|
||||||
|
.prev_frame
|
||||||
|
.iter()
|
||||||
|
.filter(|(k, v)| if let Some(ref old_v) = old.prev_frame.get(k) {
|
||||||
|
v != old_v
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
})
|
||||||
|
.map(|(&k, v)| (k, Some(v.clone())))
|
||||||
|
.chain(
|
||||||
|
old.prev_frame
|
||||||
|
.iter()
|
||||||
|
.filter(|(k, _)| self.prev_frame.get(k).is_none())
|
||||||
|
.map(|(&k, _)| (k, None))
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
let first_diff_wasm_stack_depth: usize = self
|
let first_diff_wasm_stack_depth: usize = self
|
||||||
.wasm_stack
|
.wasm_stack
|
||||||
.iter()
|
.iter()
|
||||||
@ -222,7 +242,9 @@ impl MachineState {
|
|||||||
last: None,
|
last: None,
|
||||||
stack_push: self.stack_values[first_diff_stack_depth..].to_vec(),
|
stack_push: self.stack_values[first_diff_stack_depth..].to_vec(),
|
||||||
stack_pop: old.stack_values.len() - first_diff_stack_depth,
|
stack_pop: old.stack_values.len() - first_diff_stack_depth,
|
||||||
reg_diff: reg_diff,
|
reg_diff,
|
||||||
|
|
||||||
|
prev_frame_diff,
|
||||||
|
|
||||||
wasm_stack_push: self.wasm_stack[first_diff_wasm_stack_depth..].to_vec(),
|
wasm_stack_push: self.wasm_stack[first_diff_wasm_stack_depth..].to_vec(),
|
||||||
wasm_stack_pop: old.wasm_stack.len() - first_diff_wasm_stack_depth,
|
wasm_stack_pop: old.wasm_stack.len() - first_diff_wasm_stack_depth,
|
||||||
@ -255,6 +277,13 @@ impl MachineStateDiff {
|
|||||||
for &(index, ref v) in &x.reg_diff {
|
for &(index, ref v) in &x.reg_diff {
|
||||||
state.register_values[index.0] = v.clone();
|
state.register_values[index.0] = v.clone();
|
||||||
}
|
}
|
||||||
|
for (index, ref v) in &x.prev_frame_diff {
|
||||||
|
if let Some(ref x) = v {
|
||||||
|
state.prev_frame.insert(*index, x.clone());
|
||||||
|
} else {
|
||||||
|
state.prev_frame.remove(index).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
for _ in 0..x.wasm_stack_pop {
|
for _ in 0..x.wasm_stack_pop {
|
||||||
state.wasm_stack.pop().unwrap();
|
state.wasm_stack.pop().unwrap();
|
||||||
}
|
}
|
||||||
@ -393,6 +422,7 @@ pub mod x64 {
|
|||||||
MachineState {
|
MachineState {
|
||||||
stack_values: vec![],
|
stack_values: vec![],
|
||||||
register_values: vec![MachineValue::Undefined; 16 + 8],
|
register_values: vec![MachineValue::Undefined; 16 + 8],
|
||||||
|
prev_frame: BTreeMap::new(),
|
||||||
wasm_stack: vec![],
|
wasm_stack: vec![],
|
||||||
wasm_stack_private_depth: 0,
|
wasm_stack_private_depth: 0,
|
||||||
wasm_inst_offset: ::std::usize::MAX,
|
wasm_inst_offset: ::std::usize::MAX,
|
||||||
@ -938,7 +968,20 @@ pub mod x64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stack = stack.offset(1); // RBP
|
|
||||||
|
for (offset, v) in state.prev_frame.iter() {
|
||||||
|
let offset = (*offset + 2) as isize; // (saved_rbp, return_address)
|
||||||
|
match *v {
|
||||||
|
MachineValue::WasmStack(idx) => {
|
||||||
|
wasm_stack[idx] = Some(*stack.offset(offset));
|
||||||
|
}
|
||||||
|
MachineValue::WasmLocal(idx) => {
|
||||||
|
wasm_locals[idx] = Some(*stack.offset(offset));
|
||||||
|
}
|
||||||
|
_ => unreachable!("values in prev frame can only be stack/local")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack = stack.offset(1); // saved_rbp
|
||||||
|
|
||||||
wasm_stack.truncate(
|
wasm_stack.truncate(
|
||||||
wasm_stack
|
wasm_stack
|
||||||
|
Reference in New Issue
Block a user