1 use super::address_transform::AddressTransform; 2 use crate::debug::Reader; 3 use gimli::write; 4 use wasmtime_environ::error::Error; 5 6 pub(crate) fn clone_line_program( 7 mut transform: write::ConvertLineProgram<'_, Reader<'_>>, 8 addr_tr: &AddressTransform, 9 ) -> Result<(write::LineProgram, Vec<write::FileId>), Error> { 10 while let Some(write::ConvertLineSequence { 11 start, 12 rows: saved_rows, 13 .. 14 }) = transform.read_sequence()? 15 { 16 let Some(start) = start else { 17 continue; 18 }; 19 if start == 0 { 20 continue; 21 } 22 let Some(index) = addr_tr.find_func_index(start) else { 23 // Some non-existent address found. 24 continue; 25 }; 26 let Some(map) = addr_tr.map().get(index) else { 27 continue; // no code generated 28 }; 29 let symbol = map.symbol; 30 let base_addr = map.offset; 31 transform.begin_sequence(Some(write::Address::Symbol { symbol, addend: 0 })); 32 // TODO track and place function declaration line here 33 let mut last_address = None; 34 for addr_map in map.addresses.iter() { 35 let Some(wasm_offset) = addr_map.wasm.checked_sub(start) else { 36 continue; 37 }; 38 let mut saved_row = 39 match saved_rows.binary_search_by_key(&wasm_offset, |i| i.address_offset) { 40 Ok(i) => saved_rows[i], 41 Err(i) => { 42 if i > 0 { 43 saved_rows[i - 1] 44 } else { 45 continue; 46 } 47 } 48 }; 49 // Ignore duplicates 50 if Some(saved_row.address_offset) != last_address { 51 let address_offset = if last_address.is_none() { 52 // Extend first entry to the function declaration 53 // TODO use the function declaration line instead 54 0 55 } else { 56 (addr_map.generated - base_addr) as u64 57 }; 58 last_address = Some(saved_row.address_offset); 59 saved_row.address_offset = address_offset; 60 transform.generate_row(saved_row); 61 } 62 } 63 transform.end_sequence(map.len as u64); 64 } 65 let (out_program, files) = transform.program(); 66 Ok((out_program, files)) 67 } 68