GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit 7e5c1e7a authored by qinsoon's avatar qinsoon

[wip] fixed an exception bug: when finding a catch block, by mistake we

still restored callee-saved registers, should directly jump to it
parent c6bdd727
......@@ -470,7 +470,7 @@ impl ASMCode {
None
} else {
let mut cur = i;
while cur >= 0 {
loop {
if !asm[cur].is_symbol {
return Some(cur);
}
......@@ -481,8 +481,6 @@ impl ASMCode {
cur -= 1;
}
}
None
}
}
......
......@@ -81,7 +81,7 @@ macro_rules! FPR {
GPR_ALIAS!(RAX_ALIAS: (0, RAX) -> EAX, AX , AL, AH);
GPR_ALIAS!(RCX_ALIAS: (5, RCX) -> ECX, CX , CL, CH);
GPR_ALIAS!(RDX_ALIAS: (10, RDX) -> EDX, DX , DL, DH);
GPR_ALIAS!(RDX_ALIAS: (10,RDX) -> EDX, DX , DL, DH);
GPR_ALIAS!(RBX_ALIAS: (15,RBX) -> EBX, BX , BL, BH);
GPR_ALIAS!(RSP_ALIAS: (20,RSP) -> ESP, SP , SPL);
GPR_ALIAS!(RBP_ALIAS: (24,RBP) -> EBP, BP , BPL);
......
......@@ -102,41 +102,21 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
rwlock_cf.frame.clone()
};
trace!("frame info: {}", frame);
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
let reg_id = reg.id();
trace!("update callee saved register {}", reg_id);
if frame.allocated.contains_key(&reg_id) {
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);
} else {
// rbp won't find a location
if reg_id == x86_64::RBP.id() {
} else {
info!("failed to find an entry for {} in current frame", reg_id);
}
}
}
// find exception block - comparing callsite with frame info
trace!("checking catch block: looking for callsite 0x{:x}", callsite);
let exception_callsites = frame.get_exception_callsites();
for &(ref possible_callsite, ref dest) in exception_callsites.iter() {
let possible_callsite_addr = possible_callsite.to_address();
trace!("..check {} at 0x{:x}", possible_callsite, possible_callsite_addr);
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
// prepare a plain array [rbx, rbp, r12, r13, r14, r15]
macro_rules! unpack_callee_saved_from_cursor {
($reg: expr) => {
......@@ -149,7 +129,7 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
}
}
};
let rbx = unpack_callee_saved_from_cursor!(x86_64::RBX);
let r12 = unpack_callee_saved_from_cursor!(x86_64::R12);
let r13 = unpack_callee_saved_from_cursor!(x86_64::R13);
......@@ -157,16 +137,36 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
let r15 = unpack_callee_saved_from_cursor!(x86_64::R15);
let rbp = cursor.rbp.as_usize() as Word;
let array = vec![rbx, rbp, r12, r13, r14, r15];
let rsp = cursor.rbp.offset(frame.cur_offset());
info!("going to restore thread to {} with RSP {}", dest_addr, rsp);
unsafe {thread::exception_restore(dest_addr, array.as_ptr(), rsp)};
unreachable!()
}
}
trace!("didnt find a catch block");
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
let reg_id = reg.id();
trace!("update callee saved register {}", reg.name().unwrap());
if frame.allocated.contains_key(&reg_id) {
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.name().unwrap(), reg_restore_addr);
cursor.callee_saved_locs.insert(reg_id, reg_restore_addr);
} else {
// rbp won't find a location
if reg_id == x86_64::RBP.id() {
info!("skip RBP");
} else {
info!("failed to find an entry for {} in current frame", reg.name().unwrap());
}
}
}
// keep unwinding
callsite = cursor.return_addr;
......@@ -239,7 +239,8 @@ impl fmt::Display for FrameCursor {
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()
let val = unsafe {addr.load::<u64>()};
writeln!(f, " #{} at 0x{:x} (value=0x{:x}", reg, addr, val).unwrap()
}
writeln!(f, "}}")
}
......
......@@ -312,7 +312,6 @@ fn throw_catch_dont_use_exception_arg() -> VM {
}
#[test]
#[ignore]
// issue: didn't restore callee-saved register correctly, temporarily ignore this test
// FIXME: fix the bug
fn test_exception_throw_catch_and_add() {
......@@ -455,13 +454,23 @@ fn create_catch_exception_and_add(vm: &VM) {
inst! ((vm, catch_and_add_v1) blk_exception_px4:
PRINTHEX ev4
);
// load and print exc_arg
let iref_int64 = vm.get_type(vm.id_of("iref_int64"));
ssa! ((vm, catch_and_add_v1) <iref_int64> exc_iref);
inst! ((vm, catch_and_add_v1) blk_exception_getiref:
exc_iref = GETIREF exc_arg
);
ssa! ((vm, catch_and_add_v1) <int64> exc_val);
inst! ((vm, catch_and_add_v1) blk_exception_load_exc:
exc_val = LOAD exc_iref (is_ptr: false, order: MemoryOrder::SeqCst)
);
inst! ((vm, catch_and_add_v1) blk_exception_px5:
PRINTHEX exc_arg
PRINTHEX exc_val
);
ssa! ((vm, catch_and_add_v1) <int64> res0);
inst! ((vm, catch_and_add_v1) blk_exception_add0:
res0 = BINOP (BinOp::Add) exc_arg ev0
res0 = BINOP (BinOp::Add) exc_val ev0
);
ssa! ((vm, catch_and_add_v1) <int64> res1);
......@@ -496,6 +505,9 @@ fn create_catch_exception_and_add(vm: &VM) {
blk_exception_px2,
blk_exception_px3,
blk_exception_px4,
blk_exception_getiref,
blk_exception_load_exc,
blk_exception_px5,
blk_exception_add0,
......
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