GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

Commit 116ec97c authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Tested new idea of incrementelly creating the exception table

parent 4df89048
......@@ -1103,16 +1103,29 @@ impl Clone for MuEntityHeader {
}
}
pub fn name_check(name: MuName) -> MuName {
let name = name.replace('.', "$");
if name.starts_with("@") || name.starts_with("%") {
let (_, name) = name.split_at(1);
// WARNING: A name starting with a '.L' will be interpreted as a local label
// (and so will not be exported to the generated file), however .globl overrides this
pub fn name_mangle(name: MuName) -> MuName {
/*if name.chars().next().unwrap().is_digit(10) {
unimplemented!();
// TODO: we could prefix every name with 'mu_', but this will break things
// that expect mu entities to be named in a certain way
}*/
// Note: we don't wan't symbols starting with this??
let name = if name.starts_with("%") {
warn!("The name {} cannot be loslessly demangled (WE SHOULDN't be passing local names to the VM anyway)", name);
name.split_at(1).0.to_string()
} else {
name
};
return name.to_string();
}
name.replace('-', "$")
}
name
pub fn name_demangle(name: MuName) -> MuName {
name.replace('$', "-")
}
......@@ -1127,7 +1140,7 @@ impl MuEntityHeader {
pub fn named(id: MuID, name: MuName) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: Some(name_check(name))
name: Some(name_mangle(name))
}
}
......
......@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_use]
extern crate log;
extern crate simple_logger;
#[macro_use]
......
......@@ -3507,7 +3507,6 @@ pub fn emit_context_with_reloc(vm: &VM,
fields : HashMap<Address, String>) {
use std::path;
use std::io::prelude::*;
use rustc_serialize::json;
emit_mu_types(vm);
......
......@@ -59,16 +59,14 @@ pub extern fn throw_exception_internal(exception_obj: Address, frame_cursor: Add
trace!("\tprevious_frame_pointer: 0x{:x}", previous_frame_pointer);
trace!("\tcurrent_frame_pointer: 0x{:x}", current_frame_pointer);
let table_entry = vm.compiled_exception_table.get(&callsite);
if table_entry.is_none() {
let exception_info = vm.get_exception_callsite(callsite);
if exception_info.is_none() {
error!("Cannot find Mu callsite (i.e. we have reached a native frame), either there isn't a catch block to catch the exception or your catch block is above a native function call");
print_backtrace(start_callsite, start_frame);
unreachable!(); // The above function will not return
panic!("Uncaught Mu Exception");
}
let &(catch_address, compiled_func) = table_entry.unwrap();
let (catch_address, compiled_func) = exception_info.unwrap();
// Check for a catch block at this callsite (there won't be one on the first iteration of this loop)
if !catch_address.is_zero() {
trace!("Found catch block: 0x{:x}", catch_address);
......@@ -121,7 +119,7 @@ fn print_frame(base: Address) {
// This function may segfault or panic when it reaches the bottom of the stack
// (TODO: Determine where the bottom is without segfaulting)
fn print_backtrace(start_callsite: Address, base: Address) -> !{
fn print_backtrace(start_callsite: Address, base: Address) {
error!("BACKTRACE: ");
let cur_thread = thread::MuThread::current();
......@@ -131,9 +129,11 @@ fn print_backtrace(start_callsite: Address, base: Address) -> !{
let mut frame_count = 0;
let mut callsite = start_callsite;
let compiled_exception_table = vm.compiled_exception_table.read().unwrap();
loop {
if vm.compiled_exception_table.contains_key(&callsite) {
let &(_, compiled_func_ptr) = vm.compiled_exception_table.get(&callsite).unwrap();
let info = compiled_exception_table.get(&callsite);
if info.is_some() {
let &(_, compiled_func_ptr) = info.unwrap();
unsafe {
let ref compiled_func = *compiled_func_ptr;
......@@ -149,7 +149,7 @@ fn print_backtrace(start_callsite: Address, base: Address) -> !{
frame_pointer = get_previous_frame_pointer(frame_pointer);
if frame_pointer.is_zero() {
panic!("Uncaught Mu Exception");
return;
}
callsite = get_return_address(frame_pointer);
......
......@@ -55,6 +55,7 @@ extern "C" {
// TODO: this actually returns the name and address of the nearest symbol (of any type)
// that starts before function_addr (instead we want the nearest function symbol)
// Note: this is not expected to be called on Mu entitiees
pub fn get_function_info(function_addr: Address) -> (CName, Address) {
use std::ptr;
......@@ -81,14 +82,35 @@ pub fn get_function_info(function_addr: Address) -> (CName, Address) {
} else {
("UNKOWN".to_string(), Address::from_ptr(info.dli_saddr))
}
}
// Returns None if the address isn't the address of a symbol
pub fn resolve_address(address: Address) -> Option<MuName> {
use std::ptr;
// Rust requires this to be initialised
let mut info = Dl_info {
dli_fname: ptr::null::<c_char>(),
dli_fbase: ptr::null_mut::<c_void>(),
dli_sname: ptr::null::<c_char>(),
dli_saddr: ptr::null_mut::<c_void>(),
};
unsafe {dladdr(address.to_ptr_mut::<c_void>(), &mut info)};
let error = unsafe {dlerror()};
if !error.is_null() || info.dli_sname.is_null() || Address::from_ptr(info.dli_saddr) != address {
// No symbol located at exactly address was found
None
} else {
Some(name_demangle(unsafe { CStr::from_ptr(info.dli_sname) }.to_str().unwrap().to_string()))
}
}
pub fn resolve_symbol(symbol: String) -> Address {
pub fn resolve_symbol(symbol: MuName) -> Address {
use std::ptr;
let symbol = name_check(symbol);
let symbol = name_mangle(symbol);
let rtld_default = unsafe {dlopen(ptr::null(), 0)};
let ret = unsafe {dlsym(rtld_default, CString::new(symbol.clone()).unwrap().as_ptr())};
......
......@@ -119,6 +119,12 @@ impl MuIRBuilder {
match name {
None => {},
Some(the_name) => {
let the_name = if the_name.starts_with("@") {
the_name.split_at(1).1.to_string()
} else {
the_name
};
let old = self.id_name_map.insert(my_id, the_name);
debug_assert!(old.is_none(), "ID already exists: {}, new name: {}, old name: {}",
my_id, self.id_name_map.get(&my_id).unwrap(), old.unwrap());
......
......@@ -85,7 +85,7 @@ pub struct VM {
// Maps each callsite to a tuple of the corresponding catch blocks label (or ""_
// and the id of the containing function-version
exception_table: RwLock<HashMap<MuName, (MuName, MuID)>>,
pub exception_table: RwLock<HashMap<MuName, (MuName, MuID)>>,
// ---do not serialize---
// client may try to store funcref to the heap, so that they can load it later, and call it
......@@ -93,9 +93,9 @@ pub struct VM {
#[serde(skip)]
aot_pending_funcref_store: RwLock<HashMap<Address, ValueLocation>>,
// Same as above but once the everything have been resolved to addreses
// Same as exception_table but once everything have been resolved to addresses
#[serde(skip)]
pub compiled_exception_table: HashMap<Address, (Address, *const CompiledFunction)>
pub compiled_exception_table: RwLock<HashMap<Address, (Address, *const CompiledFunction)>>
}
unsafe impl Sync for VM {}
unsafe impl Send for VM {}
......@@ -155,7 +155,7 @@ impl <'a> VM {
primordial: RwLock::new(None),
aot_pending_funcref_store: RwLock::new(HashMap::new()),
compiled_exception_table: HashMap::new(),
compiled_exception_table: RwLock::new(HashMap::new()),
};
// insert all intenral types
......@@ -233,10 +233,48 @@ impl <'a> VM {
self.exception_table.write().unwrap().insert(callsite, (catch, fv));
}
// Todo: This uses way to many lock aqcuires (up to 4 reads and 1 write)
pub fn get_exception_callsite(&self, callsite: Address) -> Option<(Address, *const CompiledFunction)> {
{
let compiled_exception_table = self.compiled_exception_table.read().unwrap();
let table_entry = compiled_exception_table.get(&callsite);
if table_entry.is_some() {
return Some(*table_entry.unwrap());
}
};
let name = resolve_address(callsite);
if name.is_none() {
return None;
}
// Get the entry in the table
let exception_table = self.exception_table.read().unwrap();
let except_entry = exception_table.get(&name.unwrap());
if except_entry.is_none() {
return None;
}
let &(ref catch, ref fv) = except_entry.unwrap();
let compiled_funcs = self.compiled_funcs.read().unwrap();
let ref compiled_func = *compiled_funcs.get(&fv).unwrap().read().unwrap();
let catch_addr = if catch.is_empty() {
unsafe { Address::zero() }
} else {
resolve_symbol(catch.clone())
};
self.compiled_exception_table.write().unwrap().insert(callsite, (catch_addr, &*compiled_func));
Some((catch_addr, &*compiled_func))
}
pub fn resume_vm(serialized_vm: &[u8]) -> VM {
use bincode;
use std::str;
let mut vm : VM = bincode::deserialize(serialized_vm).unwrap();
let vm : VM = bincode::deserialize(serialized_vm).unwrap();
vm.init_runtime();
// restore gc types
......@@ -270,22 +308,6 @@ impl <'a> VM {
}
}
// Construct Exception table
{
let exception_table = vm.exception_table.read().unwrap();
let compiled_funcs = vm.compiled_funcs.read().unwrap();
for (callsite, &(ref catch, ref fv)) in exception_table.iter() {
let ref compiled_func = *compiled_funcs.get(fv).unwrap().read().unwrap();
let catch_addr = if catch.is_empty() {
unsafe { Address::zero() }
} else {
resolve_symbol(catch.clone())
};
vm.compiled_exception_table.insert(resolve_symbol(callsite.clone()), (catch_addr, &*compiled_func));
}
}
vm
}
......@@ -807,7 +829,7 @@ impl <'a> VM {
let mut ret = hashmap!{};
for i in 0..sym_fields.len() {
let addr = sym_fields[i].v.as_address();
ret.insert(addr, name_check(sym_strings[i].clone()));
ret.insert(addr, name_mangle(sym_strings[i].clone()));
}
ret
};
......@@ -819,14 +841,14 @@ impl <'a> VM {
// client supplied relocation fields
for i in 0..reloc_fields.len() {
let addr = reloc_fields[i].v.as_address();
ret.insert(addr, name_check(reloc_strings[i].clone()));
ret.insert(addr, name_mangle(reloc_strings[i].clone()));
}
// pending funcrefs - we want to replace them as symbol
{
let mut pending_funcref = self.aot_pending_funcref_store.write().unwrap();
for (addr, vl) in pending_funcref.drain() {
ret.insert(addr, name_check(vl.to_relocatable()));
ret.insert(addr, name_mangle(vl.to_relocatable()));
}
}
......
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