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