WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

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 {
self.add_asm_symbolic(directive_globl(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) {
let func_end_symbol = {
let mut symbol = symbol(func_name.clone());
let func_end = {
let mut symbol = func_name.clone();
symbol.push_str("_end");
symbol
};
self.add_asm_symbolic(directive_globl(func_end_symbol.clone()));
self.add_asm_symbolic(format!("{}:", func_end_symbol.clone()));
self.add_asm_symbolic(directive_globl(symbol(func_end.clone())));
self.add_asm_symbolic(format!("{}:", symbol(func_end.clone())));
self.control_flow_analysis();
(
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 {
}
fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation {
let block_symbol = symbol(self.asm_block_label(block_name.clone()));
self.add_asm_symbolic(directive_globl(block_symbol.clone()));
self.add_asm_symbolic(format!("{}:", block_symbol.clone()));
let block = self.asm_block_label(block_name.clone());
self.add_asm_symbolic(directive_globl(symbol(block.clone())));
self.add_asm_symbolic(format!("{}:", symbol(block.clone())));
self.start_block(block_name);
ValueLocation::Relocatable(RegGroup::GPR, block_symbol)
ValueLocation::Relocatable(RegGroup::GPR, block)
}
fn end_block(&mut self, block_name: MuName) {
......@@ -1155,14 +1155,14 @@ impl CodeGenerator for ASMCodeGen {
fn emit_call_near_rel32(&mut self, callsite: String, func: MuName) -> ValueLocation {
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(format!("{}:", callsite_symbol.clone()));
let asm = format!("call {}", symbol(func));
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 {
......
......@@ -3,6 +3,7 @@ use ast::ptr::*;
use ast::types::*;
use runtime::ValueLocation;
use std::fmt;
use std::collections::HashMap;
use utils::POINTER_SIZE;
use vm::VM;
......@@ -28,6 +29,21 @@ pub struct Frame {
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 {
pub fn new(func_ver_id: MuID) -> Frame {
Frame {
......@@ -49,6 +65,7 @@ impl Frame {
}
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);
}
......@@ -72,6 +89,12 @@ pub struct FrameSlot {
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 {
#[cfg(target_arch = "x86_64")]
pub fn make_memory_op(&self, ty: P<MuType>, vm: &VM) -> P<Value> {
......
......@@ -9,6 +9,7 @@ use runtime::thread;
use std::sync::RwLock;
use std::sync::RwLockReadGuard;
use std::collections::HashMap;
use std::fmt;
#[no_mangle]
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)
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>()};
trace!("return address : 0x{:x} - throw instruction", rust_frame_return_addr);
// the return address is within throwing frame
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
// this is the frame that throws the exception
......@@ -36,28 +40,27 @@ pub extern fn muentry_throw_exception(exception_obj: Address) {
let mut cursor = FrameCursor {
rbp: rbp,
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()
};
trace!("cursor at first Mu frame: {}", cursor);
let mut callsite = rust_frame_return_addr;
trace!("Stack Unwinding starts");
loop {
trace!("frame cursor: {}", cursor);
// get return address (the slot above RBP slot)
// let return_addr = unsafe {rbp.plus(POINTER_SIZE).load::<Address>()};
// check if return_addr is valid
// 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) {
let rwlock_cf = match cf_lock.get(&cursor.func_ver_id) {
Some(ret) => ret,
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 ref frame = rwlock_cf.frame;
trace!("frame info: {}", frame);
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
......@@ -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 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.to_previous_frame(&cf_lock);
// 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;
for (possible_callsite, dest) in exception_callsites {
let possible_callsite_addr = possible_callsite.to_address();
if callsite == possible_callsite_addr {
trace!("found catch block at {}", dest);
// found an exception block
let dest_addr = dest.to_address();
// restore callee saved register and jump to dest_addr
unimplemented!()
}
}
trace!("didnt find a catch block");
// 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 {
rbp: Address,
return_addr: Address,
func_id: MuID,
func_ver_id: MuID,
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 {
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_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.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 {
unimplemented!()
fn find_func_for_address (cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>, pc_addr: Address) -> (MuID, MuID) {
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;
use compiler::backend::RegGroup;
use utils::Address;
use std::fmt;
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ffi::CString;
......@@ -55,6 +56,18 @@ pub enum ValueLocation {
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 {
fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
s.emit_enum("ValueLocation", |s| {
......
......@@ -157,6 +157,9 @@ fn create_catch_exception_func (vm: &VM) {
// %blk_exn_cont() %EXN:
let mut blk_exn_cont = Block::new(blk_exn_cont_id);
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 {
value: None,
ops: RwLock::new(vec![]),
......@@ -164,7 +167,7 @@ fn create_catch_exception_func (vm: &VM) {
});
blk_exn_cont.content = Some(BlockContent {
args: vec![],
exn_arg: None,
exn_arg: Some(blk_exn_cont_exception_arg.clone_value()),
body: vec![blk_exn_cont_thread_exit],
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