To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

Commit 071cf7e1 authored by qinsoon's avatar qinsoon
Browse files

[wip] going to work on catch block (exception arg)

parent 214d799f
...@@ -661,23 +661,23 @@ impl CodeGenerator for ASMCodeGen { ...@@ -661,23 +661,23 @@ impl CodeGenerator for ASMCodeGen {
self.add_asm_symbolic(directive_globl(func_symbol.clone())); self.add_asm_symbolic(directive_globl(func_symbol.clone()));
self.add_asm_symbolic(format!("{}:", func_symbol.clone())); self.add_asm_symbolic(format!("{}:", func_symbol.clone()));
ValueLocation::Relocatable(RegGroup::GPR, func_symbol) ValueLocation::Relocatable(RegGroup::GPR, func_name)
} }
fn finish_code(&mut self, func_name: MuName) -> (Box<MachineCode + Sync + Send>, ValueLocation) { fn finish_code(&mut self, func_name: MuName) -> (Box<MachineCode + Sync + Send>, ValueLocation) {
let func_end_symbol = { let func_end = {
let mut symbol = symbol(func_name.clone()); let mut symbol = func_name.clone();
symbol.push_str("_end"); symbol.push_str("_end");
symbol symbol
}; };
self.add_asm_symbolic(directive_globl(func_end_symbol.clone())); self.add_asm_symbolic(directive_globl(symbol(func_end.clone())));
self.add_asm_symbolic(format!("{}:", func_end_symbol.clone())); self.add_asm_symbolic(format!("{}:", symbol(func_end.clone())));
self.control_flow_analysis(); self.control_flow_analysis();
( (
self.cur.take().unwrap(), self.cur.take().unwrap(),
ValueLocation::Relocatable(RegGroup::GPR, func_end_symbol) ValueLocation::Relocatable(RegGroup::GPR, func_end)
) )
} }
...@@ -710,13 +710,13 @@ impl CodeGenerator for ASMCodeGen { ...@@ -710,13 +710,13 @@ impl CodeGenerator for ASMCodeGen {
} }
fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation { fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation {
let block_symbol = symbol(self.asm_block_label(block_name.clone())); let block = self.asm_block_label(block_name.clone());
self.add_asm_symbolic(directive_globl(block_symbol.clone())); self.add_asm_symbolic(directive_globl(symbol(block.clone())));
self.add_asm_symbolic(format!("{}:", block_symbol.clone())); self.add_asm_symbolic(format!("{}:", symbol(block.clone())));
self.start_block(block_name); self.start_block(block_name);
ValueLocation::Relocatable(RegGroup::GPR, block_symbol) ValueLocation::Relocatable(RegGroup::GPR, block)
} }
fn end_block(&mut self, block_name: MuName) { fn end_block(&mut self, block_name: MuName) {
...@@ -1155,14 +1155,14 @@ impl CodeGenerator for ASMCodeGen { ...@@ -1155,14 +1155,14 @@ impl CodeGenerator for ASMCodeGen {
fn emit_call_near_rel32(&mut self, callsite: String, func: MuName) -> ValueLocation { fn emit_call_near_rel32(&mut self, callsite: String, func: MuName) -> ValueLocation {
trace!("emit: call {}", func); trace!("emit: call {}", func);
let callsite_symbol = symbol(callsite); let callsite_symbol = symbol(callsite.clone());
self.add_asm_symbolic(directive_globl(callsite_symbol.clone())); self.add_asm_symbolic(directive_globl(callsite_symbol.clone()));
self.add_asm_symbolic(format!("{}:", callsite_symbol.clone())); self.add_asm_symbolic(format!("{}:", callsite_symbol.clone()));
let asm = format!("call {}", symbol(func)); let asm = format!("call {}", symbol(func));
self.add_asm_call(asm); self.add_asm_call(asm);
ValueLocation::Relocatable(RegGroup::GPR, callsite_symbol) ValueLocation::Relocatable(RegGroup::GPR, callsite)
} }
fn emit_call_near_r64(&mut self, callsite: String, func: &P<Value>) -> ValueLocation { fn emit_call_near_r64(&mut self, callsite: String, func: &P<Value>) -> ValueLocation {
......
...@@ -3,6 +3,7 @@ use ast::ptr::*; ...@@ -3,6 +3,7 @@ use ast::ptr::*;
use ast::types::*; use ast::types::*;
use runtime::ValueLocation; use runtime::ValueLocation;
use std::fmt;
use std::collections::HashMap; use std::collections::HashMap;
use utils::POINTER_SIZE; use utils::POINTER_SIZE;
use vm::VM; use vm::VM;
...@@ -28,6 +29,21 @@ pub struct Frame { ...@@ -28,6 +29,21 @@ pub struct Frame {
pub exception_callsites: HashMap<ValueLocation, ValueLocation> pub exception_callsites: HashMap<ValueLocation, ValueLocation>
} }
impl fmt::Display for Frame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "Frame for FuncVer {} {{", self.func_ver_id).unwrap();
writeln!(f, " allocated slots:").unwrap();
for slot in self.allocated.values() {
writeln!(f, " {}", slot).unwrap();
}
writeln!(f, " exception callsites:").unwrap();
for (callsite, dest) in self.exception_callsites.iter() {
writeln!(f, " callsite: {} -> {}", callsite, dest).unwrap()
}
writeln!(f, "}}")
}
}
impl Frame { impl Frame {
pub fn new(func_ver_id: MuID) -> Frame { pub fn new(func_ver_id: MuID) -> Frame {
Frame { Frame {
...@@ -49,6 +65,7 @@ impl Frame { ...@@ -49,6 +65,7 @@ impl Frame {
} }
pub fn add_exception_callsite(&mut self, callsite: ValueLocation, dest: ValueLocation) { pub fn add_exception_callsite(&mut self, callsite: ValueLocation, dest: ValueLocation) {
trace!("add exception callsite: {} to dest {}", callsite, dest);
self.exception_callsites.insert(callsite, dest); self.exception_callsites.insert(callsite, dest);
} }
...@@ -72,6 +89,12 @@ pub struct FrameSlot { ...@@ -72,6 +89,12 @@ pub struct FrameSlot {
pub value: P<Value> pub value: P<Value>
} }
impl fmt::Display for FrameSlot {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}(RBP): {}", self.offset, self.value)
}
}
impl FrameSlot { impl FrameSlot {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub fn make_memory_op(&self, ty: P<MuType>, vm: &VM) -> P<Value> { pub fn make_memory_op(&self, ty: P<MuType>, vm: &VM) -> P<Value> {
......
...@@ -9,6 +9,7 @@ use runtime::thread; ...@@ -9,6 +9,7 @@ use runtime::thread;
use std::sync::RwLock; use std::sync::RwLock;
use std::sync::RwLockReadGuard; use std::sync::RwLockReadGuard;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt;
#[no_mangle] #[no_mangle]
pub extern fn muentry_throw_exception(exception_obj: Address) { pub extern fn muentry_throw_exception(exception_obj: Address) {
...@@ -22,11 +23,14 @@ pub extern fn muentry_throw_exception(exception_obj: Address) { ...@@ -22,11 +23,14 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
// rbp of current frame (mu_throw_exception(), Rust frame) // rbp of current frame (mu_throw_exception(), Rust frame)
let rust_frame_rbp = unsafe {thread::get_current_frame_rbp()}; let rust_frame_rbp = unsafe {thread::get_current_frame_rbp()};
trace!("current frame RBP: 0x{:x}", rust_frame_rbp);
let rust_frame_return_addr = unsafe {rust_frame_rbp.plus(POINTER_SIZE).load::<Address>()}; let rust_frame_return_addr = unsafe {rust_frame_rbp.plus(POINTER_SIZE).load::<Address>()};
trace!("return address : 0x{:x} - throw instruction", rust_frame_return_addr);
// the return address is within throwing frame // the return address is within throwing frame
let throw_frame_callsite = rust_frame_return_addr; let throw_frame_callsite = rust_frame_return_addr;
let throw_func_id = find_func_for_address(&cf_lock, throw_frame_callsite); let (throw_func, throw_fv) = find_func_for_address(&cf_lock, throw_frame_callsite);
trace!("throwing fucntion: {}", throw_func);
// skip to previous frame // skip to previous frame
// this is the frame that throws the exception // this is the frame that throws the exception
...@@ -36,28 +40,27 @@ pub extern fn muentry_throw_exception(exception_obj: Address) { ...@@ -36,28 +40,27 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
let mut cursor = FrameCursor { let mut cursor = FrameCursor {
rbp: rbp, rbp: rbp,
return_addr: unsafe {rbp.plus(POINTER_SIZE).load::<Address>()}, return_addr: unsafe {rbp.plus(POINTER_SIZE).load::<Address>()},
func_id: throw_func_id, func_id: throw_func,
func_ver_id: throw_fv,
callee_saved_locs: HashMap::new() callee_saved_locs: HashMap::new()
}; };
trace!("cursor at first Mu frame: {}", cursor);
let mut callsite = rust_frame_return_addr;
trace!("Stack Unwinding starts");
loop { loop {
trace!("frame cursor: {}", cursor);
// get return address (the slot above RBP slot) // get return address (the slot above RBP slot)
// let return_addr = unsafe {rbp.plus(POINTER_SIZE).load::<Address>()}; // let return_addr = unsafe {rbp.plus(POINTER_SIZE).load::<Address>()};
// check if return_addr is valid let rwlock_cf = match cf_lock.get(&cursor.func_ver_id) {
// FIXME: should use a sentinel value here
if cursor.return_addr.is_zero() {
panic!("cannot find exception catch block, throws by {}", throw_func_id);
}
let callsite = cursor.return_addr;
let rwlock_cf = match cf_lock.get(&cursor.func_id) {
Some(ret) => ret, Some(ret) => ret,
None => panic!("cannot find compiled func with func_id {}, possibly didnt find the right frame for return address", cursor.func_id) None => panic!("cannot find compiled func with func_id {}, possibly didnt find the right frame for return address", cursor.func_id)
}; };
let rwlock_cf = rwlock_cf.read().unwrap(); let rwlock_cf = rwlock_cf.read().unwrap();
let ref frame = rwlock_cf.frame; let ref frame = rwlock_cf.frame;
trace!("frame info: {}", frame);
// update callee saved register location // update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() { for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
...@@ -66,26 +69,32 @@ pub extern fn muentry_throw_exception(exception_obj: Address) { ...@@ -66,26 +69,32 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
let offset_from_rbp = frame.allocated.get(&reg_id).unwrap().offset; let offset_from_rbp = frame.allocated.get(&reg_id).unwrap().offset;
let reg_restore_addr = cursor.rbp.offset(offset_from_rbp); let reg_restore_addr = cursor.rbp.offset(offset_from_rbp);
trace!("update callee saved register {} with loc 0x{:x}", reg_id, reg_restore_addr);
cursor.callee_saved_locs.insert(reg_id, reg_restore_addr); cursor.callee_saved_locs.insert(reg_id, reg_restore_addr);
} }
} }
cursor.to_previous_frame(&cf_lock);
// find exception block - comparing callsite with frame info // find exception block - comparing callsite with frame info
trace!("checking catch block: looking for callsite 0x{:x}", callsite);
let ref exception_callsites = frame.exception_callsites; let ref exception_callsites = frame.exception_callsites;
for (possible_callsite, dest) in exception_callsites { for (possible_callsite, dest) in exception_callsites {
let possible_callsite_addr = possible_callsite.to_address(); let possible_callsite_addr = possible_callsite.to_address();
if callsite == possible_callsite_addr { if callsite == possible_callsite_addr {
trace!("found catch block at {}", dest);
// found an exception block // found an exception block
let dest_addr = dest.to_address(); let dest_addr = dest.to_address();
// restore callee saved register and jump to dest_addr // restore callee saved register and jump to dest_addr
unimplemented!()
} }
} }
trace!("didnt find a catch block");
// keep unwinding // keep unwinding
callsite = cursor.return_addr;
cursor.to_previous_frame(&cf_lock);
trace!("cursor unwinds to previous frame: {}", cursor);
} }
} }
...@@ -93,21 +102,55 @@ struct FrameCursor { ...@@ -93,21 +102,55 @@ struct FrameCursor {
rbp: Address, rbp: Address,
return_addr: Address, return_addr: Address,
func_id: MuID, func_id: MuID,
func_ver_id: MuID,
callee_saved_locs: HashMap<MuID, Address> callee_saved_locs: HashMap<MuID, Address>
} }
impl fmt::Display for FrameCursor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "FrameCursor{{").unwrap();
writeln!(f, " rbp=0x{:x}, return_addr=0x{:x}, func_id={}, func_version_id={}", self.rbp, self.return_addr, self.func_id, self.func_ver_id).unwrap();
writeln!(f, " callee_saved:").unwrap();
for (reg, addr) in self.callee_saved_locs.iter() {
writeln!(f, " #{} at 0x{:x}", reg, addr).unwrap()
}
writeln!(f, "}}")
}
}
impl FrameCursor { impl FrameCursor {
fn to_previous_frame(&mut self, cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>) { fn to_previous_frame(&mut self, cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>) {
// check if return_addr is valid
// FIXME: should use a sentinel value here
if self.return_addr.is_zero() {
panic!("cannot go to previous frame (return address is zero)");
}
let previous_rbp = unsafe {self.rbp.load::<Address>()}; let previous_rbp = unsafe {self.rbp.load::<Address>()};
let previous_return_addr = unsafe {previous_rbp.plus(POINTER_SIZE).load::<Address>()}; let previous_return_addr = unsafe {previous_rbp.plus(POINTER_SIZE).load::<Address>()};
let previous_func_id = find_func_for_address(cf, self.return_addr); let (previous_func, previous_fv_id) = find_func_for_address(cf, self.return_addr);
self.rbp = previous_rbp; self.rbp = previous_rbp;
self.return_addr = previous_return_addr; self.return_addr = previous_return_addr;
self.func_id = previous_func_id; self.func_id = previous_func;
self.func_ver_id = previous_fv_id;
} }
} }
fn find_func_for_address (cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>, pc_addr: Address) -> MuID { fn find_func_for_address (cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>, pc_addr: Address) -> (MuID, MuID) {
unimplemented!() trace!("trying to find FuncVersion for address 0x{:x}", pc_addr);
for (id, func) in cf.iter() {
let func = func.read().unwrap();
let start = func.start.to_address();
let end = func.end.to_address();
trace!("CompiledFunction: func_id={}, fv_id={}, start=0x{:x}, end=0x{:x}", func.func_id, func.func_ver_id, start, end);
if pc_addr >= start && pc_addr <= end {
trace!("Found CompiledFunction: func_id={}, fv_id={}", func.func_id, func.func_ver_id);
return (func.func_id, func.func_ver_id);
}
}
panic!("cannot find compiled function for pc 0x{:x}");
} }
\ No newline at end of file
...@@ -7,6 +7,7 @@ use compiler::backend::Word; ...@@ -7,6 +7,7 @@ use compiler::backend::Word;
use compiler::backend::RegGroup; use compiler::backend::RegGroup;
use utils::Address; use utils::Address;
use std::fmt;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::os::raw::c_void; use std::os::raw::c_void;
use std::ffi::CString; use std::ffi::CString;
...@@ -55,6 +56,18 @@ pub enum ValueLocation { ...@@ -55,6 +56,18 @@ pub enum ValueLocation {
Indirect(RegGroup, Address), // 4 Indirect(RegGroup, Address), // 4
} }
impl fmt::Display for ValueLocation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ValueLocation::Register(_, id) => write!(f, "VL_Reg: {}", id),
&ValueLocation::Constant(_, val) => write!(f, "VL_Const: {}", val),
&ValueLocation::Relocatable(_, ref name) => write!(f, "VL_Reloc: {}", name),
&ValueLocation::Direct(_, addr) => write!(f, "VL_Direct: 0x{:x}", addr),
&ValueLocation::Indirect(_, addr) => write!(f, "VL_Indirect: 0x{:x}", addr)
}
}
}
impl Encodable for ValueLocation { impl Encodable for ValueLocation {
fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> { fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
s.emit_enum("ValueLocation", |s| { s.emit_enum("ValueLocation", |s| {
......
...@@ -157,6 +157,9 @@ fn create_catch_exception_func (vm: &VM) { ...@@ -157,6 +157,9 @@ fn create_catch_exception_func (vm: &VM) {
// %blk_exn_cont() %EXN: // %blk_exn_cont() %EXN:
let mut blk_exn_cont = Block::new(blk_exn_cont_id); let mut blk_exn_cont = Block::new(blk_exn_cont_id);
vm.set_name(blk_exn_cont.as_entity(), Mu("blk_exn_cont")); vm.set_name(blk_exn_cont.as_entity(), Mu("blk_exn_cont"));
let type_ref_int64 = vm.get_type(vm.id_of("ref_int64"));
let blk_exn_cont_exception_arg = func_ver.new_ssa(vm.next_id(), type_ref_int64.clone());
vm.set_name(blk_exn_cont_exception_arg.as_entity(), Mu("blk_0_exception_arg"));
let blk_exn_cont_thread_exit = func_ver.new_inst(vm.next_id(), Instruction { let blk_exn_cont_thread_exit = func_ver.new_inst(vm.next_id(), Instruction {
value: None, value: None,
ops: RwLock::new(vec![]), ops: RwLock::new(vec![]),
...@@ -164,7 +167,7 @@ fn create_catch_exception_func (vm: &VM) { ...@@ -164,7 +167,7 @@ fn create_catch_exception_func (vm: &VM) {
}); });
blk_exn_cont.content = Some(BlockContent { blk_exn_cont.content = Some(BlockContent {
args: vec![], args: vec![],
exn_arg: None, exn_arg: Some(blk_exn_cont_exception_arg.clone_value()),
body: vec![blk_exn_cont_thread_exit], body: vec![blk_exn_cont_thread_exit],
keepalives: None keepalives: None
}); });
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment