wasmtime_internal_cranelift/debug/transform/
synthetic.rs1use gimli::write::{
2 AttributeValue, LineProgram, Reference, StringTable, Unit, UnitEntryId, UnitId, UnitTable,
3};
4use wasmtime_environ::StaticModuleIndex;
5use wasmtime_versioned_export_macros::versioned_stringify_ident;
6
7use crate::debug::{Compilation, ModuleMemoryOffset};
8
9pub struct ModuleSyntheticUnit {
19 unit_id: UnitId,
20 vmctx_ptr_die_id: UnitEntryId,
21 wasm_ptr_die_id: UnitEntryId,
22}
23
24macro_rules! add_tag {
25 ($unit:ident, $parent_id:ident, $tag:expr => $die:ident as $die_id:ident { $($a:path = $v:expr),* }) => {
26 let $die_id = $unit.add($parent_id, $tag);
27 let $die = $unit.get_mut($die_id);
28 $( $die.set($a, $v); )*
29 };
30}
31
32impl ModuleSyntheticUnit {
33 pub fn new(
34 module: StaticModuleIndex,
35 compilation: &Compilation<'_>,
36 encoding: gimli::Encoding,
37 out_units: &mut UnitTable,
38 out_strings: &mut StringTable,
39 ) -> Self {
40 let unit_id = Self::create_unit(encoding, out_units, out_strings);
41 let unit = out_units.get_mut(unit_id);
42 let vmctx_ptr_die_id = Self::create_vmctx_ptr_die(module, compilation, unit, out_strings);
43 let wasm_ptr_die_id = Self::create_wasm_ptr_die(unit, out_strings);
44
45 Self {
46 unit_id,
47 vmctx_ptr_die_id,
48 wasm_ptr_die_id,
49 }
50 }
51
52 pub fn vmctx_ptr_die_ref(&self) -> Reference {
53 Reference::Entry(self.unit_id, self.vmctx_ptr_die_id)
54 }
55
56 pub fn wasm_ptr_die_ref(&self) -> Reference {
57 Reference::Entry(self.unit_id, self.wasm_ptr_die_id)
58 }
59
60 fn create_unit(
61 encoding: gimli::Encoding,
62 out_units: &mut UnitTable,
63 out_strings: &mut StringTable,
64 ) -> UnitId {
65 let unit_id = out_units.add(Unit::new(encoding, LineProgram::none()));
66 let unit = out_units.get_mut(unit_id);
67 let unit_die = unit.get_mut(unit.root());
68 unit_die.set(
69 gimli::DW_AT_name,
70 AttributeValue::StringRef(out_strings.add("WasmtimeModuleSyntheticUnit")),
71 );
72 unit_die.set(
73 gimli::DW_AT_producer,
74 AttributeValue::StringRef(out_strings.add("wasmtime")),
75 );
76 unit_die.set(
77 gimli::DW_AT_language,
78 AttributeValue::Language(gimli::DW_LANG_C11),
79 );
80 unit_id
81 }
82
83 fn create_vmctx_ptr_die(
84 module: StaticModuleIndex,
85 compilation: &Compilation<'_>,
86 unit: &mut Unit,
87 out_strings: &mut StringTable,
88 ) -> UnitEntryId {
89 let root_id = unit.root();
94 add_tag!(unit, root_id, gimli::DW_TAG_base_type => memory_byte_die as memory_byte_die_id {
95 gimli::DW_AT_name = AttributeValue::StringRef(out_strings.add("u8")),
96 gimli::DW_AT_encoding = AttributeValue::Encoding(gimli::DW_ATE_unsigned),
97 gimli::DW_AT_byte_size = AttributeValue::Data1(1)
98 });
99
100 add_tag!(unit, root_id, gimli::DW_TAG_pointer_type => memory_bytes_die as memory_bytes_die_id {
104 gimli::DW_AT_name = AttributeValue::StringRef(out_strings.add("u8*")),
105 gimli::DW_AT_type = AttributeValue::UnitRef(memory_byte_die_id)
106 });
107
108 let vmctx_die_id = unit.add(root_id, gimli::DW_TAG_structure_type);
112 let vmctx_die = unit.get_mut(vmctx_die_id);
113 vmctx_die.set(
114 gimli::DW_AT_name,
115 AttributeValue::StringRef(out_strings.add("WasmtimeVMContext")),
116 );
117
118 match compilation.module_memory_offsets[module] {
120 ModuleMemoryOffset::Defined(memory_offset) => {
121 const MEMORY_FIELD_SIZE_PLUS_PADDING: u32 = 8;
124 vmctx_die.set(
125 gimli::DW_AT_byte_size,
126 AttributeValue::Data4(memory_offset + MEMORY_FIELD_SIZE_PLUS_PADDING),
127 );
128
129 add_tag!(unit, vmctx_die_id, gimli::DW_TAG_member => m_die as m_die_id {
135 gimli::DW_AT_name = AttributeValue::StringRef(out_strings.add("memory")),
136 gimli::DW_AT_type = AttributeValue::UnitRef(memory_bytes_die_id),
137 gimli::DW_AT_data_member_location = AttributeValue::Udata(memory_offset as u64)
138 });
139 }
140 ModuleMemoryOffset::Imported { .. } => {
141 }
143 ModuleMemoryOffset::None => (),
144 }
145
146 add_tag!(unit, root_id, gimli::DW_TAG_pointer_type => vmctx_ptr_die as vmctx_ptr_die_id {
150 gimli::DW_AT_name = AttributeValue::StringRef(out_strings.add("WasmtimeVMContext*")),
151 gimli::DW_AT_type = AttributeValue::UnitRef(vmctx_die_id)
152 });
153
154 add_tag!(unit, vmctx_die_id, gimli::DW_TAG_subprogram => vmctx_set as vmctx_set_id {
161 gimli::DW_AT_linkage_name = AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(wasmtime_set_vmctx_memory))),
162 gimli::DW_AT_name = AttributeValue::StringRef(out_strings.add("set"))
163 });
164 add_tag!(unit, vmctx_set_id, gimli::DW_TAG_formal_parameter => vmctx_set_this_param as vmctx_set_this_param_id {
165 gimli::DW_AT_type = AttributeValue::UnitRef(vmctx_ptr_die_id),
166 gimli::DW_AT_artificial = AttributeValue::Flag(true)
167 });
168
169 vmctx_ptr_die_id
170 }
171
172 fn create_wasm_ptr_die(unit: &mut Unit, out_strings: &mut StringTable) -> UnitEntryId {
173 const WASM_PTR_LEN: u8 = 4;
178 let root_id = unit.root();
179 add_tag!(unit, root_id, gimli::DW_TAG_base_type => wp_die as wp_die_id {
180 gimli::DW_AT_name = AttributeValue::StringRef(out_strings.add("WebAssemblyPtr")),
181 gimli::DW_AT_byte_size = AttributeValue::Data1(WASM_PTR_LEN),
182 gimli::DW_AT_encoding = AttributeValue::Encoding(gimli::DW_ATE_unsigned)
183 });
184
185 wp_die_id
186 }
187}