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::debug::ModuleMemoryOffset; 6 use crate::CompiledFunctions; 7 use anyhow::Error; 8 use cranelift_codegen::isa::TargetIsa; 9 use gimli::{ 10 write, DebugAddr, DebugLine, DebugLineStr, DebugStr, DebugStrOffsets, LocationLists, 11 RangeLists, UnitSectionOffset, 12 }; 13 use std::collections::HashSet; 14 use thiserror::Error; 15 use wasmtime_environ::DebugInfoData; 16 17 pub use address_transform::AddressTransform; 18 19 mod address_transform; 20 mod attr; 21 mod expression; 22 mod line_program; 23 mod range_info_builder; 24 mod refs; 25 mod simulate; 26 mod unit; 27 mod utils; 28 29 pub(crate) trait Reader: gimli::Reader<Offset = usize> {} 30 31 impl<'input, Endian> Reader for gimli::EndianSlice<'input, Endian> where Endian: gimli::Endianity {} 32 33 #[derive(Error, Debug)] 34 #[error("Debug info transform error: {0}")] 35 pub struct TransformError(&'static str); 36 37 pub(crate) struct DebugInputContext<'a, R> 38 where 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 51 pub 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 // TODO: this should be configurable 74 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 } 127