wasm_debug/transform/
mod.rs

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