192cc0ad7SSingleAccretion use self::debug_transform_logging::dbi_log;
287c33c29SAlex Crichton use self::simulate::generate_simulated_dwarf;
387c33c29SAlex Crichton use self::unit::clone_unit;
4*c4a38d67SPhilip Craig use crate::debug::Compilation;
590ac295eSAlex Crichton use crate::debug::gc::build_dependencies;
687c33c29SAlex Crichton use cranelift_codegen::isa::TargetIsa;
7*c4a38d67SPhilip Craig use gimli::{DwarfPackage, LittleEndian, Section, write};
8*c4a38d67SPhilip Craig use std::collections::HashSet;
9af476a51SSingleAccretion use synthetic::ModuleSyntheticUnit;
10c7cab275SNick Fitzgerald use wasmtime_environ::error::Error;
11dd8c48b3SAlex Crichton use wasmtime_environ::{
12b5272a5fSNick Fitzgerald     DefinedFuncIndex, ModuleTranslation, PrimaryMap, StaticModuleIndex, Tunables, prelude::*,
13dd8c48b3SAlex Crichton };
1487c33c29SAlex Crichton 
1587c33c29SAlex Crichton pub use address_transform::AddressTransform;
1687c33c29SAlex Crichton 
1787c33c29SAlex Crichton mod address_transform;
1887c33c29SAlex Crichton mod attr;
1992cc0ad7SSingleAccretion mod debug_transform_logging;
2087c33c29SAlex Crichton mod expression;
2187c33c29SAlex Crichton mod line_program;
2287c33c29SAlex Crichton mod range_info_builder;
2387c33c29SAlex Crichton mod simulate;
24af476a51SSingleAccretion mod synthetic;
2587c33c29SAlex Crichton mod unit;
2687c33c29SAlex Crichton mod utils;
2787c33c29SAlex Crichton 
28dd8c48b3SAlex Crichton impl<'a> Compilation<'a> {
function_frame_info( &mut self, module: StaticModuleIndex, func: DefinedFuncIndex, ) -> expression::FunctionFrameInfo<'a>29dd8c48b3SAlex Crichton     fn function_frame_info(
30dd8c48b3SAlex Crichton         &mut self,
31dd8c48b3SAlex Crichton         module: StaticModuleIndex,
32dd8c48b3SAlex Crichton         func: DefinedFuncIndex,
33dd8c48b3SAlex Crichton     ) -> expression::FunctionFrameInfo<'a> {
34dd8c48b3SAlex Crichton         let (_, func) = self.function(module, func);
35dd8c48b3SAlex Crichton 
36dd8c48b3SAlex Crichton         expression::FunctionFrameInfo {
37dd8c48b3SAlex Crichton             value_ranges: &func.value_labels_ranges,
38dd8c48b3SAlex Crichton             memory_offset: self.module_memory_offsets[module].clone(),
39dd8c48b3SAlex Crichton         }
40dd8c48b3SAlex Crichton     }
41dd8c48b3SAlex Crichton }
42dd8c48b3SAlex Crichton 
load_dwp<'data>( translation: ModuleTranslation<'data>, buffer: &'data [u8], ) -> Result<DwarfPackage<gimli::EndianSlice<'data, gimli::LittleEndian>>>43fb4f4cd3Syowl fn load_dwp<'data>(
44fb4f4cd3Syowl     translation: ModuleTranslation<'data>,
45fb4f4cd3Syowl     buffer: &'data [u8],
46b5272a5fSNick Fitzgerald ) -> Result<DwarfPackage<gimli::EndianSlice<'data, gimli::LittleEndian>>> {
47fb4f4cd3Syowl     let endian_slice = gimli::EndianSlice::new(buffer, LittleEndian);
48fb4f4cd3Syowl 
49fb4f4cd3Syowl     let dwarf_package = DwarfPackage::load(
50b5272a5fSNick Fitzgerald         |id| -> Result<_> {
51fb4f4cd3Syowl             let slice = match id {
52fb4f4cd3Syowl                 gimli::SectionId::DebugAbbrev => {
53fb4f4cd3Syowl                     translation.debuginfo.dwarf.debug_abbrev.reader().slice()
54fb4f4cd3Syowl                 }
55fb4f4cd3Syowl                 gimli::SectionId::DebugInfo => {
56fb4f4cd3Syowl                     translation.debuginfo.dwarf.debug_info.reader().slice()
57fb4f4cd3Syowl                 }
58fb4f4cd3Syowl                 gimli::SectionId::DebugLine => {
59fb4f4cd3Syowl                     translation.debuginfo.dwarf.debug_line.reader().slice()
60fb4f4cd3Syowl                 }
61fb4f4cd3Syowl                 gimli::SectionId::DebugStr => {
62fb4f4cd3Syowl                     translation.debuginfo.dwarf.debug_str.reader().slice()
63fb4f4cd3Syowl                 }
64fb4f4cd3Syowl                 gimli::SectionId::DebugStrOffsets => translation
65fb4f4cd3Syowl                     .debuginfo
66fb4f4cd3Syowl                     .dwarf
67fb4f4cd3Syowl                     .debug_str_offsets
68fb4f4cd3Syowl                     .reader()
69fb4f4cd3Syowl                     .slice(),
70fb4f4cd3Syowl                 gimli::SectionId::DebugLoc => translation.debuginfo.debug_loc.reader().slice(),
71fb4f4cd3Syowl                 gimli::SectionId::DebugLocLists => {
72fb4f4cd3Syowl                     translation.debuginfo.debug_loclists.reader().slice()
73fb4f4cd3Syowl                 }
74fb4f4cd3Syowl                 gimli::SectionId::DebugRngLists => {
75fb4f4cd3Syowl                     translation.debuginfo.debug_rnglists.reader().slice()
76fb4f4cd3Syowl                 }
77fb4f4cd3Syowl                 gimli::SectionId::DebugTypes => {
78fb4f4cd3Syowl                     translation.debuginfo.dwarf.debug_types.reader().slice()
79fb4f4cd3Syowl                 }
80fb4f4cd3Syowl                 gimli::SectionId::DebugCuIndex => {
81fb4f4cd3Syowl                     translation.debuginfo.debug_cu_index.reader().slice()
82fb4f4cd3Syowl                 }
83fb4f4cd3Syowl                 gimli::SectionId::DebugTuIndex => {
84fb4f4cd3Syowl                     translation.debuginfo.debug_tu_index.reader().slice()
85fb4f4cd3Syowl                 }
86fb4f4cd3Syowl                 _ => &buffer,
87fb4f4cd3Syowl             };
88fb4f4cd3Syowl 
89fb4f4cd3Syowl             Ok(gimli::EndianSlice::new(slice, gimli::LittleEndian))
90fb4f4cd3Syowl         },
91fb4f4cd3Syowl         endian_slice,
92fb4f4cd3Syowl     )?;
93fb4f4cd3Syowl 
94fb4f4cd3Syowl     Ok(dwarf_package)
95fb4f4cd3Syowl }
96fb4f4cd3Syowl 
97fb4f4cd3Syowl /// Attempts to load a DWARF package using the passed bytes.
read_dwarf_package_from_bytes<'data>( dwp_bytes: &'data [u8], buffer: &'data [u8], tunables: &Tunables, ) -> Option<DwarfPackage<gimli::EndianSlice<'data, gimli::LittleEndian>>>98fb4f4cd3Syowl fn read_dwarf_package_from_bytes<'data>(
99fb4f4cd3Syowl     dwp_bytes: &'data [u8],
100fb4f4cd3Syowl     buffer: &'data [u8],
101fb4f4cd3Syowl     tunables: &Tunables,
102fb4f4cd3Syowl ) -> Option<DwarfPackage<gimli::EndianSlice<'data, gimli::LittleEndian>>> {
103fb4f4cd3Syowl     let mut validator = wasmparser::Validator::new();
104fb4f4cd3Syowl     let parser = wasmparser::Parser::new(0);
105fb4f4cd3Syowl     let mut types = wasmtime_environ::ModuleTypesBuilder::new(&validator);
106cfc05638SNick Fitzgerald     let translation = match wasmtime_environ::ModuleEnvironment::new(
107cfc05638SNick Fitzgerald         tunables,
108cfc05638SNick Fitzgerald         &mut validator,
109cfc05638SNick Fitzgerald         &mut types,
110cfc05638SNick Fitzgerald         StaticModuleIndex::from_u32(0),
111cfc05638SNick Fitzgerald     )
112fb4f4cd3Syowl     .translate(parser, dwp_bytes)
113fb4f4cd3Syowl     {
114fb4f4cd3Syowl         Ok(translation) => translation,
115fb4f4cd3Syowl         Err(e) => {
116fb4f4cd3Syowl             log::warn!("failed to parse wasm dwarf package: {e:?}");
117fb4f4cd3Syowl             return None;
118fb4f4cd3Syowl         }
119fb4f4cd3Syowl     };
120fb4f4cd3Syowl 
121fb4f4cd3Syowl     match load_dwp(translation, buffer) {
122fb4f4cd3Syowl         Ok(package) => Some(package),
123fb4f4cd3Syowl         Err(err) => {
1242bac6574SAlex Crichton             log::warn!("Failed to load Dwarf package {err}");
125fb4f4cd3Syowl             None
126fb4f4cd3Syowl         }
127fb4f4cd3Syowl     }
128fb4f4cd3Syowl }
129fb4f4cd3Syowl 
transform_dwarf( isa: &dyn TargetIsa, compilation: &mut Compilation<'_>, ) -> Result<write::Dwarf, Error>130f676c176SAlex Crichton pub fn transform_dwarf(
13187c33c29SAlex Crichton     isa: &dyn TargetIsa,
132dd8c48b3SAlex Crichton     compilation: &mut Compilation<'_>,
13387c33c29SAlex Crichton ) -> Result<write::Dwarf, Error> {
13492cc0ad7SSingleAccretion     dbi_log!("Commencing DWARF transform for {:?}", compilation);
13592cc0ad7SSingleAccretion 
136dd8c48b3SAlex Crichton     let mut transforms = PrimaryMap::new();
137dd8c48b3SAlex Crichton     for (i, _) in compilation.translations.iter() {
138dd8c48b3SAlex Crichton         transforms.push(AddressTransform::new(compilation, i));
139dd8c48b3SAlex Crichton     }
140fb4f4cd3Syowl 
141fb4f4cd3Syowl     let buffer = Vec::new();
142fb4f4cd3Syowl 
143dd8c48b3SAlex Crichton     let dwarf_package = compilation
144dd8c48b3SAlex Crichton         .dwarf_package_bytes
145fb4f4cd3Syowl         .map(
146fb4f4cd3Syowl             |bytes| -> Option<DwarfPackage<gimli::EndianSlice<'_, gimli::LittleEndian>>> {
147dd8c48b3SAlex Crichton                 read_dwarf_package_from_bytes(bytes, &buffer, compilation.tunables)
148fb4f4cd3Syowl             },
149fb4f4cd3Syowl         )
150fb4f4cd3Syowl         .flatten();
151fb4f4cd3Syowl 
15287c33c29SAlex Crichton     let out_encoding = gimli::Encoding {
15387c33c29SAlex Crichton         format: gimli::Format::Dwarf32,
154af476a51SSingleAccretion         version: 4, // TODO: this should be configurable
15587c33c29SAlex Crichton         address_size: isa.pointer_bytes(),
15687c33c29SAlex Crichton     };
157*c4a38d67SPhilip Craig     let mut out_dwarf = write::Dwarf::default();
15887c33c29SAlex Crichton 
159af476a51SSingleAccretion     let mut vmctx_ptr_die_refs = PrimaryMap::new();
16087c33c29SAlex Crichton 
16187c33c29SAlex Crichton     let mut translated = HashSet::new();
162dd8c48b3SAlex Crichton 
163dd8c48b3SAlex Crichton     for (module, translation) in compilation.translations.iter() {
16492cc0ad7SSingleAccretion         dbi_log!("[== Transforming CUs for module #{} ==]", module.as_u32());
16592cc0ad7SSingleAccretion 
166dd8c48b3SAlex Crichton         let addr_tr = &transforms[module];
167dd8c48b3SAlex Crichton         let di = &translation.debuginfo;
1684a722b89SPhilip Craig 
169af476a51SSingleAccretion         let out_module_synthetic_unit = ModuleSyntheticUnit::new(
170af476a51SSingleAccretion             module,
171af476a51SSingleAccretion             compilation,
172af476a51SSingleAccretion             out_encoding,
173*c4a38d67SPhilip Craig             &mut out_dwarf.units,
174*c4a38d67SPhilip Craig             &mut out_dwarf.strings,
175af476a51SSingleAccretion         );
1760b2c9d72SSingleAccretion         // TODO-DebugInfo-Cleanup: move the simulation code to be per-module and delete this map.
177af476a51SSingleAccretion         vmctx_ptr_die_refs.push(out_module_synthetic_unit.vmctx_ptr_die_ref());
178fb4f4cd3Syowl 
179*c4a38d67SPhilip Craig         let mut filter = write::FilterUnitSection::new(&di.dwarf)?;
180*c4a38d67SPhilip Craig         build_dependencies(&mut filter, addr_tr)?;
181*c4a38d67SPhilip Craig         let mut convert = out_dwarf.convert_with_filter(filter)?;
182*c4a38d67SPhilip Craig         while let Some((mut unit, root_entry)) = convert.read_unit()? {
183*c4a38d67SPhilip Craig             if let Some(dwp) = dwarf_package.as_ref()
184*c4a38d67SPhilip Craig                 && let Some(dwo_id) = unit.read_unit.dwo_id
185*c4a38d67SPhilip Craig                 && let Ok(Some(split_dwarf)) = dwp.find_cu(dwo_id, unit.read_unit.dwarf)
186fb4f4cd3Syowl             {
187*c4a38d67SPhilip Craig                 let mut split_filter =
188*c4a38d67SPhilip Craig                     write::FilterUnitSection::new_split(&split_dwarf, unit.read_unit)?;
189*c4a38d67SPhilip Craig                 build_dependencies(&mut split_filter, addr_tr)?;
190*c4a38d67SPhilip Craig                 let mut convert_split = unit.convert_split_with_filter(split_filter)?;
191*c4a38d67SPhilip Craig                 let (mut split_unit, split_root_entry) = convert_split.read_unit()?;
192*c4a38d67SPhilip Craig                 split_unit.unit.set_encoding(out_encoding);
193*c4a38d67SPhilip Craig                 clone_unit(
194dd8c48b3SAlex Crichton                     compilation,
195dd8c48b3SAlex Crichton                     module,
196*c4a38d67SPhilip Craig                     &mut split_unit,
197*c4a38d67SPhilip Craig                     &split_root_entry,
198*c4a38d67SPhilip Craig                     Some(&root_entry),
19987c33c29SAlex Crichton                     &addr_tr,
200af476a51SSingleAccretion                     &out_module_synthetic_unit,
20187c33c29SAlex Crichton                     &mut translated,
20287c33c29SAlex Crichton                     isa,
203*c4a38d67SPhilip Craig                 )?;
204*c4a38d67SPhilip Craig             } else {
205*c4a38d67SPhilip Craig                 unit.unit.set_encoding(out_encoding);
206*c4a38d67SPhilip Craig                 clone_unit(
207*c4a38d67SPhilip Craig                     compilation,
208*c4a38d67SPhilip Craig                     module,
209*c4a38d67SPhilip Craig                     &mut unit,
210*c4a38d67SPhilip Craig                     &root_entry,
211*c4a38d67SPhilip Craig                     None,
212*c4a38d67SPhilip Craig                     &addr_tr,
213*c4a38d67SPhilip Craig                     &out_module_synthetic_unit,
214*c4a38d67SPhilip Craig                     &mut translated,
215*c4a38d67SPhilip Craig                     isa,
216*c4a38d67SPhilip Craig                 )?;
21787c33c29SAlex Crichton             }
21887c33c29SAlex Crichton         }
219dd8c48b3SAlex Crichton     }
22087c33c29SAlex Crichton 
22187c33c29SAlex Crichton     generate_simulated_dwarf(
222dd8c48b3SAlex Crichton         compilation,
223dd8c48b3SAlex Crichton         &transforms,
22487c33c29SAlex Crichton         &translated,
22587c33c29SAlex Crichton         out_encoding,
226af476a51SSingleAccretion         &vmctx_ptr_die_refs,
227*c4a38d67SPhilip Craig         &mut out_dwarf.units,
228*c4a38d67SPhilip Craig         &mut out_dwarf.strings,
22987c33c29SAlex Crichton         isa,
23087c33c29SAlex Crichton     )?;
23187c33c29SAlex Crichton 
232*c4a38d67SPhilip Craig     Ok(out_dwarf)
233fb4f4cd3Syowl }
234