wasmtime_environ/
module_environ.rs

1use crate::module::{
2    AnyfuncIndex, Initializer, MemoryInitialization, MemoryInitializer, MemoryPlan, Module,
3    ModuleType, TableInitializer, TablePlan,
4};
5use crate::{
6    DataIndex, DefinedFuncIndex, ElemIndex, EntityIndex, EntityType, FuncIndex, Global,
7    GlobalIndex, GlobalInit, MemoryIndex, ModuleTypesBuilder, PrimaryMap, SignatureIndex,
8    TableIndex, TableInitialization, Tunables, TypeIndex, WasmError, WasmFuncType, WasmResult,
9};
10use cranelift_entity::packed_option::ReservedValue;
11use std::borrow::Cow;
12use std::collections::HashMap;
13use std::convert::{TryFrom, TryInto};
14use std::path::PathBuf;
15use std::sync::Arc;
16use wasmparser::{
17    types::Types, CustomSectionReader, DataKind, ElementItems, ElementKind, Encoding, ExternalKind,
18    FuncToValidate, FunctionBody, NameSectionReader, Naming, Operator, Parser, Payload, Type,
19    TypeRef, Validator, ValidatorResources,
20};
21
22/// Object containing the standalone environment information.
23pub struct ModuleEnvironment<'a, 'data> {
24    /// The current module being translated
25    result: ModuleTranslation<'data>,
26
27    /// Intern'd types for this entire translation, shared by all modules.
28    types: &'a mut ModuleTypesBuilder,
29
30    // Various bits and pieces of configuration
31    validator: &'a mut Validator,
32    tunables: &'a Tunables,
33}
34
35/// The result of translating via `ModuleEnvironment`. Function bodies are not
36/// yet translated, and data initializers have not yet been copied out of the
37/// original buffer.
38#[derive(Default)]
39pub struct ModuleTranslation<'data> {
40    /// Module information.
41    pub module: Module,
42
43    /// The input wasm binary.
44    ///
45    /// This can be useful, for example, when modules are parsed from a
46    /// component and the embedder wants access to the raw wasm modules
47    /// themselves.
48    pub wasm: &'data [u8],
49
50    /// References to the function bodies.
51    pub function_body_inputs: PrimaryMap<DefinedFuncIndex, FunctionBodyData<'data>>,
52
53    /// A list of type signatures which are considered exported from this
54    /// module, or those that can possibly be called. This list is sorted, and
55    /// trampolines for each of these signatures are required.
56    pub exported_signatures: Vec<SignatureIndex>,
57
58    /// DWARF debug information, if enabled, parsed from the module.
59    pub debuginfo: DebugInfoData<'data>,
60
61    /// Set if debuginfo was found but it was not parsed due to `Tunables`
62    /// configuration.
63    pub has_unparsed_debuginfo: bool,
64
65    /// List of data segments found in this module which should be concatenated
66    /// together for the final compiled artifact.
67    ///
68    /// These data segments, when concatenated, are indexed by the
69    /// `MemoryInitializer` type.
70    pub data: Vec<Cow<'data, [u8]>>,
71
72    /// The desired alignment of `data` in the final data section of the object
73    /// file that we'll emit.
74    ///
75    /// Note that this is 1 by default but `MemoryInitialization::Static` might
76    /// switch this to a higher alignment to facilitate mmap-ing data from
77    /// an object file into a linear memory.
78    pub data_align: Option<u64>,
79
80    /// Total size of all data pushed onto `data` so far.
81    total_data: u32,
82
83    /// List of passive element segments found in this module which will get
84    /// concatenated for the final artifact.
85    pub passive_data: Vec<&'data [u8]>,
86
87    /// Total size of all passive data pushed into `passive_data` so far.
88    total_passive_data: u32,
89
90    /// When we're parsing the code section this will be incremented so we know
91    /// which function is currently being defined.
92    code_index: u32,
93
94    /// The type information of the current module made available at the end of the
95    /// validation process.
96    types: Option<Types>,
97}
98
99impl<'data> ModuleTranslation<'data> {
100    /// Returns a reference to the type information of the current module.
101    pub fn get_types(&self) -> &Types {
102        self.types
103            .as_ref()
104            .expect("module type information to be available")
105    }
106}
107
108/// Contains function data: byte code and its offset in the module.
109pub struct FunctionBodyData<'a> {
110    /// The body of the function, containing code and locals.
111    pub body: FunctionBody<'a>,
112    /// Validator for the function body
113    pub validator: FuncToValidate<ValidatorResources>,
114}
115
116#[derive(Debug, Default)]
117#[allow(missing_docs)]
118pub struct DebugInfoData<'a> {
119    pub dwarf: Dwarf<'a>,
120    pub name_section: NameSection<'a>,
121    pub wasm_file: WasmFileInfo,
122    debug_loc: gimli::DebugLoc<Reader<'a>>,
123    debug_loclists: gimli::DebugLocLists<Reader<'a>>,
124    pub debug_ranges: gimli::DebugRanges<Reader<'a>>,
125    pub debug_rnglists: gimli::DebugRngLists<Reader<'a>>,
126}
127
128#[allow(missing_docs)]
129pub type Dwarf<'input> = gimli::Dwarf<Reader<'input>>;
130
131type Reader<'input> = gimli::EndianSlice<'input, gimli::LittleEndian>;
132
133#[derive(Debug, Default)]
134#[allow(missing_docs)]
135pub struct NameSection<'a> {
136    pub module_name: Option<&'a str>,
137    pub func_names: HashMap<FuncIndex, &'a str>,
138    pub locals_names: HashMap<FuncIndex, HashMap<u32, &'a str>>,
139}
140
141#[derive(Debug, Default)]
142#[allow(missing_docs)]
143pub struct WasmFileInfo {
144    pub path: Option<PathBuf>,
145    pub code_section_offset: u64,
146    pub imported_func_count: u32,
147    pub funcs: Vec<FunctionMetadata>,
148}
149
150#[derive(Debug)]
151#[allow(missing_docs)]
152pub struct FunctionMetadata {
153    pub params: Box<[wasmparser::ValType]>,
154    pub locals: Box<[(u32, wasmparser::ValType)]>,
155}
156
157impl<'a, 'data> ModuleEnvironment<'a, 'data> {
158    /// Allocates the environment data structures.
159    pub fn new(
160        tunables: &'a Tunables,
161        validator: &'a mut Validator,
162        types: &'a mut ModuleTypesBuilder,
163    ) -> Self {
164        Self {
165            result: ModuleTranslation::default(),
166            types,
167            tunables,
168            validator,
169        }
170    }
171
172    /// Translate a wasm module using this environment.
173    ///
174    /// This function will translate the `data` provided with `parser`,
175    /// validating everything along the way with this environment's validator.
176    ///
177    /// The result of translation, [`ModuleTranslation`], contains everything
178    /// necessary to compile functions afterwards as well as learn type
179    /// information about the module at runtime.
180    pub fn translate(
181        mut self,
182        parser: Parser,
183        data: &'data [u8],
184    ) -> WasmResult<ModuleTranslation<'data>> {
185        self.result.wasm = data;
186
187        for payload in parser.parse_all(data) {
188            self.translate_payload(payload?)?;
189        }
190
191        Ok(self.result)
192    }
193
194    fn translate_payload(&mut self, payload: Payload<'data>) -> WasmResult<()> {
195        match payload {
196            Payload::Version {
197                num,
198                encoding,
199                range,
200            } => {
201                self.validator.version(num, encoding, &range)?;
202                match encoding {
203                    Encoding::Module => {}
204                    Encoding::Component => {
205                        return Err(WasmError::Unsupported(format!("component model")));
206                    }
207                }
208            }
209
210            Payload::End(offset) => {
211                self.result.types = Some(self.validator.end(offset)?);
212
213                // With the `escaped_funcs` set of functions finished
214                // we can calculate the set of signatures that are exported as
215                // the set of exported functions' signatures.
216                self.result.exported_signatures = self
217                    .result
218                    .module
219                    .functions
220                    .iter()
221                    .filter_map(|(_, func)| {
222                        if func.is_escaping() {
223                            Some(func.signature)
224                        } else {
225                            None
226                        }
227                    })
228                    .collect();
229                self.result.exported_signatures.sort_unstable();
230                self.result.exported_signatures.dedup();
231            }
232
233            Payload::TypeSection(types) => {
234                self.validator.type_section(&types)?;
235                let num = usize::try_from(types.count()).unwrap();
236                self.result.module.types.reserve(num);
237                self.types.reserve_wasm_signatures(num);
238
239                for ty in types {
240                    match ty? {
241                        Type::Func(wasm_func_ty) => {
242                            self.declare_type_func(wasm_func_ty.try_into()?)?;
243                        }
244                    }
245                }
246            }
247
248            Payload::ImportSection(imports) => {
249                self.validator.import_section(&imports)?;
250
251                let cnt = usize::try_from(imports.count()).unwrap();
252                self.result.module.initializers.reserve(cnt);
253
254                for entry in imports {
255                    let import = entry?;
256                    let ty = match import.ty {
257                        TypeRef::Func(index) => {
258                            let index = TypeIndex::from_u32(index);
259                            let sig_index = self.result.module.types[index].unwrap_function();
260                            self.result.module.num_imported_funcs += 1;
261                            self.result.debuginfo.wasm_file.imported_func_count += 1;
262                            EntityType::Function(sig_index)
263                        }
264                        TypeRef::Memory(ty) => {
265                            self.result.module.num_imported_memories += 1;
266                            EntityType::Memory(ty.into())
267                        }
268                        TypeRef::Global(ty) => {
269                            self.result.module.num_imported_globals += 1;
270                            EntityType::Global(Global::new(ty, GlobalInit::Import)?)
271                        }
272                        TypeRef::Table(ty) => {
273                            self.result.module.num_imported_tables += 1;
274                            EntityType::Table(ty.try_into()?)
275                        }
276
277                        // doesn't get past validation
278                        TypeRef::Tag(_) => unreachable!(),
279                    };
280                    self.declare_import(import.module, import.name, ty);
281                }
282            }
283
284            Payload::FunctionSection(functions) => {
285                self.validator.function_section(&functions)?;
286
287                let cnt = usize::try_from(functions.count()).unwrap();
288                self.result.module.functions.reserve_exact(cnt);
289
290                for entry in functions {
291                    let sigindex = entry?;
292                    let ty = TypeIndex::from_u32(sigindex);
293                    let sig_index = self.result.module.types[ty].unwrap_function();
294                    self.result.module.push_function(sig_index);
295                }
296            }
297
298            Payload::TableSection(tables) => {
299                self.validator.table_section(&tables)?;
300                let cnt = usize::try_from(tables.count()).unwrap();
301                self.result.module.table_plans.reserve_exact(cnt);
302
303                for entry in tables {
304                    let table = entry?.ty.try_into()?;
305                    let plan = TablePlan::for_table(table, &self.tunables);
306                    self.result.module.table_plans.push(plan);
307                }
308            }
309
310            Payload::MemorySection(memories) => {
311                self.validator.memory_section(&memories)?;
312
313                let cnt = usize::try_from(memories.count()).unwrap();
314                self.result.module.memory_plans.reserve_exact(cnt);
315
316                for entry in memories {
317                    let memory = entry?;
318                    let plan = MemoryPlan::for_memory(memory.into(), &self.tunables);
319                    self.result.module.memory_plans.push(plan);
320                }
321            }
322
323            Payload::TagSection(tags) => {
324                self.validator.tag_section(&tags)?;
325
326                // This feature isn't enabled at this time, so we should
327                // never get here.
328                unreachable!();
329            }
330
331            Payload::GlobalSection(globals) => {
332                self.validator.global_section(&globals)?;
333
334                let cnt = usize::try_from(globals.count()).unwrap();
335                self.result.module.globals.reserve_exact(cnt);
336
337                for entry in globals {
338                    let wasmparser::Global { ty, init_expr } = entry?;
339                    let mut init_expr_reader = init_expr.get_binary_reader();
340                    let initializer = match init_expr_reader.read_operator()? {
341                        Operator::I32Const { value } => GlobalInit::I32Const(value),
342                        Operator::I64Const { value } => GlobalInit::I64Const(value),
343                        Operator::F32Const { value } => GlobalInit::F32Const(value.bits()),
344                        Operator::F64Const { value } => GlobalInit::F64Const(value.bits()),
345                        Operator::V128Const { value } => {
346                            GlobalInit::V128Const(u128::from_le_bytes(*value.bytes()))
347                        }
348                        Operator::RefNull { hty: _ } => GlobalInit::RefNullConst,
349                        Operator::RefFunc { function_index } => {
350                            let index = FuncIndex::from_u32(function_index);
351                            self.flag_func_escaped(index);
352                            GlobalInit::RefFunc(index)
353                        }
354                        Operator::GlobalGet { global_index } => {
355                            GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
356                        }
357                        s => {
358                            return Err(WasmError::Unsupported(format!(
359                                "unsupported init expr in global section: {:?}",
360                                s
361                            )));
362                        }
363                    };
364                    let ty = Global::new(ty, initializer)?;
365                    self.result.module.globals.push(ty);
366                }
367            }
368
369            Payload::ExportSection(exports) => {
370                self.validator.export_section(&exports)?;
371
372                let cnt = usize::try_from(exports.count()).unwrap();
373                self.result.module.exports.reserve(cnt);
374
375                for entry in exports {
376                    let wasmparser::Export { name, kind, index } = entry?;
377                    let entity = match kind {
378                        ExternalKind::Func => {
379                            let index = FuncIndex::from_u32(index);
380                            self.flag_func_escaped(index);
381                            EntityIndex::Function(index)
382                        }
383                        ExternalKind::Table => EntityIndex::Table(TableIndex::from_u32(index)),
384                        ExternalKind::Memory => EntityIndex::Memory(MemoryIndex::from_u32(index)),
385                        ExternalKind::Global => EntityIndex::Global(GlobalIndex::from_u32(index)),
386
387                        // this never gets past validation
388                        ExternalKind::Tag => unreachable!(),
389                    };
390                    self.result
391                        .module
392                        .exports
393                        .insert(String::from(name), entity);
394                }
395            }
396
397            Payload::StartSection { func, range } => {
398                self.validator.start_section(func, &range)?;
399
400                let func_index = FuncIndex::from_u32(func);
401                self.flag_func_escaped(func_index);
402                debug_assert!(self.result.module.start_func.is_none());
403                self.result.module.start_func = Some(func_index);
404            }
405
406            Payload::ElementSection(elements) => {
407                self.validator.element_section(&elements)?;
408
409                for (index, entry) in elements.into_iter().enumerate() {
410                    let wasmparser::Element {
411                        kind,
412                        items,
413                        ty: _,
414                        range: _,
415                    } = entry?;
416
417                    // Build up a list of `FuncIndex` corresponding to all the
418                    // entries listed in this segment. Note that it's not
419                    // possible to create anything other than a `ref.null
420                    // extern` for externref segments, so those just get
421                    // translated to the reserved value of `FuncIndex`.
422                    let mut elements = Vec::new();
423                    match items {
424                        ElementItems::Functions(funcs) => {
425                            elements.reserve(usize::try_from(funcs.count()).unwrap());
426                            for func in funcs {
427                                let func = FuncIndex::from_u32(func?);
428                                self.flag_func_escaped(func);
429                                elements.push(func);
430                            }
431                        }
432                        ElementItems::Expressions(funcs) => {
433                            elements.reserve(usize::try_from(funcs.count()).unwrap());
434                            for func in funcs {
435                                let func = match func?.get_binary_reader().read_operator()? {
436                                    Operator::RefNull { .. } => FuncIndex::reserved_value(),
437                                    Operator::RefFunc { function_index } => {
438                                        let func = FuncIndex::from_u32(function_index);
439                                        self.flag_func_escaped(func);
440                                        func
441                                    }
442                                    s => {
443                                        return Err(WasmError::Unsupported(format!(
444                                            "unsupported init expr in element section: {:?}",
445                                            s
446                                        )));
447                                    }
448                                };
449                                elements.push(func);
450                            }
451                        }
452                    }
453
454                    match kind {
455                        ElementKind::Active {
456                            table_index,
457                            offset_expr,
458                        } => {
459                            let table_index = TableIndex::from_u32(table_index);
460                            let mut offset_expr_reader = offset_expr.get_binary_reader();
461                            let (base, offset) = match offset_expr_reader.read_operator()? {
462                                Operator::I32Const { value } => (None, value as u32),
463                                Operator::GlobalGet { global_index } => {
464                                    (Some(GlobalIndex::from_u32(global_index)), 0)
465                                }
466                                ref s => {
467                                    return Err(WasmError::Unsupported(format!(
468                                        "unsupported init expr in element section: {:?}",
469                                        s
470                                    )));
471                                }
472                            };
473
474                            let table_segments = match &mut self.result.module.table_initialization
475                            {
476                                TableInitialization::Segments { segments } => segments,
477                                TableInitialization::FuncTable { .. } => unreachable!(),
478                            };
479                            table_segments.push(TableInitializer {
480                                table_index,
481                                base,
482                                offset,
483                                elements: elements.into(),
484                            });
485                        }
486
487                        ElementKind::Passive => {
488                            let elem_index = ElemIndex::from_u32(index as u32);
489                            let index = self.result.module.passive_elements.len();
490                            self.result.module.passive_elements.push(elements.into());
491                            self.result
492                                .module
493                                .passive_elements_map
494                                .insert(elem_index, index);
495                        }
496
497                        ElementKind::Declared => {}
498                    }
499                }
500            }
501
502            Payload::CodeSectionStart { count, range, .. } => {
503                self.validator.code_section_start(count, &range)?;
504                let cnt = usize::try_from(count).unwrap();
505                self.result.function_body_inputs.reserve_exact(cnt);
506                self.result.debuginfo.wasm_file.code_section_offset = range.start as u64;
507            }
508
509            Payload::CodeSectionEntry(mut body) => {
510                let validator = self.validator.code_section_entry(&body)?;
511                let func_index =
512                    self.result.code_index + self.result.module.num_imported_funcs as u32;
513                let func_index = FuncIndex::from_u32(func_index);
514
515                if self.tunables.generate_native_debuginfo {
516                    let sig_index = self.result.module.functions[func_index].signature;
517                    let sig = &self.types[sig_index];
518                    let mut locals = Vec::new();
519                    for pair in body.get_locals_reader()? {
520                        locals.push(pair?);
521                    }
522                    self.result
523                        .debuginfo
524                        .wasm_file
525                        .funcs
526                        .push(FunctionMetadata {
527                            locals: locals.into_boxed_slice(),
528                            params: sig.params().iter().cloned().map(|i| i.into()).collect(),
529                        });
530                }
531                body.allow_memarg64(self.validator.features().memory64);
532                self.result
533                    .function_body_inputs
534                    .push(FunctionBodyData { validator, body });
535                self.result.code_index += 1;
536            }
537
538            Payload::DataSection(data) => {
539                self.validator.data_section(&data)?;
540
541                let initializers = match &mut self.result.module.memory_initialization {
542                    MemoryInitialization::Segmented(i) => i,
543                    _ => unreachable!(),
544                };
545
546                let cnt = usize::try_from(data.count()).unwrap();
547                initializers.reserve_exact(cnt);
548                self.result.data.reserve_exact(cnt);
549
550                for (index, entry) in data.into_iter().enumerate() {
551                    let wasmparser::Data {
552                        kind,
553                        data,
554                        range: _,
555                    } = entry?;
556                    let mk_range = |total: &mut u32| -> Result<_, WasmError> {
557                        let range = u32::try_from(data.len())
558                            .ok()
559                            .and_then(|size| {
560                                let start = *total;
561                                let end = start.checked_add(size)?;
562                                Some(start..end)
563                            })
564                            .ok_or_else(|| {
565                                WasmError::Unsupported(format!(
566                                    "more than 4 gigabytes of data in wasm module",
567                                ))
568                            })?;
569                        *total += range.end - range.start;
570                        Ok(range)
571                    };
572                    match kind {
573                        DataKind::Active {
574                            memory_index,
575                            offset_expr,
576                        } => {
577                            let range = mk_range(&mut self.result.total_data)?;
578                            let memory_index = MemoryIndex::from_u32(memory_index);
579                            let mut offset_expr_reader = offset_expr.get_binary_reader();
580                            let (base, offset) = match offset_expr_reader.read_operator()? {
581                                Operator::I32Const { value } => (None, value as u64),
582                                Operator::I64Const { value } => (None, value as u64),
583                                Operator::GlobalGet { global_index } => {
584                                    (Some(GlobalIndex::from_u32(global_index)), 0)
585                                }
586                                s => {
587                                    return Err(WasmError::Unsupported(format!(
588                                        "unsupported init expr in data section: {:?}",
589                                        s
590                                    )));
591                                }
592                            };
593
594                            initializers.push(MemoryInitializer {
595                                memory_index,
596                                base,
597                                offset,
598                                data: range,
599                            });
600                            self.result.data.push(data.into());
601                        }
602                        DataKind::Passive => {
603                            let data_index = DataIndex::from_u32(index as u32);
604                            let range = mk_range(&mut self.result.total_passive_data)?;
605                            self.result.passive_data.push(data);
606                            self.result
607                                .module
608                                .passive_data_map
609                                .insert(data_index, range);
610                        }
611                    }
612                }
613            }
614
615            Payload::DataCountSection { count, range } => {
616                self.validator.data_count_section(count, &range)?;
617
618                // Note: the count passed in here is the *total* segment count
619                // There is no way to reserve for just the passive segments as
620                // they are discovered when iterating the data section entries
621                // Given that the total segment count might be much larger than
622                // the passive count, do not reserve anything here.
623            }
624
625            Payload::CustomSection(s) if s.name() == "name" => {
626                let result = self.name_section(NameSectionReader::new(s.data(), s.data_offset()));
627                if let Err(e) = result {
628                    log::warn!("failed to parse name section {:?}", e);
629                }
630            }
631
632            Payload::CustomSection(s)
633                if s.name() == "webidl-bindings" || s.name() == "wasm-interface-types" =>
634            {
635                return Err(WasmError::Unsupported(
636                    "\
637Support for interface types has temporarily been removed from `wasmtime`.
638
639For more information about this temporary change you can read on the issue online:
640
641    https://github.com/bytecodealliance/wasmtime/issues/1271
642
643and for re-adding support for interface types you can see this issue:
644
645    https://github.com/bytecodealliance/wasmtime/issues/677
646"
647                    .to_string(),
648                ))
649            }
650
651            Payload::CustomSection(s) => {
652                self.register_dwarf_section(&s);
653            }
654
655            // It's expected that validation will probably reject other
656            // payloads such as `UnknownSection` or those related to the
657            // component model. If, however, something gets past validation then
658            // that's a bug in Wasmtime as we forgot to implement something.
659            other => {
660                self.validator.payload(&other)?;
661                panic!("unimplemented section in wasm file {:?}", other);
662            }
663        }
664        Ok(())
665    }
666
667    fn register_dwarf_section(&mut self, section: &CustomSectionReader<'data>) {
668        let name = section.name();
669        if !name.starts_with(".debug_") {
670            return;
671        }
672        if !self.tunables.generate_native_debuginfo && !self.tunables.parse_wasm_debuginfo {
673            self.result.has_unparsed_debuginfo = true;
674            return;
675        }
676        let info = &mut self.result.debuginfo;
677        let dwarf = &mut info.dwarf;
678        let endian = gimli::LittleEndian;
679        let data = section.data();
680        let slice = gimli::EndianSlice::new(data, endian);
681
682        match name {
683            // `gimli::Dwarf` fields.
684            ".debug_abbrev" => dwarf.debug_abbrev = gimli::DebugAbbrev::new(data, endian),
685            ".debug_addr" => dwarf.debug_addr = gimli::DebugAddr::from(slice),
686            ".debug_info" => dwarf.debug_info = gimli::DebugInfo::new(data, endian),
687            ".debug_line" => dwarf.debug_line = gimli::DebugLine::new(data, endian),
688            ".debug_line_str" => dwarf.debug_line_str = gimli::DebugLineStr::from(slice),
689            ".debug_str" => dwarf.debug_str = gimli::DebugStr::new(data, endian),
690            ".debug_str_offsets" => dwarf.debug_str_offsets = gimli::DebugStrOffsets::from(slice),
691            ".debug_str_sup" => {
692                let mut dwarf_sup: Dwarf<'data> = Default::default();
693                dwarf_sup.debug_str = gimli::DebugStr::from(slice);
694                dwarf.sup = Some(Arc::new(dwarf_sup));
695            }
696            ".debug_types" => dwarf.debug_types = gimli::DebugTypes::from(slice),
697
698            // Additional fields.
699            ".debug_loc" => info.debug_loc = gimli::DebugLoc::from(slice),
700            ".debug_loclists" => info.debug_loclists = gimli::DebugLocLists::from(slice),
701            ".debug_ranges" => info.debug_ranges = gimli::DebugRanges::new(data, endian),
702            ".debug_rnglists" => info.debug_rnglists = gimli::DebugRngLists::new(data, endian),
703
704            // We don't use these at the moment.
705            ".debug_aranges" | ".debug_pubnames" | ".debug_pubtypes" => return,
706
707            other => {
708                log::warn!("unknown debug section `{}`", other);
709                return;
710            }
711        }
712
713        dwarf.ranges = gimli::RangeLists::new(info.debug_ranges, info.debug_rnglists);
714        dwarf.locations = gimli::LocationLists::new(info.debug_loc, info.debug_loclists);
715    }
716
717    /// Declares a new import with the `module` and `field` names, importing the
718    /// `ty` specified.
719    ///
720    /// Note that this method is somewhat tricky due to the implementation of
721    /// the module linking proposal. In the module linking proposal two-level
722    /// imports are recast as single-level imports of instances. That recasting
723    /// happens here by recording an import of an instance for the first time
724    /// we see a two-level import.
725    ///
726    /// When the module linking proposal is disabled, however, disregard this
727    /// logic and instead work directly with two-level imports since no
728    /// instances are defined.
729    fn declare_import(&mut self, module: &'data str, field: &'data str, ty: EntityType) {
730        let index = self.push_type(ty);
731        self.result.module.initializers.push(Initializer::Import {
732            name: module.to_owned(),
733            field: field.to_owned(),
734            index,
735        });
736    }
737
738    fn push_type(&mut self, ty: EntityType) -> EntityIndex {
739        match ty {
740            EntityType::Function(ty) => EntityIndex::Function(self.result.module.push_function(ty)),
741            EntityType::Table(ty) => {
742                let plan = TablePlan::for_table(ty, &self.tunables);
743                EntityIndex::Table(self.result.module.table_plans.push(plan))
744            }
745            EntityType::Memory(ty) => {
746                let plan = MemoryPlan::for_memory(ty, &self.tunables);
747                EntityIndex::Memory(self.result.module.memory_plans.push(plan))
748            }
749            EntityType::Global(ty) => EntityIndex::Global(self.result.module.globals.push(ty)),
750            EntityType::Tag(_) => unimplemented!(),
751        }
752    }
753
754    fn flag_func_escaped(&mut self, func: FuncIndex) {
755        let ty = &mut self.result.module.functions[func];
756        // If this was already assigned an anyfunc index no need to re-assign it.
757        if ty.is_escaping() {
758            return;
759        }
760        let index = self.result.module.num_escaped_funcs as u32;
761        ty.anyfunc = AnyfuncIndex::from_u32(index);
762        self.result.module.num_escaped_funcs += 1;
763    }
764
765    fn declare_type_func(&mut self, wasm: WasmFuncType) -> WasmResult<()> {
766        let sig_index = self.types.wasm_func_type(wasm);
767        self.result
768            .module
769            .types
770            .push(ModuleType::Function(sig_index));
771        Ok(())
772    }
773
774    /// Parses the Name section of the wasm module.
775    fn name_section(&mut self, names: NameSectionReader<'data>) -> WasmResult<()> {
776        for subsection in names {
777            match subsection? {
778                wasmparser::Name::Function(names) => {
779                    for name in names {
780                        let Naming { index, name } = name?;
781                        // Skip this naming if it's naming a function that
782                        // doesn't actually exist.
783                        if (index as usize) >= self.result.module.functions.len() {
784                            continue;
785                        }
786
787                        // Store the name unconditionally, regardless of
788                        // whether we're parsing debuginfo, since function
789                        // names are almost always present in the
790                        // final compilation artifact.
791                        let index = FuncIndex::from_u32(index);
792                        self.result
793                            .debuginfo
794                            .name_section
795                            .func_names
796                            .insert(index, name);
797                    }
798                }
799                wasmparser::Name::Module { name, .. } => {
800                    self.result.module.name = Some(name.to_string());
801                    if self.tunables.generate_native_debuginfo {
802                        self.result.debuginfo.name_section.module_name = Some(name);
803                    }
804                }
805                wasmparser::Name::Local(reader) => {
806                    if !self.tunables.generate_native_debuginfo {
807                        continue;
808                    }
809                    for f in reader {
810                        let f = f?;
811                        // Skip this naming if it's naming a function that
812                        // doesn't actually exist.
813                        if (f.index as usize) >= self.result.module.functions.len() {
814                            continue;
815                        }
816                        for name in f.names {
817                            let Naming { index, name } = name?;
818
819                            self.result
820                                .debuginfo
821                                .name_section
822                                .locals_names
823                                .entry(FuncIndex::from_u32(f.index))
824                                .or_insert(HashMap::new())
825                                .insert(index, name);
826                        }
827                    }
828                }
829                wasmparser::Name::Label(_)
830                | wasmparser::Name::Type(_)
831                | wasmparser::Name::Table(_)
832                | wasmparser::Name::Global(_)
833                | wasmparser::Name::Memory(_)
834                | wasmparser::Name::Element(_)
835                | wasmparser::Name::Data(_)
836                | wasmparser::Name::Unknown { .. } => {}
837            }
838        }
839        Ok(())
840    }
841}