Utility methods for artificial debug types in the generated DWARF (#1482)
* add operator* * add operator-> * add ptr() unwrap method * comments/refactor * macro_rules * external symbols workaround
This commit is contained in:
@@ -6,49 +6,62 @@ use wasmtime_environ::isa::TargetIsa;
|
||||
use wasmtime_environ::wasm::DefinedFuncIndex;
|
||||
use wasmtime_environ::{ModuleMemoryOffset, ModuleVmctxInfo, ValueLabelsRanges};
|
||||
|
||||
/// Adds internal Wasm utility types DIEs such as WebAssemblyPtr and
|
||||
/// WasmtimeVMContext.
|
||||
///
|
||||
/// For unwrapping Wasm pointer, the WasmtimeVMContext has the `set()` method
|
||||
/// that allows to contol current Wasm memory to inspect.
|
||||
/// Notice that "set_vmctx_memory" is an external/builtin subprogram that
|
||||
/// is not part of Wasm code.
|
||||
pub(crate) fn add_internal_types(
|
||||
comp_unit: &mut write::Unit,
|
||||
root_id: write::UnitEntryId,
|
||||
out_strings: &mut write::StringTable,
|
||||
module_info: &ModuleVmctxInfo,
|
||||
) -> (write::UnitEntryId, write::UnitEntryId) {
|
||||
let wp_die_id = comp_unit.add(root_id, gimli::DW_TAG_base_type);
|
||||
let wp_die = comp_unit.get_mut(wp_die_id);
|
||||
wp_die.set(
|
||||
gimli::DW_AT_name,
|
||||
write::AttributeValue::StringRef(out_strings.add("WebAssemblyPtr")),
|
||||
);
|
||||
wp_die.set(gimli::DW_AT_byte_size, write::AttributeValue::Data1(4));
|
||||
wp_die.set(
|
||||
gimli::DW_AT_encoding,
|
||||
write::AttributeValue::Encoding(gimli::DW_ATE_unsigned),
|
||||
);
|
||||
const WASM_PTR_LEN: u8 = 4;
|
||||
|
||||
let memory_byte_die_id = comp_unit.add(root_id, gimli::DW_TAG_base_type);
|
||||
let memory_byte_die = comp_unit.get_mut(memory_byte_die_id);
|
||||
memory_byte_die.set(
|
||||
gimli::DW_AT_name,
|
||||
write::AttributeValue::StringRef(out_strings.add("u8")),
|
||||
);
|
||||
memory_byte_die.set(
|
||||
gimli::DW_AT_encoding,
|
||||
write::AttributeValue::Encoding(gimli::DW_ATE_unsigned),
|
||||
);
|
||||
memory_byte_die.set(gimli::DW_AT_byte_size, write::AttributeValue::Data1(1));
|
||||
macro_rules! add_tag {
|
||||
($parent_id:ident, $tag:expr => $die:ident as $die_id:ident { $($a:path = $v:expr),* }) => {
|
||||
let $die_id = comp_unit.add($parent_id, $tag);
|
||||
let $die = comp_unit.get_mut($die_id);
|
||||
$( $die.set($a, $v); )*
|
||||
};
|
||||
}
|
||||
|
||||
let memory_bytes_die_id = comp_unit.add(root_id, gimli::DW_TAG_pointer_type);
|
||||
let memory_bytes_die = comp_unit.get_mut(memory_bytes_die_id);
|
||||
memory_bytes_die.set(
|
||||
gimli::DW_AT_name,
|
||||
write::AttributeValue::StringRef(out_strings.add("u8*")),
|
||||
);
|
||||
memory_bytes_die.set(
|
||||
gimli::DW_AT_type,
|
||||
write::AttributeValue::ThisUnitEntryRef(memory_byte_die_id),
|
||||
);
|
||||
// Build DW_TAG_base_type for generic `WebAssemblyPtr`.
|
||||
// .. DW_AT_name = "WebAssemblyPtr"
|
||||
// .. DW_AT_byte_size = 4
|
||||
// .. DW_AT_encoding = DW_ATE_unsigned
|
||||
// let wp_die_id = comp_unit.add(root_id, gimli::DW_TAG_base_type);
|
||||
// let wp_die = comp_unit.get_mut(wp_die_id);
|
||||
add_tag!(root_id, gimli::DW_TAG_base_type => wp_die as wp_die_id {
|
||||
gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("WebAssemblyPtr")),
|
||||
gimli::DW_AT_byte_size = write::AttributeValue::Data1(WASM_PTR_LEN),
|
||||
gimli::DW_AT_encoding = write::AttributeValue::Encoding(gimli::DW_ATE_unsigned)
|
||||
});
|
||||
|
||||
// Build DW_TAG_base_type for Wasm byte:
|
||||
// .. DW_AT_name = u8
|
||||
// .. DW_AT_encoding = DW_ATE_unsigned
|
||||
// .. DW_AT_byte_size = 1
|
||||
add_tag!(root_id, gimli::DW_TAG_base_type => memory_byte_die as memory_byte_die_id {
|
||||
gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("u8")),
|
||||
gimli::DW_AT_encoding = write::AttributeValue::Encoding(gimli::DW_ATE_unsigned),
|
||||
gimli::DW_AT_byte_size = write::AttributeValue::Data1(1)
|
||||
});
|
||||
|
||||
// Build DW_TAG_pointer_type that references Wasm bytes:
|
||||
// .. DW_AT_name = "u8*"
|
||||
// .. DW_AT_type = <memory_byte_die>
|
||||
add_tag!(root_id, gimli::DW_TAG_pointer_type => memory_bytes_die as memory_bytes_die_id {
|
||||
gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("u8*")),
|
||||
gimli::DW_AT_type = write::AttributeValue::ThisUnitEntryRef(memory_byte_die_id)
|
||||
});
|
||||
|
||||
// Create artificial VMContext type and its reference for convinience viewing
|
||||
// its fields (such as memory ref) in a debugger.
|
||||
// its fields (such as memory ref) in a debugger. Build DW_TAG_structure_type:
|
||||
// .. DW_AT_name = "WasmtimeVMContext"
|
||||
let vmctx_die_id = comp_unit.add(root_id, gimli::DW_TAG_structure_type);
|
||||
let vmctx_die = comp_unit.get_mut(vmctx_die_id);
|
||||
vmctx_die.set(
|
||||
@@ -56,6 +69,7 @@ pub(crate) fn add_internal_types(
|
||||
write::AttributeValue::StringRef(out_strings.add("WasmtimeVMContext")),
|
||||
);
|
||||
|
||||
// TODO multiple memories
|
||||
match module_info.memory_offset {
|
||||
ModuleMemoryOffset::Defined(memory_offset) => {
|
||||
// The context has defined memory: extend the WasmtimeVMContext size
|
||||
@@ -67,20 +81,15 @@ pub(crate) fn add_internal_types(
|
||||
);
|
||||
|
||||
// Define the "memory" field which is a direct pointer to allocated Wasm memory.
|
||||
let m_die_id = comp_unit.add(vmctx_die_id, gimli::DW_TAG_member);
|
||||
let m_die = comp_unit.get_mut(m_die_id);
|
||||
m_die.set(
|
||||
gimli::DW_AT_name,
|
||||
write::AttributeValue::StringRef(out_strings.add("memory")),
|
||||
);
|
||||
m_die.set(
|
||||
gimli::DW_AT_type,
|
||||
write::AttributeValue::ThisUnitEntryRef(memory_bytes_die_id),
|
||||
);
|
||||
m_die.set(
|
||||
gimli::DW_AT_data_member_location,
|
||||
write::AttributeValue::Udata(memory_offset as u64),
|
||||
);
|
||||
// Build DW_TAG_member:
|
||||
// .. DW_AT_name = "memory"
|
||||
// .. DW_AT_type = <memory_bytes_die>
|
||||
// .. DW_AT_data_member_location = `memory_offset`
|
||||
add_tag!(vmctx_die_id, gimli::DW_TAG_member => m_die as m_die_id {
|
||||
gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("memory")),
|
||||
gimli::DW_AT_type = write::AttributeValue::ThisUnitEntryRef(memory_bytes_die_id),
|
||||
gimli::DW_AT_data_member_location = write::AttributeValue::Udata(memory_offset as u64)
|
||||
});
|
||||
}
|
||||
ModuleMemoryOffset::Imported(_) => {
|
||||
// TODO implement convinience pointer to and additional types for VMMemoryImport.
|
||||
@@ -88,16 +97,28 @@ pub(crate) fn add_internal_types(
|
||||
ModuleMemoryOffset::None => (),
|
||||
}
|
||||
|
||||
let vmctx_ptr_die_id = comp_unit.add(root_id, gimli::DW_TAG_pointer_type);
|
||||
let vmctx_ptr_die = comp_unit.get_mut(vmctx_ptr_die_id);
|
||||
vmctx_ptr_die.set(
|
||||
gimli::DW_AT_name,
|
||||
write::AttributeValue::StringRef(out_strings.add("WasmtimeVMContext*")),
|
||||
);
|
||||
vmctx_ptr_die.set(
|
||||
gimli::DW_AT_type,
|
||||
write::AttributeValue::ThisUnitEntryRef(vmctx_die_id),
|
||||
);
|
||||
// Build DW_TAG_pointer_type for `WasmtimeVMContext*`:
|
||||
// .. DW_AT_name = "WasmtimeVMContext*"
|
||||
// .. DW_AT_type = <vmctx_die>
|
||||
add_tag!(root_id, gimli::DW_TAG_pointer_type => vmctx_ptr_die as vmctx_ptr_die_id {
|
||||
gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("WasmtimeVMContext*")),
|
||||
gimli::DW_AT_type = write::AttributeValue::ThisUnitEntryRef(vmctx_die_id)
|
||||
});
|
||||
|
||||
// Build vmctx_die's DW_TAG_subprogram for `set` method:
|
||||
// .. DW_AT_linkage_name = "set_vmctx_memory"
|
||||
// .. DW_AT_name = "set"
|
||||
// .. DW_TAG_formal_parameter
|
||||
// .. .. DW_AT_type = <vmctx_ptr_die>
|
||||
// .. .. DW_AT_artificial = 1
|
||||
add_tag!(vmctx_die_id, gimli::DW_TAG_subprogram => vmctx_set as vmctx_set_id {
|
||||
gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("set_vmctx_memory")),
|
||||
gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("set"))
|
||||
});
|
||||
add_tag!(vmctx_set_id, gimli::DW_TAG_formal_parameter => vmctx_set_this_param as vmctx_set_this_param_id {
|
||||
gimli::DW_AT_type = write::AttributeValue::ThisUnitEntryRef(vmctx_ptr_die_id),
|
||||
gimli::DW_AT_artificial = write::AttributeValue::Flag(true)
|
||||
});
|
||||
|
||||
(wp_die_id, vmctx_ptr_die_id)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user