Generate debug info for LLDB/GDB (#50)
* Transform DWARF sections into native format for wasm2obj and wasmtime. Generate DWARF sections based on WASM DWARF. Ignore some of debug_info/debug_line for dead code. * Fix test
This commit is contained in:
committed by
Dan Gohman
parent
6eb09d9edd
commit
ddbc00752e
@@ -4,6 +4,7 @@
|
||||
|
||||
use crate::export::Export;
|
||||
use crate::imports::Imports;
|
||||
use crate::jit_int::GdbJitImageRegistration;
|
||||
use crate::memory::LinearMemory;
|
||||
use crate::mmap::Mmap;
|
||||
use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish};
|
||||
@@ -215,6 +216,9 @@ pub(crate) struct Instance {
|
||||
/// Hosts can store arbitrary per-instance information here.
|
||||
host_state: Box<dyn Any>,
|
||||
|
||||
/// Optional image of JIT'ed code for debugger registration.
|
||||
dbg_jit_registration: Option<Rc<GdbJitImageRegistration>>,
|
||||
|
||||
/// Additional context used by compiled wasm code. This field is last, and
|
||||
/// represents a dynamically-sized array that extends beyond the nominal
|
||||
/// end of the struct (similar to a flexible array member).
|
||||
@@ -623,6 +627,7 @@ impl InstanceHandle {
|
||||
imports: Imports,
|
||||
data_initializers: &[DataInitializer<'_>],
|
||||
vmshared_signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
|
||||
dbg_jit_registration: Option<Rc<GdbJitImageRegistration>>,
|
||||
host_state: Box<dyn Any>,
|
||||
) -> Result<Self, InstantiationError> {
|
||||
let mut tables = create_tables(&module);
|
||||
@@ -664,6 +669,7 @@ impl InstanceHandle {
|
||||
memories,
|
||||
tables,
|
||||
finished_functions,
|
||||
dbg_jit_registration,
|
||||
host_state,
|
||||
vmctx: VMContext {},
|
||||
};
|
||||
|
||||
113
lib/runtime/src/jit_int.rs
Normal file
113
lib/runtime/src/jit_int.rs
Normal file
@@ -0,0 +1,113 @@
|
||||
//! The GDB's JIT compilation interface. The low level module that exposes
|
||||
//! the __jit_debug_register_code() and __jit_debug_descriptor to register
|
||||
//! or unregister generated object images with debuggers.
|
||||
|
||||
use std::boxed::Box;
|
||||
use std::ptr;
|
||||
|
||||
#[repr(C)]
|
||||
struct JITCodeEntry {
|
||||
next_entry: *mut JITCodeEntry,
|
||||
prev_entry: *mut JITCodeEntry,
|
||||
symfile_addr: *const u8,
|
||||
symfile_size: u64,
|
||||
}
|
||||
|
||||
const JIT_NOACTION: u32 = 0;
|
||||
const JIT_REGISTER_FN: u32 = 1;
|
||||
const JIT_UNREGISTER_FN: u32 = 2;
|
||||
|
||||
#[repr(C)]
|
||||
struct JITDescriptor {
|
||||
version: u32,
|
||||
action_flag: u32,
|
||||
relevant_entry: *mut JITCodeEntry,
|
||||
first_entry: *mut JITCodeEntry,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[used]
|
||||
static mut __jit_debug_descriptor: JITDescriptor = JITDescriptor {
|
||||
version: 1,
|
||||
action_flag: JIT_NOACTION,
|
||||
relevant_entry: ptr::null_mut(),
|
||||
first_entry: ptr::null_mut(),
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
extern "C" fn __jit_debug_register_code() {}
|
||||
|
||||
/// Registeration for JIT image
|
||||
pub struct GdbJitImageRegistration {
|
||||
entry: *mut JITCodeEntry,
|
||||
file: Vec<u8>,
|
||||
}
|
||||
|
||||
impl GdbJitImageRegistration {
|
||||
/// Registers JIT image using __jit_debug_register_code
|
||||
pub fn register(file: Vec<u8>) -> GdbJitImageRegistration {
|
||||
GdbJitImageRegistration {
|
||||
entry: unsafe { register_gdb_jit_image(&file) },
|
||||
file,
|
||||
}
|
||||
}
|
||||
|
||||
/// JIT image used in registration
|
||||
pub fn file(&self) -> &[u8] {
|
||||
&self.file
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for GdbJitImageRegistration {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
unregister_gdb_jit_image(self.entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn register_gdb_jit_image(file: &[u8]) -> *mut JITCodeEntry {
|
||||
// Create a code entry for the file, which gives the start and size of the symbol file.
|
||||
let entry = Box::into_raw(Box::new(JITCodeEntry {
|
||||
next_entry: __jit_debug_descriptor.first_entry,
|
||||
prev_entry: ptr::null_mut(),
|
||||
symfile_addr: file.as_ptr(),
|
||||
symfile_size: file.len() as u64,
|
||||
}));
|
||||
// Add it to the linked list in the JIT descriptor.
|
||||
if __jit_debug_descriptor.first_entry != ptr::null_mut() {
|
||||
(*__jit_debug_descriptor.first_entry).prev_entry = entry;
|
||||
}
|
||||
__jit_debug_descriptor.first_entry = entry;
|
||||
// Point the relevant_entry field of the descriptor at the entry.
|
||||
__jit_debug_descriptor.relevant_entry = entry;
|
||||
// Set action_flag to JIT_REGISTER and call __jit_debug_register_code.
|
||||
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
|
||||
__jit_debug_register_code();
|
||||
|
||||
__jit_debug_descriptor.action_flag = JIT_NOACTION;
|
||||
__jit_debug_descriptor.relevant_entry = ptr::null_mut();
|
||||
entry
|
||||
}
|
||||
|
||||
unsafe fn unregister_gdb_jit_image(entry: *mut JITCodeEntry) {
|
||||
// Remove the code entry corresponding to the code from the linked list.
|
||||
if (*entry).prev_entry != ptr::null_mut() {
|
||||
(*(*entry).prev_entry).next_entry = (*entry).next_entry;
|
||||
} else {
|
||||
__jit_debug_descriptor.first_entry = (*entry).next_entry;
|
||||
}
|
||||
if (*entry).next_entry != ptr::null_mut() {
|
||||
(*(*entry).next_entry).prev_entry = (*entry).prev_entry;
|
||||
}
|
||||
// Point the relevant_entry field of the descriptor at the code entry.
|
||||
__jit_debug_descriptor.relevant_entry = entry;
|
||||
// Set action_flag to JIT_UNREGISTER and call __jit_debug_register_code.
|
||||
__jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
|
||||
__jit_debug_register_code();
|
||||
|
||||
__jit_debug_descriptor.action_flag = JIT_NOACTION;
|
||||
__jit_debug_descriptor.relevant_entry = ptr::null_mut();
|
||||
let _box = Box::from_raw(entry);
|
||||
}
|
||||
@@ -34,6 +34,7 @@ extern crate winapi;
|
||||
mod export;
|
||||
mod imports;
|
||||
mod instance;
|
||||
mod jit_int;
|
||||
mod memory;
|
||||
mod mmap;
|
||||
mod sig_registry;
|
||||
@@ -47,6 +48,7 @@ pub mod libcalls;
|
||||
pub use crate::export::Export;
|
||||
pub use crate::imports::Imports;
|
||||
pub use crate::instance::{InstanceHandle, InstantiationError, LinkError};
|
||||
pub use crate::jit_int::GdbJitImageRegistration;
|
||||
pub use crate::mmap::Mmap;
|
||||
pub use crate::sig_registry::SignatureRegistry;
|
||||
pub use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish};
|
||||
|
||||
@@ -393,7 +393,7 @@ pub struct VMSharedSignatureIndex(u32);
|
||||
mod test_vmshared_signature_index {
|
||||
use super::VMSharedSignatureIndex;
|
||||
use core::mem::size_of;
|
||||
use wasmtime_environ::{Module, VMOffsets};
|
||||
use wasmtime_environ::{Module, TargetSharedSignatureIndex, VMOffsets};
|
||||
|
||||
#[test]
|
||||
fn check_vmshared_signature_index() {
|
||||
@@ -404,6 +404,14 @@ mod test_vmshared_signature_index {
|
||||
usize::from(offsets.size_of_vmshared_signature_index())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_target_shared_signature_index() {
|
||||
assert_eq!(
|
||||
size_of::<VMSharedSignatureIndex>(),
|
||||
size_of::<TargetSharedSignatureIndex>()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl VMSharedSignatureIndex {
|
||||
|
||||
Reference in New Issue
Block a user