Backtrace WebAssembly function JIT frames (#759)

* Create backtrace

* Extend unwind information with FDE data.

* Expose backtrace via API/Trap

* wasmtime_call returns not-str

* Return Arc<JITFrameTag>

* rename frame -> function

* Fix windows crashes and unwrap UNWIND_HISTORY_TABLE

* mmaps -> entries

* pass a backtrace in ActionOutcome

* add test_trap_stack_overflow

* Update cranelift version.
This commit is contained in:
Yury Delendik
2020-01-15 13:48:24 -06:00
committed by GitHub
parent 0848a7eaaa
commit 2a50701f0a
26 changed files with 803 additions and 149 deletions

View File

@@ -0,0 +1,83 @@
#![allow(missing_docs)]
use lazy_static::lazy_static;
use std::collections::BTreeMap;
use std::sync::{Arc, RwLock};
lazy_static! {
static ref REGISTRY: RwLock<JITFunctionRegistry> = RwLock::new(JITFunctionRegistry::default());
}
#[derive(Clone)]
pub struct JITFunctionTag {
pub module_id: Option<String>,
pub func_index: usize,
}
impl std::fmt::Debug for JITFunctionTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(ref module_id) = self.module_id {
write!(f, "{}", module_id)?;
} else {
write!(f, "(module)")?;
}
write!(f, ":{}", self.func_index)
}
}
struct JITFunctionRegistry {
ranges: BTreeMap<usize, (usize, Arc<JITFunctionTag>)>,
}
impl Default for JITFunctionRegistry {
fn default() -> Self {
Self {
ranges: Default::default(),
}
}
}
impl JITFunctionRegistry {
fn register(&mut self, fn_start: usize, fn_end: usize, tag: JITFunctionTag) {
self.ranges.insert(fn_end, (fn_start, Arc::new(tag)));
}
fn unregister(&mut self, fn_end: usize) {
self.ranges.remove(&fn_end);
}
fn find(&self, pc: usize) -> Option<&Arc<JITFunctionTag>> {
self.ranges
.range(pc..)
.next()
.and_then(|(end, (start, s))| {
if *start <= pc && pc < *end {
Some(s)
} else {
None
}
})
}
}
pub fn register(fn_start: usize, fn_end: usize, tag: JITFunctionTag) {
REGISTRY
.write()
.expect("jit function registry lock got poisoned")
.register(fn_start, fn_end, tag);
}
pub fn unregister(_fn_start: usize, fn_end: usize) {
REGISTRY
.write()
.expect("jit function registry lock got poisoned")
.unregister(fn_end);
}
pub fn find(pc: usize) -> Option<Arc<JITFunctionTag>> {
REGISTRY
.read()
.expect("jit function registry lock got poisoned")
.find(pc)
.cloned()
}