wasmtime_cranelift/debug/transform/
utils.rs1use super::address_transform::AddressTransform;
2use super::expression::{CompiledExpression, FunctionFrameInfo};
3use crate::debug::ModuleMemoryOffset;
4use crate::CompiledFunctions;
5use anyhow::Error;
6use cranelift_codegen::isa::TargetIsa;
7use gimli::write;
8use wasmtime_environ::DefinedFuncIndex;
9
10pub(crate) fn add_internal_types(
18 comp_unit: &mut write::Unit,
19 root_id: write::UnitEntryId,
20 out_strings: &mut write::StringTable,
21 memory_offset: &ModuleMemoryOffset,
22) -> (write::UnitEntryId, write::UnitEntryId) {
23 const WASM_PTR_LEN: u8 = 4;
24
25 macro_rules! add_tag {
26 ($parent_id:ident, $tag:expr => $die:ident as $die_id:ident { $($a:path = $v:expr),* }) => {
27 let $die_id = comp_unit.add($parent_id, $tag);
28 let $die = comp_unit.get_mut($die_id);
29 $( $die.set($a, $v); )*
30 };
31 }
32
33 add_tag!(root_id, gimli::DW_TAG_base_type => wp_die as wp_die_id {
40 gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("WebAssemblyPtr")),
41 gimli::DW_AT_byte_size = write::AttributeValue::Data1(WASM_PTR_LEN),
42 gimli::DW_AT_encoding = write::AttributeValue::Encoding(gimli::DW_ATE_unsigned)
43 });
44
45 add_tag!(root_id, gimli::DW_TAG_base_type => memory_byte_die as memory_byte_die_id {
50 gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("u8")),
51 gimli::DW_AT_encoding = write::AttributeValue::Encoding(gimli::DW_ATE_unsigned),
52 gimli::DW_AT_byte_size = write::AttributeValue::Data1(1)
53 });
54
55 add_tag!(root_id, gimli::DW_TAG_pointer_type => memory_bytes_die as memory_bytes_die_id {
59 gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("u8*")),
60 gimli::DW_AT_type = write::AttributeValue::UnitRef(memory_byte_die_id)
61 });
62
63 let vmctx_die_id = comp_unit.add(root_id, gimli::DW_TAG_structure_type);
67 let vmctx_die = comp_unit.get_mut(vmctx_die_id);
68 vmctx_die.set(
69 gimli::DW_AT_name,
70 write::AttributeValue::StringRef(out_strings.add("WasmtimeVMContext")),
71 );
72
73 match *memory_offset {
75 ModuleMemoryOffset::Defined(memory_offset) => {
76 const MEMORY_FIELD_SIZE_PLUS_PADDING: u32 = 8;
79 vmctx_die.set(
80 gimli::DW_AT_byte_size,
81 write::AttributeValue::Data4(memory_offset + MEMORY_FIELD_SIZE_PLUS_PADDING),
82 );
83
84 add_tag!(vmctx_die_id, gimli::DW_TAG_member => m_die as m_die_id {
90 gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("memory")),
91 gimli::DW_AT_type = write::AttributeValue::UnitRef(memory_bytes_die_id),
92 gimli::DW_AT_data_member_location = write::AttributeValue::Udata(memory_offset as u64)
93 });
94 }
95 ModuleMemoryOffset::Imported(_) => {
96 }
98 ModuleMemoryOffset::None => (),
99 }
100
101 add_tag!(root_id, gimli::DW_TAG_pointer_type => vmctx_ptr_die as vmctx_ptr_die_id {
105 gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("WasmtimeVMContext*")),
106 gimli::DW_AT_type = write::AttributeValue::UnitRef(vmctx_die_id)
107 });
108
109 add_tag!(vmctx_die_id, gimli::DW_TAG_subprogram => vmctx_set as vmctx_set_id {
116 gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("set_vmctx_memory")),
117 gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("set"))
118 });
119 add_tag!(vmctx_set_id, gimli::DW_TAG_formal_parameter => vmctx_set_this_param as vmctx_set_this_param_id {
120 gimli::DW_AT_type = write::AttributeValue::UnitRef(vmctx_ptr_die_id),
121 gimli::DW_AT_artificial = write::AttributeValue::Flag(true)
122 });
123
124 (wp_die_id, vmctx_ptr_die_id)
125}
126
127pub(crate) fn append_vmctx_info(
128 comp_unit: &mut write::Unit,
129 parent_id: write::UnitEntryId,
130 vmctx_die_id: write::UnitEntryId,
131 addr_tr: &AddressTransform,
132 frame_info: Option<&FunctionFrameInfo>,
133 scope_ranges: &[(u64, u64)],
134 out_strings: &mut write::StringTable,
135 isa: &dyn TargetIsa,
136) -> Result<(), Error> {
137 let loc = {
138 let expr = CompiledExpression::vmctx();
139 let locs = expr
140 .build_with_locals(scope_ranges, addr_tr, frame_info, isa)
141 .map(|i| {
142 i.map(|(begin, length, data)| write::Location::StartLength {
143 begin,
144 length,
145 data,
146 })
147 })
148 .collect::<Result<Vec<_>, _>>()?;
149 let list_id = comp_unit.locations.add(write::LocationList(locs));
150 write::AttributeValue::LocationListRef(list_id)
151 };
152
153 let var_die_id = comp_unit.add(parent_id, gimli::DW_TAG_variable);
154 let var_die = comp_unit.get_mut(var_die_id);
155 var_die.set(
156 gimli::DW_AT_name,
157 write::AttributeValue::StringRef(out_strings.add("__vmctx")),
158 );
159 var_die.set(
160 gimli::DW_AT_type,
161 write::AttributeValue::UnitRef(vmctx_die_id),
162 );
163 var_die.set(gimli::DW_AT_location, loc);
164
165 Ok(())
166}
167
168pub(crate) fn get_function_frame_info<'a, 'b, 'c>(
169 memory_offset: &ModuleMemoryOffset,
170 funcs: &'b CompiledFunctions,
171 func_index: DefinedFuncIndex,
172) -> Option<FunctionFrameInfo<'a>>
173where
174 'b: 'a,
175 'c: 'a,
176{
177 if let Some(func) = funcs.get(func_index) {
178 let frame_info = FunctionFrameInfo {
179 value_ranges: &func.value_labels_ranges,
180 memory_offset: memory_offset.clone(),
181 sized_stack_slots: &func.sized_stack_slots,
182 };
183 Some(frame_info)
184 } else {
185 None
186 }
187}