wasmparser/readers/core/
custom.rs

1use crate::{BinaryReader, Result};
2use core::fmt;
3use core::ops::Range;
4
5/// A reader for custom sections of a WebAssembly module.
6#[derive(Clone)]
7pub struct CustomSectionReader<'a> {
8    name: &'a str,
9    reader: BinaryReader<'a>,
10}
11
12impl<'a> CustomSectionReader<'a> {
13    /// Constructs a new `CustomSectionReader` for the given data and offset.
14    pub fn new(mut reader: BinaryReader<'a>) -> Result<CustomSectionReader<'a>> {
15        let name = reader.read_string()?;
16        Ok(CustomSectionReader { name, reader })
17    }
18
19    /// The name of the custom section.
20    pub fn name(&self) -> &'a str {
21        self.name
22    }
23
24    /// The offset, relative to the start of the original module or component,
25    /// that the `data` payload for this custom section starts at.
26    pub fn data_offset(&self) -> usize {
27        self.reader.original_position()
28    }
29
30    /// The actual contents of the custom section.
31    pub fn data(&self) -> &'a [u8] {
32        self.reader.remaining_buffer()
33    }
34
35    /// The range of bytes that specify this whole custom section (including
36    /// both the name of this custom section and its data) specified in
37    /// offsets relative to the start of the byte stream.
38    pub fn range(&self) -> Range<usize> {
39        self.reader.range()
40    }
41
42    /// Attempts to match and see if this custom section is statically known to
43    /// `wasmparser` with any known section reader.
44    ///
45    /// This will inspect `self.name()` and return a [`KnownCustom`] if the name
46    /// matches a known custom section where there is a parser available for it.
47    /// This can also be used as a convenience function for creating such
48    /// parsers.
49    ///
50    /// If the custom section name is not known, or if a reader could not be
51    /// created, then `KnownCustom::Unknown` is returned.
52    pub fn as_known(&self) -> KnownCustom<'a> {
53        match self.name() {
54            "name" => KnownCustom::Name(crate::NameSectionReader::new(self.reader.shrink())),
55            "component-name" => KnownCustom::ComponentName(crate::ComponentNameSectionReader::new(
56                self.reader.shrink(),
57            )),
58            "metadata.code.branch_hint" => {
59                match crate::BranchHintSectionReader::new(self.reader.shrink()) {
60                    Ok(s) => KnownCustom::BranchHints(s),
61                    Err(_) => KnownCustom::Unknown,
62                }
63            }
64            "producers" => match crate::ProducersSectionReader::new(self.reader.shrink()) {
65                Ok(s) => KnownCustom::Producers(s),
66                Err(_) => KnownCustom::Unknown,
67            },
68            "dylink.0" => {
69                KnownCustom::Dylink0(crate::Dylink0SectionReader::new(self.reader.shrink()))
70            }
71            "core" => match crate::CoreDumpSection::new(self.reader.shrink()) {
72                Ok(s) => KnownCustom::CoreDump(s),
73                Err(_) => KnownCustom::Unknown,
74            },
75            "coremodules" => match crate::CoreDumpModulesSection::new(self.reader.shrink()) {
76                Ok(s) => KnownCustom::CoreDumpModules(s),
77                Err(_) => KnownCustom::Unknown,
78            },
79            "coreinstances" => match crate::CoreDumpInstancesSection::new(self.reader.shrink()) {
80                Ok(s) => KnownCustom::CoreDumpInstances(s),
81                Err(_) => KnownCustom::Unknown,
82            },
83            "corestack" => match crate::CoreDumpStackSection::new(self.reader.shrink()) {
84                Ok(s) => KnownCustom::CoreDumpStack(s),
85                Err(_) => KnownCustom::Unknown,
86            },
87            "linking" => match crate::LinkingSectionReader::new(self.reader.shrink()) {
88                Ok(s) => KnownCustom::Linking(s),
89                Err(_) => KnownCustom::Unknown,
90            },
91            s if s.starts_with("reloc.") => {
92                match crate::RelocSectionReader::new(self.reader.shrink()) {
93                    Ok(s) => KnownCustom::Reloc(s),
94                    Err(_) => KnownCustom::Unknown,
95                }
96            }
97            _ => KnownCustom::Unknown,
98        }
99    }
100}
101
102/// Return value of [`CustomSectionReader::as_known`].
103#[allow(missing_docs)]
104pub enum KnownCustom<'a> {
105    Name(crate::NameSectionReader<'a>),
106    ComponentName(crate::ComponentNameSectionReader<'a>),
107    BranchHints(crate::BranchHintSectionReader<'a>),
108    Producers(crate::ProducersSectionReader<'a>),
109    Dylink0(crate::Dylink0SectionReader<'a>),
110    CoreDump(crate::CoreDumpSection<'a>),
111    CoreDumpStack(crate::CoreDumpStackSection<'a>),
112    CoreDumpInstances(crate::CoreDumpInstancesSection),
113    CoreDumpModules(crate::CoreDumpModulesSection<'a>),
114    Linking(crate::LinkingSectionReader<'a>),
115    Reloc(crate::RelocSectionReader<'a>),
116    Unknown,
117}
118
119impl<'a> fmt::Debug for CustomSectionReader<'a> {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        f.debug_struct("CustomSectionReader")
122            .field("name", &self.name)
123            .field("data_offset", &self.data_offset())
124            .field("data", &"...")
125            .field("range", &self.range())
126            .finish()
127    }
128}