Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/cranelift/src/debug/transform/mod.rs
3068 views
1
use self::debug_transform_logging::dbi_log;
2
use self::simulate::generate_simulated_dwarf;
3
use self::unit::clone_unit;
4
use crate::debug::Compilation;
5
use crate::debug::gc::build_dependencies;
6
use cranelift_codegen::isa::TargetIsa;
7
use gimli::{DwarfPackage, LittleEndian, Section, write};
8
use std::collections::HashSet;
9
use synthetic::ModuleSyntheticUnit;
10
use wasmtime_environ::error::Error;
11
use wasmtime_environ::{
12
DefinedFuncIndex, ModuleTranslation, PrimaryMap, StaticModuleIndex, Tunables, prelude::*,
13
};
14
15
pub use address_transform::AddressTransform;
16
17
mod address_transform;
18
mod attr;
19
mod debug_transform_logging;
20
mod expression;
21
mod line_program;
22
mod range_info_builder;
23
mod simulate;
24
mod synthetic;
25
mod unit;
26
mod utils;
27
28
impl<'a> Compilation<'a> {
29
fn function_frame_info(
30
&mut self,
31
module: StaticModuleIndex,
32
func: DefinedFuncIndex,
33
) -> expression::FunctionFrameInfo<'a> {
34
let (_, func) = self.function(module, func);
35
36
expression::FunctionFrameInfo {
37
value_ranges: &func.value_labels_ranges,
38
memory_offset: self.module_memory_offsets[module].clone(),
39
}
40
}
41
}
42
43
fn load_dwp<'data>(
44
translation: ModuleTranslation<'data>,
45
buffer: &'data [u8],
46
) -> Result<DwarfPackage<gimli::EndianSlice<'data, gimli::LittleEndian>>> {
47
let endian_slice = gimli::EndianSlice::new(buffer, LittleEndian);
48
49
let dwarf_package = DwarfPackage::load(
50
|id| -> Result<_> {
51
let slice = match id {
52
gimli::SectionId::DebugAbbrev => {
53
translation.debuginfo.dwarf.debug_abbrev.reader().slice()
54
}
55
gimli::SectionId::DebugInfo => {
56
translation.debuginfo.dwarf.debug_info.reader().slice()
57
}
58
gimli::SectionId::DebugLine => {
59
translation.debuginfo.dwarf.debug_line.reader().slice()
60
}
61
gimli::SectionId::DebugStr => {
62
translation.debuginfo.dwarf.debug_str.reader().slice()
63
}
64
gimli::SectionId::DebugStrOffsets => translation
65
.debuginfo
66
.dwarf
67
.debug_str_offsets
68
.reader()
69
.slice(),
70
gimli::SectionId::DebugLoc => translation.debuginfo.debug_loc.reader().slice(),
71
gimli::SectionId::DebugLocLists => {
72
translation.debuginfo.debug_loclists.reader().slice()
73
}
74
gimli::SectionId::DebugRngLists => {
75
translation.debuginfo.debug_rnglists.reader().slice()
76
}
77
gimli::SectionId::DebugTypes => {
78
translation.debuginfo.dwarf.debug_types.reader().slice()
79
}
80
gimli::SectionId::DebugCuIndex => {
81
translation.debuginfo.debug_cu_index.reader().slice()
82
}
83
gimli::SectionId::DebugTuIndex => {
84
translation.debuginfo.debug_tu_index.reader().slice()
85
}
86
_ => &buffer,
87
};
88
89
Ok(gimli::EndianSlice::new(slice, gimli::LittleEndian))
90
},
91
endian_slice,
92
)?;
93
94
Ok(dwarf_package)
95
}
96
97
/// Attempts to load a DWARF package using the passed bytes.
98
fn read_dwarf_package_from_bytes<'data>(
99
dwp_bytes: &'data [u8],
100
buffer: &'data [u8],
101
tunables: &Tunables,
102
) -> Option<DwarfPackage<gimli::EndianSlice<'data, gimli::LittleEndian>>> {
103
let mut validator = wasmparser::Validator::new();
104
let parser = wasmparser::Parser::new(0);
105
let mut types = wasmtime_environ::ModuleTypesBuilder::new(&validator);
106
let translation = match wasmtime_environ::ModuleEnvironment::new(
107
tunables,
108
&mut validator,
109
&mut types,
110
StaticModuleIndex::from_u32(0),
111
)
112
.translate(parser, dwp_bytes)
113
{
114
Ok(translation) => translation,
115
Err(e) => {
116
log::warn!("failed to parse wasm dwarf package: {e:?}");
117
return None;
118
}
119
};
120
121
match load_dwp(translation, buffer) {
122
Ok(package) => Some(package),
123
Err(err) => {
124
log::warn!("Failed to load Dwarf package {err}");
125
None
126
}
127
}
128
}
129
130
pub fn transform_dwarf(
131
isa: &dyn TargetIsa,
132
compilation: &mut Compilation<'_>,
133
) -> Result<write::Dwarf, Error> {
134
dbi_log!("Commencing DWARF transform for {:?}", compilation);
135
136
let mut transforms = PrimaryMap::new();
137
for (i, _) in compilation.translations.iter() {
138
transforms.push(AddressTransform::new(compilation, i));
139
}
140
141
let buffer = Vec::new();
142
143
let dwarf_package = compilation
144
.dwarf_package_bytes
145
.map(
146
|bytes| -> Option<DwarfPackage<gimli::EndianSlice<'_, gimli::LittleEndian>>> {
147
read_dwarf_package_from_bytes(bytes, &buffer, compilation.tunables)
148
},
149
)
150
.flatten();
151
152
let out_encoding = gimli::Encoding {
153
format: gimli::Format::Dwarf32,
154
version: 4, // TODO: this should be configurable
155
address_size: isa.pointer_bytes(),
156
};
157
let mut out_dwarf = write::Dwarf::default();
158
159
let mut vmctx_ptr_die_refs = PrimaryMap::new();
160
161
let mut translated = HashSet::new();
162
163
for (module, translation) in compilation.translations.iter() {
164
dbi_log!("[== Transforming CUs for module #{} ==]", module.as_u32());
165
166
let addr_tr = &transforms[module];
167
let di = &translation.debuginfo;
168
169
let out_module_synthetic_unit = ModuleSyntheticUnit::new(
170
module,
171
compilation,
172
out_encoding,
173
&mut out_dwarf.units,
174
&mut out_dwarf.strings,
175
);
176
// TODO-DebugInfo-Cleanup: move the simulation code to be per-module and delete this map.
177
vmctx_ptr_die_refs.push(out_module_synthetic_unit.vmctx_ptr_die_ref());
178
179
let mut filter = write::FilterUnitSection::new(&di.dwarf)?;
180
build_dependencies(&mut filter, addr_tr)?;
181
let mut convert = out_dwarf.convert_with_filter(filter)?;
182
while let Some((mut unit, root_entry)) = convert.read_unit()? {
183
if let Some(dwp) = dwarf_package.as_ref()
184
&& let Some(dwo_id) = unit.read_unit.dwo_id
185
&& let Ok(Some(split_dwarf)) = dwp.find_cu(dwo_id, unit.read_unit.dwarf)
186
{
187
let mut split_filter =
188
write::FilterUnitSection::new_split(&split_dwarf, unit.read_unit)?;
189
build_dependencies(&mut split_filter, addr_tr)?;
190
let mut convert_split = unit.convert_split_with_filter(split_filter)?;
191
let (mut split_unit, split_root_entry) = convert_split.read_unit()?;
192
split_unit.unit.set_encoding(out_encoding);
193
clone_unit(
194
compilation,
195
module,
196
&mut split_unit,
197
&split_root_entry,
198
Some(&root_entry),
199
&addr_tr,
200
&out_module_synthetic_unit,
201
&mut translated,
202
isa,
203
)?;
204
} else {
205
unit.unit.set_encoding(out_encoding);
206
clone_unit(
207
compilation,
208
module,
209
&mut unit,
210
&root_entry,
211
None,
212
&addr_tr,
213
&out_module_synthetic_unit,
214
&mut translated,
215
isa,
216
)?;
217
}
218
}
219
}
220
221
generate_simulated_dwarf(
222
compilation,
223
&transforms,
224
&translated,
225
out_encoding,
226
&vmctx_ptr_die_refs,
227
&mut out_dwarf.units,
228
&mut out_dwarf.strings,
229
isa,
230
)?;
231
232
Ok(out_dwarf)
233
}
234
235