190ac295eSAlex Crichton use super::AddressTransform;
287c33c29SAlex Crichton use super::expression::{CompiledExpression, FunctionFrameInfo};
3af476a51SSingleAccretion use super::utils::append_vmctx_info;
4af476a51SSingleAccretion use crate::debug::Compilation;
5a96845c3SAlex Crichton use crate::translate::get_vmctx_value_label;
687c33c29SAlex Crichton use cranelift_codegen::isa::TargetIsa;
79ce3ffe1SAlex Crichton use gimli::LineEncoding;
890ac295eSAlex Crichton use gimli::write;
987c33c29SAlex Crichton use std::collections::{HashMap, HashSet};
1087c33c29SAlex Crichton use std::path::PathBuf;
1187c33c29SAlex Crichton use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
12c7cab275SNick Fitzgerald use wasmtime_environ::error::{Context, Error};
1387c33c29SAlex Crichton use wasmtime_environ::{
14dd8c48b3SAlex Crichton DebugInfoData, EntityRef, FunctionMetadata, PrimaryMap, StaticModuleIndex, WasmFileInfo,
15496237c2SNick Fitzgerald WasmValType,
1687c33c29SAlex Crichton };
1787c33c29SAlex Crichton
1887c33c29SAlex Crichton const PRODUCER_NAME: &str = "wasmtime";
1987c33c29SAlex Crichton
2087c33c29SAlex Crichton macro_rules! assert_dwarf_str {
2187c33c29SAlex Crichton ($s:expr) => {{
2287c33c29SAlex Crichton let s = $s;
2387c33c29SAlex Crichton if cfg!(debug_assertions) {
2487c33c29SAlex Crichton // Perform check the same way as gimli does it.
2587c33c29SAlex Crichton let bytes: Vec<u8> = s.clone().into();
2687c33c29SAlex Crichton debug_assert!(!bytes.contains(&0), "DWARF string shall not have NULL byte");
2787c33c29SAlex Crichton }
2887c33c29SAlex Crichton s
2987c33c29SAlex Crichton }};
3087c33c29SAlex Crichton }
3187c33c29SAlex Crichton
generate_line_info( addr_tr: &PrimaryMap<StaticModuleIndex, AddressTransform>, translated: &HashSet<usize>, out_encoding: gimli::Encoding, w: &WasmFileInfo, comp_dir_id: write::StringId, name_id: write::StringId, name: &str, ) -> Result<(write::LineProgram, write::FileId), Error>3287c33c29SAlex Crichton fn generate_line_info(
33dd8c48b3SAlex Crichton addr_tr: &PrimaryMap<StaticModuleIndex, AddressTransform>,
34dd8c48b3SAlex Crichton translated: &HashSet<usize>,
3587c33c29SAlex Crichton out_encoding: gimli::Encoding,
3687c33c29SAlex Crichton w: &WasmFileInfo,
3787c33c29SAlex Crichton comp_dir_id: write::StringId,
3887c33c29SAlex Crichton name_id: write::StringId,
3987c33c29SAlex Crichton name: &str,
407cd4f630SPhilip Craig ) -> Result<(write::LineProgram, write::FileId), Error> {
4187c33c29SAlex Crichton let out_comp_dir = write::LineString::StringRef(comp_dir_id);
4287c33c29SAlex Crichton let out_comp_name = write::LineString::StringRef(name_id);
4387c33c29SAlex Crichton
4487c33c29SAlex Crichton let line_encoding = LineEncoding::default();
4587c33c29SAlex Crichton
4687c33c29SAlex Crichton let mut out_program = write::LineProgram::new(
4787c33c29SAlex Crichton out_encoding,
4887c33c29SAlex Crichton line_encoding,
4987c33c29SAlex Crichton out_comp_dir,
5078d5940fSAlex Crichton None,
5187c33c29SAlex Crichton out_comp_name,
5287c33c29SAlex Crichton None,
5387c33c29SAlex Crichton );
5487c33c29SAlex Crichton
5587c33c29SAlex Crichton let file_index = out_program.add_file(
5687c33c29SAlex Crichton write::LineString::String(name.as_bytes().to_vec()),
5787c33c29SAlex Crichton out_program.default_directory(),
5887c33c29SAlex Crichton None,
5987c33c29SAlex Crichton );
6087c33c29SAlex Crichton
61dd8c48b3SAlex Crichton let maps = addr_tr.iter().flat_map(|(_, transform)| {
62dd8c48b3SAlex Crichton transform.map().iter().filter_map(|(_, map)| {
63dd8c48b3SAlex Crichton if translated.contains(&map.symbol) {
64dd8c48b3SAlex Crichton None
65dd8c48b3SAlex Crichton } else {
66dd8c48b3SAlex Crichton Some((map.symbol, map))
6787c33c29SAlex Crichton }
68dd8c48b3SAlex Crichton })
69dd8c48b3SAlex Crichton });
7087c33c29SAlex Crichton
71dd8c48b3SAlex Crichton for (symbol, map) in maps {
7287c33c29SAlex Crichton let base_addr = map.offset;
7343db4612SSingleAccretion out_program.begin_sequence(Some(write::Address::Symbol {
7443db4612SSingleAccretion symbol,
7543db4612SSingleAccretion addend: base_addr as i64,
7643db4612SSingleAccretion }));
7743db4612SSingleAccretion
7843db4612SSingleAccretion // Always emit a row for offset zero - debuggers expect this.
7943db4612SSingleAccretion out_program.row().address_offset = 0;
8043db4612SSingleAccretion out_program.row().file = file_index;
8143db4612SSingleAccretion out_program.row().line = 0; // Special line number for non-user code.
8243db4612SSingleAccretion out_program.row().discriminator = 1;
8343db4612SSingleAccretion out_program.row().is_statement = true;
8443db4612SSingleAccretion out_program.generate_row();
8543db4612SSingleAccretion
8643db4612SSingleAccretion let mut is_prologue_end = true;
8787c33c29SAlex Crichton for addr_map in map.addresses.iter() {
8887c33c29SAlex Crichton let address_offset = (addr_map.generated - base_addr) as u64;
8987c33c29SAlex Crichton out_program.row().address_offset = address_offset;
905856590fSAlex Crichton let wasm_offset = w.code_section_offset + addr_map.wasm;
9187c33c29SAlex Crichton out_program.row().line = wasm_offset;
9287c33c29SAlex Crichton out_program.row().discriminator = 1;
9343db4612SSingleAccretion out_program.row().prologue_end = is_prologue_end;
9487c33c29SAlex Crichton out_program.generate_row();
9543db4612SSingleAccretion
9643db4612SSingleAccretion is_prologue_end = false;
9787c33c29SAlex Crichton }
9843db4612SSingleAccretion let end_addr = (base_addr + map.len - 1) as u64;
9987c33c29SAlex Crichton out_program.end_sequence(end_addr);
10087c33c29SAlex Crichton }
10187c33c29SAlex Crichton
1027cd4f630SPhilip Craig Ok((out_program, file_index))
10387c33c29SAlex Crichton }
10487c33c29SAlex Crichton
check_invalid_chars_in_name(s: &str) -> Option<&str>10587c33c29SAlex Crichton fn check_invalid_chars_in_name(s: &str) -> Option<&str> {
10690ac295eSAlex Crichton if s.contains('\x00') { None } else { Some(s) }
10787c33c29SAlex Crichton }
10887c33c29SAlex Crichton
autogenerate_dwarf_wasm_path(di: &DebugInfoData) -> PathBuf10987c33c29SAlex Crichton fn autogenerate_dwarf_wasm_path(di: &DebugInfoData) -> PathBuf {
11087c33c29SAlex Crichton static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
11187c33c29SAlex Crichton let module_name = di
11287c33c29SAlex Crichton .name_section
11387c33c29SAlex Crichton .module_name
11487c33c29SAlex Crichton .and_then(check_invalid_chars_in_name)
11587c33c29SAlex Crichton .map(|s| s.to_string())
1167cd4f630SPhilip Craig .unwrap_or_else(|| format!("<gen-{}>.wasm", NEXT_ID.fetch_add(1, SeqCst)));
1177cd4f630SPhilip Craig let path = format!("/<wasm-module>/{module_name}");
11887c33c29SAlex Crichton PathBuf::from(path)
11987c33c29SAlex Crichton }
12087c33c29SAlex Crichton
12187c33c29SAlex Crichton struct WasmTypesDieRefs {
12287c33c29SAlex Crichton i32: write::UnitEntryId,
12387c33c29SAlex Crichton i64: write::UnitEntryId,
12487c33c29SAlex Crichton f32: write::UnitEntryId,
12587c33c29SAlex Crichton f64: write::UnitEntryId,
12687c33c29SAlex Crichton }
12787c33c29SAlex Crichton
add_wasm_types( unit: &mut write::Unit, root_id: write::UnitEntryId, out_strings: &mut write::StringTable, ) -> WasmTypesDieRefs12887c33c29SAlex Crichton fn add_wasm_types(
12987c33c29SAlex Crichton unit: &mut write::Unit,
13087c33c29SAlex Crichton root_id: write::UnitEntryId,
13187c33c29SAlex Crichton out_strings: &mut write::StringTable,
13287c33c29SAlex Crichton ) -> WasmTypesDieRefs {
13387c33c29SAlex Crichton macro_rules! def_type {
13487c33c29SAlex Crichton ($id:literal, $size:literal, $enc:path) => {{
13587c33c29SAlex Crichton let die_id = unit.add(root_id, gimli::DW_TAG_base_type);
13687c33c29SAlex Crichton let die = unit.get_mut(die_id);
13787c33c29SAlex Crichton die.set(
13887c33c29SAlex Crichton gimli::DW_AT_name,
13987c33c29SAlex Crichton write::AttributeValue::StringRef(out_strings.add($id)),
14087c33c29SAlex Crichton );
14187c33c29SAlex Crichton die.set(gimli::DW_AT_byte_size, write::AttributeValue::Data1($size));
14287c33c29SAlex Crichton die.set(gimli::DW_AT_encoding, write::AttributeValue::Encoding($enc));
14387c33c29SAlex Crichton die_id
14487c33c29SAlex Crichton }};
14587c33c29SAlex Crichton }
14687c33c29SAlex Crichton
14787c33c29SAlex Crichton let i32_die_id = def_type!("i32", 4, gimli::DW_ATE_signed);
14887c33c29SAlex Crichton let i64_die_id = def_type!("i64", 8, gimli::DW_ATE_signed);
14987c33c29SAlex Crichton let f32_die_id = def_type!("f32", 4, gimli::DW_ATE_float);
15087c33c29SAlex Crichton let f64_die_id = def_type!("f64", 8, gimli::DW_ATE_float);
15187c33c29SAlex Crichton
15287c33c29SAlex Crichton WasmTypesDieRefs {
15387c33c29SAlex Crichton i32: i32_die_id,
15487c33c29SAlex Crichton i64: i64_die_id,
15587c33c29SAlex Crichton f32: f32_die_id,
15687c33c29SAlex Crichton f64: f64_die_id,
15787c33c29SAlex Crichton }
15887c33c29SAlex Crichton }
15987c33c29SAlex Crichton
resolve_var_type( index: usize, wasm_types: &WasmTypesDieRefs, func_meta: &FunctionMetadata, ) -> Option<(write::UnitEntryId, bool)>16087c33c29SAlex Crichton fn resolve_var_type(
16187c33c29SAlex Crichton index: usize,
16287c33c29SAlex Crichton wasm_types: &WasmTypesDieRefs,
16387c33c29SAlex Crichton func_meta: &FunctionMetadata,
16487c33c29SAlex Crichton ) -> Option<(write::UnitEntryId, bool)> {
16587c33c29SAlex Crichton let (ty, is_param) = if index < func_meta.params.len() {
16687c33c29SAlex Crichton (func_meta.params[index], true)
16787c33c29SAlex Crichton } else {
16887c33c29SAlex Crichton let mut i = (index - func_meta.params.len()) as u32;
16987c33c29SAlex Crichton let mut j = 0;
17087c33c29SAlex Crichton while j < func_meta.locals.len() && i >= func_meta.locals[j].0 {
17187c33c29SAlex Crichton i -= func_meta.locals[j].0;
17287c33c29SAlex Crichton j += 1;
17387c33c29SAlex Crichton }
17487c33c29SAlex Crichton if j >= func_meta.locals.len() {
17587c33c29SAlex Crichton // Ignore the var index out of bound.
17687c33c29SAlex Crichton return None;
17787c33c29SAlex Crichton }
17887c33c29SAlex Crichton (func_meta.locals[j].1, false)
17987c33c29SAlex Crichton };
18087c33c29SAlex Crichton let type_die_id = match ty {
181496237c2SNick Fitzgerald WasmValType::I32 => wasm_types.i32,
182496237c2SNick Fitzgerald WasmValType::I64 => wasm_types.i64,
183496237c2SNick Fitzgerald WasmValType::F32 => wasm_types.f32,
184496237c2SNick Fitzgerald WasmValType::F64 => wasm_types.f64,
18587c33c29SAlex Crichton _ => {
18687c33c29SAlex Crichton // Ignore unsupported types.
18787c33c29SAlex Crichton return None;
18887c33c29SAlex Crichton }
18987c33c29SAlex Crichton };
19087c33c29SAlex Crichton Some((type_die_id, is_param))
19187c33c29SAlex Crichton }
19287c33c29SAlex Crichton
generate_vars( unit: &mut write::Unit, die_id: write::UnitEntryId, addr_tr: &AddressTransform, frame_info: &FunctionFrameInfo, scope_ranges: &[(u64, u64)], vmctx_ptr_die_ref: write::DebugInfoRef, wasm_types: &WasmTypesDieRefs, func_meta: &FunctionMetadata, locals_names: Option<&HashMap<u32, &str>>, out_strings: &mut write::StringTable, isa: &dyn TargetIsa, ) -> Result<(), Error>19387c33c29SAlex Crichton fn generate_vars(
19487c33c29SAlex Crichton unit: &mut write::Unit,
19587c33c29SAlex Crichton die_id: write::UnitEntryId,
19687c33c29SAlex Crichton addr_tr: &AddressTransform,
19787c33c29SAlex Crichton frame_info: &FunctionFrameInfo,
19887c33c29SAlex Crichton scope_ranges: &[(u64, u64)],
199*7ee620a5SPhilip Craig vmctx_ptr_die_ref: write::DebugInfoRef,
20087c33c29SAlex Crichton wasm_types: &WasmTypesDieRefs,
20187c33c29SAlex Crichton func_meta: &FunctionMetadata,
20287c33c29SAlex Crichton locals_names: Option<&HashMap<u32, &str>>,
20387c33c29SAlex Crichton out_strings: &mut write::StringTable,
20487c33c29SAlex Crichton isa: &dyn TargetIsa,
20587c33c29SAlex Crichton ) -> Result<(), Error> {
20687c33c29SAlex Crichton let vmctx_label = get_vmctx_value_label();
20787c33c29SAlex Crichton
2080e9121daSFrankReh // Normalize order of ValueLabelsRanges keys to have reproducible results.
20987c33c29SAlex Crichton let mut vars = frame_info.value_ranges.keys().collect::<Vec<_>>();
21087c33c29SAlex Crichton vars.sort_by(|a, b| a.index().cmp(&b.index()));
21187c33c29SAlex Crichton
21287c33c29SAlex Crichton for label in vars {
21387c33c29SAlex Crichton if label.index() == vmctx_label.index() {
21487c33c29SAlex Crichton append_vmctx_info(
21587c33c29SAlex Crichton unit,
21687c33c29SAlex Crichton die_id,
217af476a51SSingleAccretion vmctx_ptr_die_ref,
21887c33c29SAlex Crichton addr_tr,
21987c33c29SAlex Crichton Some(frame_info),
22087c33c29SAlex Crichton scope_ranges,
22187c33c29SAlex Crichton out_strings,
22287c33c29SAlex Crichton isa,
22387c33c29SAlex Crichton )?;
22487c33c29SAlex Crichton } else {
22587c33c29SAlex Crichton let var_index = label.index();
22687c33c29SAlex Crichton let (type_die_id, is_param) =
22787c33c29SAlex Crichton if let Some(result) = resolve_var_type(var_index, wasm_types, func_meta) {
22887c33c29SAlex Crichton result
22987c33c29SAlex Crichton } else {
23087c33c29SAlex Crichton // Skipping if type of local cannot be detected.
23187c33c29SAlex Crichton continue;
23287c33c29SAlex Crichton };
23387c33c29SAlex Crichton
23487c33c29SAlex Crichton let loc_list_id = {
23587c33c29SAlex Crichton let locs = CompiledExpression::from_label(*label)
23687c33c29SAlex Crichton .build_with_locals(scope_ranges, addr_tr, Some(frame_info), isa)
237d2c9d2a2SSingleAccretion .expressions
23887c33c29SAlex Crichton .map(|i| {
23987c33c29SAlex Crichton i.map(|(begin, length, data)| write::Location::StartLength {
24087c33c29SAlex Crichton begin,
24187c33c29SAlex Crichton length,
24287c33c29SAlex Crichton data,
24387c33c29SAlex Crichton })
24487c33c29SAlex Crichton })
24587c33c29SAlex Crichton .collect::<Result<Vec<_>, _>>()?;
24687c33c29SAlex Crichton unit.locations.add(write::LocationList(locs))
24787c33c29SAlex Crichton };
24887c33c29SAlex Crichton
24987c33c29SAlex Crichton let var_id = unit.add(
25087c33c29SAlex Crichton die_id,
25187c33c29SAlex Crichton if is_param {
25287c33c29SAlex Crichton gimli::DW_TAG_formal_parameter
25387c33c29SAlex Crichton } else {
25487c33c29SAlex Crichton gimli::DW_TAG_variable
25587c33c29SAlex Crichton },
25687c33c29SAlex Crichton );
25787c33c29SAlex Crichton let var = unit.get_mut(var_id);
25887c33c29SAlex Crichton
25987c33c29SAlex Crichton let name_id = match locals_names
26087c33c29SAlex Crichton .and_then(|m| m.get(&(var_index as u32)))
26187c33c29SAlex Crichton .and_then(|s| check_invalid_chars_in_name(s))
26287c33c29SAlex Crichton {
26387c33c29SAlex Crichton Some(n) => out_strings.add(assert_dwarf_str!(n)),
264a0442ea0SHamir Mahal None => out_strings.add(format!("var{var_index}")),
26587c33c29SAlex Crichton };
26687c33c29SAlex Crichton
26787c33c29SAlex Crichton var.set(gimli::DW_AT_name, write::AttributeValue::StringRef(name_id));
26887c33c29SAlex Crichton var.set(
26987c33c29SAlex Crichton gimli::DW_AT_type,
27087c33c29SAlex Crichton write::AttributeValue::UnitRef(type_die_id),
27187c33c29SAlex Crichton );
27287c33c29SAlex Crichton var.set(
27387c33c29SAlex Crichton gimli::DW_AT_location,
27487c33c29SAlex Crichton write::AttributeValue::LocationListRef(loc_list_id),
27587c33c29SAlex Crichton );
27687c33c29SAlex Crichton }
27787c33c29SAlex Crichton }
27887c33c29SAlex Crichton Ok(())
27987c33c29SAlex Crichton }
28087c33c29SAlex Crichton
check_invalid_chars_in_path(path: PathBuf) -> Option<PathBuf>28187c33c29SAlex Crichton fn check_invalid_chars_in_path(path: PathBuf) -> Option<PathBuf> {
28287c33c29SAlex Crichton path.clone()
28387c33c29SAlex Crichton .to_str()
28487c33c29SAlex Crichton .and_then(move |s| if s.contains('\x00') { None } else { Some(path) })
28587c33c29SAlex Crichton }
28687c33c29SAlex Crichton
287af476a51SSingleAccretion /// Generate "simulated" native DWARF for functions lacking WASM-level DWARF.
generate_simulated_dwarf( compilation: &mut Compilation<'_>, addr_tr: &PrimaryMap<StaticModuleIndex, AddressTransform>, translated: &HashSet<usize>, out_encoding: gimli::Encoding, vmctx_ptr_die_refs: &PrimaryMap<StaticModuleIndex, write::DebugInfoRef>, out_units: &mut write::UnitTable, out_strings: &mut write::StringTable, isa: &dyn TargetIsa, ) -> Result<(), Error>28887c33c29SAlex Crichton pub fn generate_simulated_dwarf(
289dd8c48b3SAlex Crichton compilation: &mut Compilation<'_>,
290dd8c48b3SAlex Crichton addr_tr: &PrimaryMap<StaticModuleIndex, AddressTransform>,
291dd8c48b3SAlex Crichton translated: &HashSet<usize>,
29287c33c29SAlex Crichton out_encoding: gimli::Encoding,
293*7ee620a5SPhilip Craig vmctx_ptr_die_refs: &PrimaryMap<StaticModuleIndex, write::DebugInfoRef>,
29487c33c29SAlex Crichton out_units: &mut write::UnitTable,
29587c33c29SAlex Crichton out_strings: &mut write::StringTable,
29687c33c29SAlex Crichton isa: &dyn TargetIsa,
29787c33c29SAlex Crichton ) -> Result<(), Error> {
298dd8c48b3SAlex Crichton let (wasm_file, path) = {
299dd8c48b3SAlex Crichton let di = &compilation.translations.iter().next().unwrap().1.debuginfo;
30087c33c29SAlex Crichton let path = di
30187c33c29SAlex Crichton .wasm_file
30287c33c29SAlex Crichton .path
30387c33c29SAlex Crichton .to_owned()
30487c33c29SAlex Crichton .and_then(check_invalid_chars_in_path)
30587c33c29SAlex Crichton .unwrap_or_else(|| autogenerate_dwarf_wasm_path(di));
306dd8c48b3SAlex Crichton (&di.wasm_file, path)
307dd8c48b3SAlex Crichton };
30887c33c29SAlex Crichton
3097cd4f630SPhilip Craig let (unit, root_id, file_id) = {
31090ac295eSAlex Crichton let comp_dir_id = out_strings.add(assert_dwarf_str!(
31190ac295eSAlex Crichton path.parent()
31287c33c29SAlex Crichton .context("path dir")?
31387c33c29SAlex Crichton .to_str()
31490ac295eSAlex Crichton .context("path dir encoding")?
31590ac295eSAlex Crichton ));
31687c33c29SAlex Crichton let name = path
31787c33c29SAlex Crichton .file_name()
31887c33c29SAlex Crichton .context("path name")?
31987c33c29SAlex Crichton .to_str()
32087c33c29SAlex Crichton .context("path name encoding")?;
32187c33c29SAlex Crichton let name_id = out_strings.add(assert_dwarf_str!(name));
32287c33c29SAlex Crichton
3237cd4f630SPhilip Craig let (out_program, file_id) = generate_line_info(
32487c33c29SAlex Crichton addr_tr,
32587c33c29SAlex Crichton translated,
32687c33c29SAlex Crichton out_encoding,
327dd8c48b3SAlex Crichton wasm_file,
32887c33c29SAlex Crichton comp_dir_id,
32987c33c29SAlex Crichton name_id,
33087c33c29SAlex Crichton name,
33187c33c29SAlex Crichton )?;
33287c33c29SAlex Crichton
33387c33c29SAlex Crichton let unit_id = out_units.add(write::Unit::new(out_encoding, out_program));
33487c33c29SAlex Crichton let unit = out_units.get_mut(unit_id);
33587c33c29SAlex Crichton
33687c33c29SAlex Crichton let root_id = unit.root();
33787c33c29SAlex Crichton let root = unit.get_mut(root_id);
33887c33c29SAlex Crichton
33987c33c29SAlex Crichton let id = out_strings.add(PRODUCER_NAME);
34087c33c29SAlex Crichton root.set(gimli::DW_AT_producer, write::AttributeValue::StringRef(id));
341329ae912SPhilip Craig root.set(
342329ae912SPhilip Craig gimli::DW_AT_language,
343329ae912SPhilip Craig write::AttributeValue::Language(gimli::DW_LANG_C11),
344329ae912SPhilip Craig );
34587c33c29SAlex Crichton root.set(gimli::DW_AT_name, write::AttributeValue::StringRef(name_id));
34687c33c29SAlex Crichton root.set(
34787c33c29SAlex Crichton gimli::DW_AT_stmt_list,
34887c33c29SAlex Crichton write::AttributeValue::LineProgramRef,
34987c33c29SAlex Crichton );
35087c33c29SAlex Crichton root.set(
35187c33c29SAlex Crichton gimli::DW_AT_comp_dir,
35287c33c29SAlex Crichton write::AttributeValue::StringRef(comp_dir_id),
35387c33c29SAlex Crichton );
3547cd4f630SPhilip Craig (unit, root_id, file_id)
35587c33c29SAlex Crichton };
35687c33c29SAlex Crichton
357af476a51SSingleAccretion let wasm_types = add_wasm_types(unit, root_id, out_strings);
35843db4612SSingleAccretion let mut unit_ranges = vec![];
359dd8c48b3SAlex Crichton for (module, index) in compilation.indexes().collect::<Vec<_>>() {
360dd8c48b3SAlex Crichton let (symbol, _) = compilation.function(module, index);
361dd8c48b3SAlex Crichton if translated.contains(&symbol) {
36287c33c29SAlex Crichton continue;
36387c33c29SAlex Crichton }
36487c33c29SAlex Crichton
365dd8c48b3SAlex Crichton let addr_tr = &addr_tr[module];
366dd8c48b3SAlex Crichton let map = &addr_tr.map()[index];
36787c33c29SAlex Crichton let die_id = unit.add(root_id, gimli::DW_TAG_subprogram);
36887c33c29SAlex Crichton let die = unit.get_mut(die_id);
36943db4612SSingleAccretion let low_pc = write::Address::Symbol {
370dd8c48b3SAlex Crichton symbol,
37143db4612SSingleAccretion addend: map.offset as i64,
37243db4612SSingleAccretion };
37343db4612SSingleAccretion let code_length = map.len as u64;
37443db4612SSingleAccretion die.set(gimli::DW_AT_low_pc, write::AttributeValue::Address(low_pc));
37587c33c29SAlex Crichton die.set(
37687c33c29SAlex Crichton gimli::DW_AT_high_pc,
37743db4612SSingleAccretion write::AttributeValue::Udata(code_length),
37887c33c29SAlex Crichton );
37943db4612SSingleAccretion unit_ranges.push(write::Range::StartLength {
38043db4612SSingleAccretion begin: low_pc,
38143db4612SSingleAccretion length: code_length,
38243db4612SSingleAccretion });
38387c33c29SAlex Crichton
384dd8c48b3SAlex Crichton let translation = &compilation.translations[module];
385dd8c48b3SAlex Crichton let func_index = translation.module.func_index(index);
386dd8c48b3SAlex Crichton let di = &translation.debuginfo;
387dd8c48b3SAlex Crichton let id = match di
388dd8c48b3SAlex Crichton .name_section
389dd8c48b3SAlex Crichton .func_names
390dd8c48b3SAlex Crichton .get(&func_index)
39187c33c29SAlex Crichton .and_then(|s| check_invalid_chars_in_name(s))
39287c33c29SAlex Crichton {
39387c33c29SAlex Crichton Some(n) => out_strings.add(assert_dwarf_str!(n)),
394dd8c48b3SAlex Crichton None => out_strings.add(format!("wasm-function[{}]", func_index.as_u32())),
39587c33c29SAlex Crichton };
39687c33c29SAlex Crichton
39787c33c29SAlex Crichton die.set(gimli::DW_AT_name, write::AttributeValue::StringRef(id));
39887c33c29SAlex Crichton
39987c33c29SAlex Crichton die.set(
40087c33c29SAlex Crichton gimli::DW_AT_decl_file,
4017cd4f630SPhilip Craig write::AttributeValue::FileIndex(Some(file_id)),
40287c33c29SAlex Crichton );
40387c33c29SAlex Crichton
40487c33c29SAlex Crichton let f_start = map.addresses[0].wasm;
4055856590fSAlex Crichton let wasm_offset = di.wasm_file.code_section_offset + f_start;
40687c33c29SAlex Crichton die.set(
4077cd4f630SPhilip Craig gimli::DW_AT_decl_line,
40887c33c29SAlex Crichton write::AttributeValue::Udata(wasm_offset),
40987c33c29SAlex Crichton );
41087c33c29SAlex Crichton
411dd8c48b3SAlex Crichton let frame_info = compilation.function_frame_info(module, index);
412dd8c48b3SAlex Crichton let source_range = addr_tr.func_source_range(index);
41387c33c29SAlex Crichton generate_vars(
41487c33c29SAlex Crichton unit,
41587c33c29SAlex Crichton die_id,
41687c33c29SAlex Crichton addr_tr,
41787c33c29SAlex Crichton &frame_info,
41887c33c29SAlex Crichton &[(source_range.0, source_range.1)],
419af476a51SSingleAccretion vmctx_ptr_die_refs[module],
420af476a51SSingleAccretion &wasm_types,
421dd8c48b3SAlex Crichton &di.wasm_file.funcs[index.as_u32() as usize],
422dd8c48b3SAlex Crichton di.name_section.locals_names.get(&func_index),
42387c33c29SAlex Crichton out_strings,
42487c33c29SAlex Crichton isa,
42587c33c29SAlex Crichton )?;
42687c33c29SAlex Crichton }
42743db4612SSingleAccretion let unit_ranges_id = unit.ranges.add(write::RangeList(unit_ranges));
42843db4612SSingleAccretion unit.get_mut(root_id).set(
42943db4612SSingleAccretion gimli::DW_AT_ranges,
43043db4612SSingleAccretion write::AttributeValue::RangeListRef(unit_ranges_id),
43143db4612SSingleAccretion );
43287c33c29SAlex Crichton
43387c33c29SAlex Crichton Ok(())
43487c33c29SAlex Crichton }
435