wasmtime_cranelift/debug/transform/
mod.rs1use self::refs::DebugInfoRefsMap;
2use self::simulate::generate_simulated_dwarf;
3use self::unit::clone_unit;
4use crate::debug::gc::build_dependencies;
5use crate::debug::ModuleMemoryOffset;
6use crate::CompiledFunctions;
7use anyhow::Error;
8use cranelift_codegen::isa::TargetIsa;
9use gimli::{
10 write, DebugAddr, DebugLine, DebugLineStr, DebugStr, DebugStrOffsets, LocationLists,
11 RangeLists, UnitSectionOffset,
12};
13use std::collections::HashSet;
14use thiserror::Error;
15use wasmtime_environ::DebugInfoData;
16
17pub use address_transform::AddressTransform;
18
19mod address_transform;
20mod attr;
21mod expression;
22mod line_program;
23mod range_info_builder;
24mod refs;
25mod simulate;
26mod unit;
27mod utils;
28
29pub(crate) trait Reader: gimli::Reader<Offset = usize> {}
30
31impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian> where Endian: gimli::Endianity {}
32
33#[derive(Error, Debug)]
34#[error("Debug info transform error: {0}")]
35pub struct TransformError(&'static str);
36
37pub(crate) struct DebugInputContext<'a, R>
38where
39 R: Reader,
40{
41 debug_str: &'a DebugStr<R>,
42 debug_str_offsets: &'a DebugStrOffsets<R>,
43 debug_line_str: &'a DebugLineStr<R>,
44 debug_line: &'a DebugLine<R>,
45 debug_addr: &'a DebugAddr<R>,
46 rnglists: &'a RangeLists<R>,
47 loclists: &'a LocationLists<R>,
48 reachable: &'a HashSet<UnitSectionOffset>,
49}
50
51pub fn transform_dwarf(
52 isa: &dyn TargetIsa,
53 di: &DebugInfoData,
54 funcs: &CompiledFunctions,
55 memory_offset: &ModuleMemoryOffset,
56) -> Result<write::Dwarf, Error> {
57 let addr_tr = AddressTransform::new(funcs, &di.wasm_file);
58 let reachable = build_dependencies(&di.dwarf, &addr_tr)?.get_reachable();
59
60 let context = DebugInputContext {
61 debug_str: &di.dwarf.debug_str,
62 debug_str_offsets: &di.dwarf.debug_str_offsets,
63 debug_line_str: &di.dwarf.debug_line_str,
64 debug_line: &di.dwarf.debug_line,
65 debug_addr: &di.dwarf.debug_addr,
66 rnglists: &di.dwarf.ranges,
67 loclists: &di.dwarf.locations,
68 reachable: &reachable,
69 };
70
71 let out_encoding = gimli::Encoding {
72 format: gimli::Format::Dwarf32,
73 version: 4,
75 address_size: isa.pointer_bytes(),
76 };
77
78 let mut out_strings = write::StringTable::default();
79 let mut out_units = write::UnitTable::default();
80
81 let out_line_strings = write::LineStringTable::default();
82 let mut pending_di_refs = Vec::new();
83 let mut di_ref_map = DebugInfoRefsMap::new();
84
85 let mut translated = HashSet::new();
86 let mut iter = di.dwarf.debug_info.units();
87 while let Some(header) = iter.next().unwrap_or(None) {
88 let unit = di.dwarf.unit(header)?;
89 if let Some((id, ref_map, pending_refs)) = clone_unit(
90 &di.dwarf,
91 unit,
92 &context,
93 &addr_tr,
94 funcs,
95 memory_offset,
96 out_encoding,
97 &mut out_units,
98 &mut out_strings,
99 &mut translated,
100 isa,
101 )? {
102 di_ref_map.insert(&header, id, ref_map);
103 pending_di_refs.push((id, pending_refs));
104 }
105 }
106 di_ref_map.patch(pending_di_refs.into_iter(), &mut out_units);
107
108 generate_simulated_dwarf(
109 &addr_tr,
110 di,
111 memory_offset,
112 funcs,
113 &translated,
114 out_encoding,
115 &mut out_units,
116 &mut out_strings,
117 isa,
118 )?;
119
120 Ok(write::Dwarf {
121 units: out_units,
122 line_programs: vec![],
123 line_strings: out_line_strings,
124 strings: out_strings,
125 })
126}