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