mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-24 18:02:13 +00:00
Add updates from feedback
Co-authored-by: Ivan Enderlin <ivan.enderlin@wanadoo.fr>
This commit is contained in:
parent
3d6e915108
commit
40e4dddc4b
@ -17,8 +17,8 @@ These are the projects that were used as inspiration and/or that we are using co
|
|||||||
of generating debug information for each function with Cranelift
|
of generating debug information for each function with Cranelift
|
||||||
(for example, the sorting of the extended basic blocks before
|
(for example, the sorting of the extended basic blocks before
|
||||||
processing the instructions), and the API for transforming DWARF
|
processing the instructions), and the API for transforming DWARF
|
||||||
see wasm-debug's attribution file for more information (TODO: link
|
see [wasm-debug's attribution file](https://github.com/wasmerio/wasm-debug/blob/master/ATTRIBUTIONS.md)
|
||||||
and update here).
|
for more information
|
||||||
- [stackoverflow](https://stackoverflow.com/a/45795699/1072990): to create an efficient HashMap with pair keys
|
- [stackoverflow](https://stackoverflow.com/a/45795699/1072990): to create an efficient HashMap with pair keys
|
||||||
- [Emscripten](https://github.com/kripken/emscripten): for emtests test sources to ensure compatibility
|
- [Emscripten](https://github.com/kripken/emscripten): for emtests test sources to ensure compatibility
|
||||||
- [The WebAssembly spec](https://github.com/WebAssembly/spec/tree/master/test): for implementation details of WebAssembly and spectests
|
- [The WebAssembly spec](https://github.com/WebAssembly/spec/tree/master/test): for implementation details of WebAssembly and spectests
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
- [#1233](https://github.com/wasmerio/wasmer/pull/1233) Improved Wasmer C API release artifacts.
|
- [#1233](https://github.com/wasmerio/wasmer/pull/1233) Improved Wasmer C API release artifacts.
|
||||||
- [#1216](https://github.com/wasmerio/wasmer/pull/1216) `wasmer-interface-types` receives a binary encoder.
|
- [#1216](https://github.com/wasmerio/wasmer/pull/1216) `wasmer-interface-types` receives a binary encoder.
|
||||||
- [#1212](https://github.com/wasmerio/wasmer/pull/1212) Add `--generate-debug-info` and `-g` flags to `wasmer run` to generate debug information during compilation that is passed via the GDB JIT interface to a debugger to allow source-level debugging of Wasm files. Currently only available on clif-backend, see PR for more information on its implementation.
|
- [#1212](https://github.com/wasmerio/wasmer/pull/1212) Add `--generate-debug-info` and `-g` flags to `wasmer run` to generate debug information during compilation that is passed via the GDB JIT interface to a debugger to allow source-level debugging of Wasm files. Currently only available on clif-backend, see PR for more information on its implementation.
|
||||||
- [#1228](https://github.com/wasmerio/wasmer/pull/1228) Singlepass cleanup: Resolve several FIXMEs and remove protect_unix.
|
- [#1228](https://github.com/wasmerio/wasmer/pull/1228) Singlepass cleanup: Resolve several FIXMEs and remove protect_unix.
|
||||||
- [#1218](https://github.com/wasmerio/wasmer/pull/1218) Enable Cranelift verifier in debug mode. Fix bug with table indices being the wrong type.
|
- [#1218](https://github.com/wasmerio/wasmer/pull/1218) Enable Cranelift verifier in debug mode. Fix bug with table indices being the wrong type.
|
||||||
- [#787](https://github.com/wasmerio/wasmer/pull/787) New crate `wasmer-interface-types` to implement WebAssembly Interface Types.
|
- [#787](https://github.com/wasmerio/wasmer/pull/787) New crate `wasmer-interface-types` to implement WebAssembly Interface Types.
|
||||||
|
@ -71,7 +71,7 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
|
|||||||
fn next_function(
|
fn next_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_info: Arc<RwLock<ModuleInfo>>,
|
module_info: Arc<RwLock<ModuleInfo>>,
|
||||||
loc: (u32, u32),
|
loc: WasmSpan,
|
||||||
) -> Result<&mut CraneliftFunctionCodeGenerator, CodegenError> {
|
) -> Result<&mut CraneliftFunctionCodeGenerator, CodegenError> {
|
||||||
// define_function_body(
|
// define_function_body(
|
||||||
|
|
||||||
@ -102,8 +102,7 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
|
|||||||
target_config: self.isa.frontend_config().clone(),
|
target_config: self.isa.frontend_config().clone(),
|
||||||
clif_signatures: self.clif_signatures.clone(),
|
clif_signatures: self.clif_signatures.clone(),
|
||||||
},
|
},
|
||||||
start: loc.0,
|
loc,
|
||||||
end: loc.1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let generate_debug_info = module_info.read().unwrap().generate_debug_info;
|
let generate_debug_info = module_info.read().unwrap().generate_debug_info;
|
||||||
@ -120,7 +119,7 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
|
|||||||
&mut func_env.position,
|
&mut func_env.position,
|
||||||
);
|
);
|
||||||
|
|
||||||
builder.set_srcloc(ir::SourceLoc::new(loc.0));
|
builder.set_srcloc(ir::SourceLoc::new(loc.start()));
|
||||||
|
|
||||||
let entry_block = builder.create_ebb();
|
let entry_block = builder.create_ebb();
|
||||||
builder.append_ebb_params_for_function_params(entry_block);
|
builder.append_ebb_params_for_function_params(entry_block);
|
||||||
@ -156,9 +155,9 @@ impl ModuleCodeGenerator<CraneliftFunctionCodeGenerator, Caller, CodegenError>
|
|||||||
),
|
),
|
||||||
CodegenError,
|
CodegenError,
|
||||||
> {
|
> {
|
||||||
let mut func_bodies: Map<LocalFuncIndex, (ir::Function, (u32, u32))> = Map::new();
|
let mut func_bodies: Map<LocalFuncIndex, (ir::Function, WasmSpan)> = Map::new();
|
||||||
for f in self.functions.into_iter() {
|
for f in self.functions.into_iter() {
|
||||||
func_bodies.push((f.func, (f.start, f.end)));
|
func_bodies.push((f.func, f.loc));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (func_resolver_builder, debug_metadata, handler_data) =
|
let (func_resolver_builder, debug_metadata, handler_data) =
|
||||||
@ -256,12 +255,8 @@ pub struct CraneliftFunctionCodeGenerator {
|
|||||||
next_local: usize,
|
next_local: usize,
|
||||||
position: Position,
|
position: Position,
|
||||||
func_env: FunctionEnvironment,
|
func_env: FunctionEnvironment,
|
||||||
/// Start location of the function as an offset in bytes in the Wasm module
|
/// Where the function lives in the Wasm module as a span of bytes
|
||||||
/// from the beginning of the code section.
|
loc: WasmSpan,
|
||||||
start: u32,
|
|
||||||
/// End location of the function as an offset in bytes in the Wasm module
|
|
||||||
/// from the beginning of the code section.
|
|
||||||
end: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FunctionEnvironment {
|
pub struct FunctionEnvironment {
|
||||||
|
@ -26,6 +26,7 @@ use wasmer_runtime_core::{
|
|||||||
SigRegistry,
|
SigRegistry,
|
||||||
},
|
},
|
||||||
cache::Error as CacheError,
|
cache::Error as CacheError,
|
||||||
|
codegen::WasmSpan,
|
||||||
error::{CompileError, CompileResult},
|
error::{CompileError, CompileResult},
|
||||||
module::ModuleInfo,
|
module::ModuleInfo,
|
||||||
structures::{Map, SliceMap, TypedIndex},
|
structures::{Map, SliceMap, TypedIndex},
|
||||||
@ -96,7 +97,7 @@ impl FuncResolverBuilder {
|
|||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
isa: &dyn isa::TargetIsa,
|
isa: &dyn isa::TargetIsa,
|
||||||
function_bodies: Map<LocalFuncIndex, (ir::Function, (u32, u32))>,
|
function_bodies: Map<LocalFuncIndex, (ir::Function, WasmSpan)>,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
) -> CompileResult<(
|
) -> CompileResult<(
|
||||||
Self,
|
Self,
|
||||||
@ -127,7 +128,7 @@ impl FuncResolverBuilder {
|
|||||||
.par_iter()
|
.par_iter()
|
||||||
.map_init(
|
.map_init(
|
||||||
|| Context::new(),
|
|| Context::new(),
|
||||||
|ctx, (lfi, (func, (start, end)))| {
|
|ctx, (lfi, (func, loc))| {
|
||||||
let mut code_buf = Vec::new();
|
let mut code_buf = Vec::new();
|
||||||
ctx.func = func.to_owned();
|
ctx.func = func.to_owned();
|
||||||
let mut reloc_sink = RelocSink::new();
|
let mut reloc_sink = RelocSink::new();
|
||||||
@ -179,8 +180,8 @@ impl FuncResolverBuilder {
|
|||||||
|
|
||||||
let entry = CompiledFunctionData {
|
let entry = CompiledFunctionData {
|
||||||
instructions,
|
instructions,
|
||||||
start_srcloc: wasm_debug::types::SourceLoc::new(*start),
|
start_srcloc: wasm_debug::types::SourceLoc::new(loc.start()),
|
||||||
end_srcloc: wasm_debug::types::SourceLoc::new(*end),
|
end_srcloc: wasm_debug::types::SourceLoc::new(loc.end()),
|
||||||
// this not being 0 breaks inst-level debugging
|
// this not being 0 breaks inst-level debugging
|
||||||
body_offset: 0,
|
body_offset: 0,
|
||||||
body_len: code_buf.len(),
|
body_len: code_buf.len(),
|
||||||
|
@ -8739,7 +8739,7 @@ impl<'ctx> ModuleCodeGenerator<LLVMFunctionCodeGenerator<'ctx>, LLVMBackend, Cod
|
|||||||
fn next_function(
|
fn next_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
_module_info: Arc<RwLock<ModuleInfo>>,
|
_module_info: Arc<RwLock<ModuleInfo>>,
|
||||||
_loc: (u32, u32),
|
_loc: WasmSpan,
|
||||||
) -> Result<&mut LLVMFunctionCodeGenerator<'ctx>, CodegenError> {
|
) -> Result<&mut LLVMFunctionCodeGenerator<'ctx>, CodegenError> {
|
||||||
// Creates a new function and returns the function-scope code generator for it.
|
// Creates a new function and returns the function-scope code generator for it.
|
||||||
let (context, builder, intrinsics) = match self.functions.last_mut() {
|
let (context, builder, intrinsics) = match self.functions.last_mut() {
|
||||||
|
@ -65,6 +65,45 @@ impl fmt::Debug for InternalEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Type representing an area of Wasm code in bytes as an offset from the
|
||||||
|
/// beginning of the code section.
|
||||||
|
///
|
||||||
|
/// `start` must be less than or equal to `end`.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct WasmSpan {
|
||||||
|
/// Start offset in bytes from the beginning of the Wasm code section
|
||||||
|
start: u32,
|
||||||
|
/// End offset in bytes from the beginning of the Wasm code section
|
||||||
|
end: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasmSpan {
|
||||||
|
/// Create a new `WasmSpan`.
|
||||||
|
///
|
||||||
|
/// `start` must be less than or equal to `end`.
|
||||||
|
// TODO: mark this function as `const` when asserts get stabilized as `const`
|
||||||
|
// see: https://github.com/rust-lang/rust/issues/57563
|
||||||
|
pub fn new(start: u32, end: u32) -> Self {
|
||||||
|
debug_assert!(start <= end);
|
||||||
|
Self { start, end }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start offset in bytes from the beginning of the Wasm code section
|
||||||
|
pub const fn start(&self) -> u32 {
|
||||||
|
self.start
|
||||||
|
}
|
||||||
|
|
||||||
|
/// End offset in bytes from the beginning of the Wasm code section
|
||||||
|
pub const fn end(&self) -> u32 {
|
||||||
|
self.end
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Size in bytes of the span
|
||||||
|
pub const fn size(&self) -> u32 {
|
||||||
|
self.end - self.start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Information for a breakpoint
|
/// Information for a breakpoint
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub struct BreakpointInfo<'a> {
|
pub struct BreakpointInfo<'a> {
|
||||||
@ -115,7 +154,7 @@ pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule,
|
|||||||
fn next_function(
|
fn next_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
module_info: Arc<RwLock<ModuleInfo>>,
|
module_info: Arc<RwLock<ModuleInfo>>,
|
||||||
loc: (u32, u32),
|
loc: WasmSpan,
|
||||||
) -> Result<&mut FCG, E>;
|
) -> Result<&mut FCG, E>;
|
||||||
/// Finalizes this module.
|
/// Finalizes this module.
|
||||||
fn finalize(
|
fn finalize(
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
//! Code for interacting with the
|
//! Code for interacting with the
|
||||||
//! [GDB JIT inteface](https://sourceware.org/gdb/current/onlinedocs/gdb.html#JIT-Interface).
|
//! [GDB JIT interface](https://sourceware.org/gdb/current/onlinedocs/gdb.html#JIT-Interface).
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use std::os::raw::c_char;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
/// Entrypoint that the debugger will use to trigger a read from the
|
/// Entrypoint that the debugger will use to trigger a read from the
|
||||||
/// [`__jit_debug_descriptor`] global variable.
|
/// [`__jit_debug_descriptor`] global variable.
|
||||||
@ -17,45 +20,43 @@ use std::sync::Arc;
|
|||||||
extern "C" fn __jit_debug_register_code() {
|
extern "C" fn __jit_debug_register_code() {
|
||||||
// This code exists to prevent optimization of this function so that the
|
// This code exists to prevent optimization of this function so that the
|
||||||
// GDB JIT interface behaves as expected
|
// GDB JIT interface behaves as expected
|
||||||
let x = 3;
|
let x = 42;
|
||||||
unsafe {
|
unsafe {
|
||||||
std::ptr::read_volatile(&x);
|
std::ptr::read_volatile(&x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The operation that the debugger should perform with the entry that we gave it.
|
/// The operation that the debugger should perform with the entry that we gave it.
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub(crate) enum JITAction {
|
enum JitAction {
|
||||||
/// Do nothing.
|
/// Do nothing.
|
||||||
JIT_NOACTION = 0,
|
NoAction = 0,
|
||||||
/// Register the given code.
|
/// Register the given code.
|
||||||
JIT_REGISTER_FN = 1,
|
RegisterFn = 1,
|
||||||
/// Unregister the given code.
|
/// Unregister the given code.
|
||||||
JIT_UNREGISTER_FN = 2,
|
UnregisterFn = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Node of the doubly linked list that the GDB JIT interface reads from.
|
/// Node of the doubly linked list that the GDB JIT interface reads from.
|
||||||
#[no_mangle]
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub(crate) struct JITCodeEntry {
|
struct JitCodeEntry {
|
||||||
/// Next entry in the linked list.
|
/// Next entry in the linked list.
|
||||||
next: *mut JITCodeEntry,
|
next: *mut Self,
|
||||||
/// Previous entry in the linked list.
|
/// Previous entry in the linked list.
|
||||||
prev: *mut JITCodeEntry,
|
prev: *mut Self,
|
||||||
/// Pointer to the data we want the debugger to read.
|
/// Pointer to the data we want the debugger to read.
|
||||||
symfile_addr: *mut u8,
|
symfile_addr: *const c_char,
|
||||||
/// The amount of data at the `symfile_addr` pointer.
|
/// The amount of data at the `symfile_addr` pointer.
|
||||||
symfile_size: u64,
|
symfile_size: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for JITCodeEntry {
|
impl Default for JitCodeEntry {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
next: ptr::null_mut(),
|
next: ptr::null_mut(),
|
||||||
prev: ptr::null_mut(),
|
prev: ptr::null_mut(),
|
||||||
symfile_addr: ptr::null_mut(),
|
symfile_addr: ptr::null(),
|
||||||
symfile_size: 0,
|
symfile_size: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,41 +65,50 @@ impl Default for JITCodeEntry {
|
|||||||
/// Head node of the doubly linked list that the GDB JIT interface expects.
|
/// Head node of the doubly linked list that the GDB JIT interface expects.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub(crate) struct JitDebugDescriptor {
|
struct JitDebugDescriptor {
|
||||||
/// The version of the JIT interface to use (presumably, TODO: double check this)
|
/// The version of the JIT interface to use.
|
||||||
version: u32,
|
version: u32,
|
||||||
/// Which action to perform, see [`JITAction`].
|
/// Which action to perform.
|
||||||
action_flag: u32,
|
action_flag: JitAction,
|
||||||
/// The entry in the list that the `action_flag` applies to.
|
/// The entry in the list that the `action_flag` applies to.
|
||||||
relevant_entry: *mut JITCodeEntry,
|
relevant_entry: *mut JitCodeEntry,
|
||||||
/// The first entry in the doubly linked list.
|
/// The first entry in the doubly linked list.
|
||||||
first_entry: *mut JITCodeEntry,
|
first_entry: *mut JitCodeEntry,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Global variable that the GDB JIT interface will read the data from.
|
/// Global variable that the GDB JIT interface will read the data from.
|
||||||
/// The data is in the form of a doubly linked list. This global variable acts
|
/// The data is in the form of a doubly linked list. This global variable acts
|
||||||
/// as a head node with extra information about the operation that we want the
|
/// as a head node with extra information about the operation that we want the
|
||||||
/// debugger to perform.
|
/// debugger to perform.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
pub(crate) static mut __jit_debug_descriptor: JitDebugDescriptor = JitDebugDescriptor {
|
static mut __jit_debug_descriptor: JitDebugDescriptor = JitDebugDescriptor {
|
||||||
version: 1,
|
version: 1,
|
||||||
action_flag: JITAction::JIT_NOACTION as _,
|
action_flag: JitAction::NoAction,
|
||||||
relevant_entry: ptr::null_mut(),
|
relevant_entry: ptr::null_mut(),
|
||||||
first_entry: ptr::null_mut(),
|
first_entry: ptr::null_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
/// Global lock on [`__jit_debug_descriptor`]. Acquire this lock when
|
||||||
|
/// reading or writing to the global variable. This includes calls to
|
||||||
|
/// [`__jit_debug_register_code`] which may cause a debugger to read from
|
||||||
|
/// the global variable.
|
||||||
|
static ref JIT_DEBUG_DESCRIPTOR_LOCK: Mutex<()> = Mutex::new(());
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepend an item to the front of the `__jit_debug_descriptor` entry list
|
/// Prepend an item to the front of the `__jit_debug_descriptor` entry list
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// - Access to underlying global variable is unsynchronized.
|
/// - Access to underlying global variable is unsynchronized: acquire a lock on
|
||||||
/// - Pointer to [`JITCodeEntry`] should point to a valid entry.
|
/// [`JIT_DEBUG_DESCRIPTOR_LOCK`] before calling this function.
|
||||||
unsafe fn push_front(jce: *mut JITCodeEntry) {
|
/// - Pointer to [`JitCodeEntry`] must point to a valid entry.
|
||||||
|
unsafe fn push_front(jce: *mut JitCodeEntry) {
|
||||||
if __jit_debug_descriptor.first_entry.is_null() {
|
if __jit_debug_descriptor.first_entry.is_null() {
|
||||||
__jit_debug_descriptor.first_entry = jce;
|
__jit_debug_descriptor.first_entry = jce;
|
||||||
} else {
|
} else {
|
||||||
let old_first = __jit_debug_descriptor.first_entry;
|
let old_first = __jit_debug_descriptor.first_entry;
|
||||||
debug_assert!((*old_first).prev.is_null());
|
assert!((*old_first).prev.is_null());
|
||||||
(*jce).next = old_first;
|
(*jce).next = old_first;
|
||||||
(*old_first).prev = jce;
|
(*old_first).prev = jce;
|
||||||
__jit_debug_descriptor.first_entry = jce;
|
__jit_debug_descriptor.first_entry = jce;
|
||||||
@ -109,11 +119,12 @@ unsafe fn push_front(jce: *mut JITCodeEntry) {
|
|||||||
/// connected to.
|
/// connected to.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
/// - Access to underlying global variable is unsynchronized.
|
/// - Access to underlying global variable is unsynchronized: acquire a lock on
|
||||||
/// - Pointer must point to a valid `JitCodeEntry`.
|
/// [`JIT_DEBUG_DESCRIPTOR_LOCK`] before calling this function.
|
||||||
unsafe fn remove_node(jce: *mut JITCodeEntry) {
|
/// - Pointer to [`JitCodeEntry`] must point to a valid entry.
|
||||||
|
unsafe fn remove_node(jce: *mut JitCodeEntry) {
|
||||||
if __jit_debug_descriptor.first_entry == jce {
|
if __jit_debug_descriptor.first_entry == jce {
|
||||||
debug_assert!((*jce).prev.is_null());
|
assert!((*jce).prev.is_null());
|
||||||
__jit_debug_descriptor.first_entry = (*jce).next;
|
__jit_debug_descriptor.first_entry = (*jce).next;
|
||||||
}
|
}
|
||||||
if !(*jce).prev.is_null() {
|
if !(*jce).prev.is_null() {
|
||||||
@ -126,25 +137,26 @@ unsafe fn remove_node(jce: *mut JITCodeEntry) {
|
|||||||
|
|
||||||
/// Type for implementing Drop on the memory shared with the debugger.
|
/// Type for implementing Drop on the memory shared with the debugger.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct JITCodeDebugInfoEntryHandleInner(*mut JITCodeEntry);
|
struct JitCodeDebugInfoEntryHandleInner(*mut JitCodeEntry);
|
||||||
|
|
||||||
/// Handle to debug info about JIT code registered with a debugger
|
/// Handle to debug info about JIT code registered with a debugger
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct JITCodeDebugInfoEntryHandle(Arc<JITCodeDebugInfoEntryHandleInner>);
|
pub(crate) struct JitCodeDebugInfoEntryHandle(Arc<JitCodeDebugInfoEntryHandleInner>);
|
||||||
|
|
||||||
impl Drop for JITCodeDebugInfoEntryHandleInner {
|
impl Drop for JitCodeDebugInfoEntryHandleInner {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
let _guard = JIT_DEBUG_DESCRIPTOR_LOCK.lock().unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
// unregister the function when dropping the JIT code entry
|
// unregister the function when dropping the JIT code entry
|
||||||
__jit_debug_descriptor.relevant_entry = self.0;
|
__jit_debug_descriptor.relevant_entry = self.0;
|
||||||
__jit_debug_descriptor.action_flag = JITAction::JIT_UNREGISTER_FN as u32;
|
__jit_debug_descriptor.action_flag = JitAction::UnregisterFn;
|
||||||
__jit_debug_register_code();
|
__jit_debug_register_code();
|
||||||
__jit_debug_descriptor.relevant_entry = ptr::null_mut();
|
__jit_debug_descriptor.relevant_entry = ptr::null_mut();
|
||||||
__jit_debug_descriptor.action_flag = JITAction::JIT_NOACTION as u32;
|
__jit_debug_descriptor.action_flag = JitAction::NoAction;
|
||||||
remove_node(self.0);
|
remove_node(self.0);
|
||||||
let entry: Box<JITCodeEntry> = Box::from_raw(self.0);
|
let entry: Box<JitCodeEntry> = Box::from_raw(self.0);
|
||||||
Vec::from_raw_parts(
|
Vec::from_raw_parts(
|
||||||
entry.symfile_addr,
|
entry.symfile_addr as *mut u8,
|
||||||
entry.symfile_size as _,
|
entry.symfile_size as _,
|
||||||
entry.symfile_size as _,
|
entry.symfile_size as _,
|
||||||
);
|
);
|
||||||
@ -154,16 +166,16 @@ impl Drop for JITCodeDebugInfoEntryHandleInner {
|
|||||||
|
|
||||||
/// Manager of debug info registered with the debugger.
|
/// Manager of debug info registered with the debugger.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct JITCodeDebugInfoManager {
|
pub(crate) struct JitCodeDebugInfoManager {
|
||||||
inner: Vec<JITCodeDebugInfoEntryHandle>,
|
inner: Vec<JitCodeDebugInfoEntryHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JITCodeDebugInfoManager {
|
impl JitCodeDebugInfoManager {
|
||||||
/// Register debug info relating to JIT code with the debugger.
|
/// Register debug info relating to JIT code with the debugger.
|
||||||
pub(crate) fn register_new_jit_code_entry(
|
pub(crate) fn register_new_jit_code_entry(
|
||||||
&mut self,
|
&mut self,
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
) -> JITCodeDebugInfoEntryHandle {
|
) -> JitCodeDebugInfoEntryHandle {
|
||||||
let mut owned_bytes = bytes.iter().cloned().collect::<Vec<u8>>();
|
let mut owned_bytes = bytes.iter().cloned().collect::<Vec<u8>>();
|
||||||
// ensure length == capacity to simplify memory freeing code
|
// ensure length == capacity to simplify memory freeing code
|
||||||
owned_bytes.shrink_to_fit();
|
owned_bytes.shrink_to_fit();
|
||||||
@ -172,22 +184,23 @@ impl JITCodeDebugInfoManager {
|
|||||||
|
|
||||||
std::mem::forget(owned_bytes);
|
std::mem::forget(owned_bytes);
|
||||||
|
|
||||||
let entry: *mut JITCodeEntry = Box::into_raw(Box::new(JITCodeEntry {
|
let entry: *mut JitCodeEntry = Box::into_raw(Box::new(JitCodeEntry {
|
||||||
symfile_addr: ptr,
|
symfile_addr: ptr as *const _,
|
||||||
symfile_size: len as _,
|
symfile_size: len as _,
|
||||||
..JITCodeEntry::default()
|
..JitCodeEntry::default()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let _guard = JIT_DEBUG_DESCRIPTOR_LOCK.lock().unwrap();
|
||||||
push_front(entry);
|
push_front(entry);
|
||||||
__jit_debug_descriptor.relevant_entry = entry;
|
__jit_debug_descriptor.relevant_entry = entry;
|
||||||
__jit_debug_descriptor.action_flag = JITAction::JIT_REGISTER_FN as u32;
|
__jit_debug_descriptor.action_flag = JitAction::RegisterFn;
|
||||||
__jit_debug_register_code();
|
__jit_debug_register_code();
|
||||||
__jit_debug_descriptor.relevant_entry = ptr::null_mut();
|
__jit_debug_descriptor.relevant_entry = ptr::null_mut();
|
||||||
__jit_debug_descriptor.action_flag = JITAction::JIT_NOACTION as u32;
|
__jit_debug_descriptor.action_flag = JitAction::NoAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
let handle = JITCodeDebugInfoEntryHandle(Arc::new(JITCodeDebugInfoEntryHandleInner(entry)));
|
let handle = JitCodeDebugInfoEntryHandle(Arc::new(JitCodeDebugInfoEntryHandleInner(entry)));
|
||||||
self.inner.push(handle.clone());
|
self.inner.push(handle.clone());
|
||||||
|
|
||||||
handle
|
handle
|
||||||
|
@ -87,7 +87,7 @@ pub struct ModuleInfo {
|
|||||||
#[cfg(feature = "generate-debug-information")]
|
#[cfg(feature = "generate-debug-information")]
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
/// Resource manager of debug information being used by a debugger.
|
/// Resource manager of debug information being used by a debugger.
|
||||||
pub debug_info_manager: jit_debug::JITCodeDebugInfoManager,
|
pub(crate) debug_info_manager: jit_debug::JitCodeDebugInfoManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleInfo {
|
impl ModuleInfo {
|
||||||
|
@ -229,7 +229,10 @@ pub fn read_module<
|
|||||||
}
|
}
|
||||||
|
|
||||||
let fcg = mcg
|
let fcg = mcg
|
||||||
.next_function(Arc::clone(&info), (range.start as u32, range.end as u32))
|
.next_function(
|
||||||
|
Arc::clone(&info),
|
||||||
|
WasmSpan::new(range.start as u32, range.end as u32),
|
||||||
|
)
|
||||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -682,7 +682,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
|||||||
fn next_function(
|
fn next_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
_module_info: Arc<RwLock<ModuleInfo>>,
|
_module_info: Arc<RwLock<ModuleInfo>>,
|
||||||
_loc: (u32, u32),
|
_loc: WasmSpan,
|
||||||
) -> Result<&mut X64FunctionCode, CodegenError> {
|
) -> Result<&mut X64FunctionCode, CodegenError> {
|
||||||
let (mut assembler, mut function_labels, breakpoints, exception_table) =
|
let (mut assembler, mut function_labels, breakpoints, exception_table) =
|
||||||
match self.functions.last_mut() {
|
match self.functions.last_mut() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user