use super::address_transform::AddressTransform;
use crate::debug::Reader;
use gimli::write;
use wasmtime_environ::error::Error;
pub(crate) fn clone_line_program(
mut transform: write::ConvertLineProgram<'_, Reader<'_>>,
addr_tr: &AddressTransform,
) -> Result<(write::LineProgram, Vec<write::FileId>), Error> {
while let Some(write::ConvertLineSequence {
start,
rows: saved_rows,
..
}) = transform.read_sequence()?
{
let Some(start) = start else {
continue;
};
if start == 0 {
continue;
}
let Some(index) = addr_tr.find_func_index(start) else {
continue;
};
let Some(map) = addr_tr.map().get(index) else {
continue; };
let symbol = map.symbol;
let base_addr = map.offset;
transform.begin_sequence(Some(write::Address::Symbol { symbol, addend: 0 }));
let mut last_address = None;
for addr_map in map.addresses.iter() {
let Some(wasm_offset) = addr_map.wasm.checked_sub(start) else {
continue;
};
let mut saved_row =
match saved_rows.binary_search_by_key(&wasm_offset, |i| i.address_offset) {
Ok(i) => saved_rows[i],
Err(i) => {
if i > 0 {
saved_rows[i - 1]
} else {
continue;
}
}
};
if Some(saved_row.address_offset) != last_address {
let address_offset = if last_address.is_none() {
0
} else {
(addr_map.generated - base_addr) as u64
};
last_address = Some(saved_row.address_offset);
saved_row.address_offset = address_offset;
transform.generate_row(saved_row);
}
}
transform.end_sequence(map.len as u64);
}
let (out_program, files) = transform.program();
Ok((out_program, files))
}