/src/wasm-tools/crates/wasm-mutate/src/info.rs
Line | Count | Source |
1 | | use crate::{ |
2 | | Error, Result, |
3 | | module::{PrimitiveTypeInfo, TypeInfo}, |
4 | | }; |
5 | | use std::{collections::HashSet, ops::Range}; |
6 | | use wasm_encoder::{RawSection, SectionId}; |
7 | | use wasmparser::{BinaryReader, Chunk, Parser, Payload}; |
8 | | |
9 | | /// Provides module information for future usage during mutation |
10 | | /// an instance of ModuleInfo could be user to determine which mutation could be applied |
11 | | #[derive(Default, Clone, Debug)] |
12 | | pub struct ModuleInfo<'a> { |
13 | | // The following fields are offsets inside the `raw_sections` field. |
14 | | // The main idea is to maintain the order of the sections in the input Wasm. |
15 | | pub exports: Option<usize>, |
16 | | pub export_names: HashSet<String>, |
17 | | |
18 | | // Indices of various sections within `self.raw_sections`. |
19 | | pub types: Option<usize>, |
20 | | pub imports: Option<usize>, |
21 | | pub tables: Option<usize>, |
22 | | pub memories: Option<usize>, |
23 | | pub globals: Option<usize>, |
24 | | pub elements: Option<usize>, |
25 | | pub functions: Option<usize>, |
26 | | pub data_count: Option<usize>, |
27 | | pub data: Option<usize>, |
28 | | pub code: Option<usize>, |
29 | | pub start: Option<usize>, |
30 | | |
31 | | pub exports_count: u32, |
32 | | elements_count: u32, |
33 | | data_segments_count: u32, |
34 | | start_function: Option<u32>, |
35 | | memory_count: u32, |
36 | | table_count: u32, |
37 | | tag_count: u32, |
38 | | |
39 | | imported_functions_count: u32, |
40 | | imported_globals_count: u32, |
41 | | imported_memories_count: u32, |
42 | | imported_tables_count: u32, |
43 | | imported_tags_count: u32, |
44 | | |
45 | | // types for inner functions |
46 | | pub types_map: Vec<TypeInfo>, |
47 | | |
48 | | // function idx to type idx |
49 | | pub function_map: Vec<u32>, |
50 | | pub global_types: Vec<PrimitiveTypeInfo>, |
51 | | pub table_types: Vec<wasmparser::TableType>, |
52 | | pub memory_types: Vec<wasmparser::MemoryType>, |
53 | | |
54 | | // raw_sections |
55 | | pub raw_sections: Vec<RawSection<'a>>, |
56 | | pub input_wasm: &'a [u8], |
57 | | } |
58 | | |
59 | | impl<'a> ModuleInfo<'a> { |
60 | | /// Parse the given Wasm bytes and fill out a `ModuleInfo` AST for it. |
61 | 3.86k | pub fn new(input_wasm: &[u8]) -> Result<ModuleInfo<'_>> { |
62 | 3.86k | let mut parser = Parser::new(0); |
63 | 3.86k | let mut info = ModuleInfo::default(); |
64 | 3.86k | let mut wasm = input_wasm; |
65 | 3.86k | info.input_wasm = wasm; |
66 | | |
67 | | loop { |
68 | | // Convert into a range into the wasm input |
69 | 27.5k | let offset = parser.offset(); |
70 | 27.5k | let get_input_data = |range: &Range<u64>| { |
71 | 20.2k | &wasm[(range.start - offset) as usize..(range.end - offset) as usize] |
72 | 20.2k | }; |
73 | 27.5k | let (payload, consumed) = match parser.parse(wasm, true)? { |
74 | 0 | Chunk::NeedMoreData(hint) => { |
75 | 0 | panic!("Invalid Wasm module {hint:?}"); |
76 | | } |
77 | 27.5k | Chunk::Parsed { consumed, payload } => (payload, consumed), |
78 | | }; |
79 | 27.5k | match payload { |
80 | | Payload::CodeSectionStart { |
81 | | count: _, |
82 | 2.48k | range, |
83 | | size: _, |
84 | | } => { |
85 | 2.48k | info.code = Some(info.raw_sections.len()); |
86 | 2.48k | info.section(SectionId::Code.into(), get_input_data(&range)); |
87 | 2.48k | parser.skip_section(); |
88 | | // update slice, bypass the section |
89 | 2.48k | wasm = &wasm[(range.end - offset) as usize..]; |
90 | | |
91 | 2.48k | continue; |
92 | | } |
93 | 3.41k | Payload::TypeSection(reader) => { |
94 | 3.41k | info.types = Some(info.raw_sections.len()); |
95 | 3.41k | info.section(SectionId::Type.into(), get_input_data(&reader.range())); |
96 | | |
97 | | // Save function types |
98 | 24.0k | for ty in reader.into_iter_err_on_gc_types() { |
99 | 24.0k | info.types_map.push(ty?.try_into()?); |
100 | | } |
101 | | } |
102 | 2.29k | Payload::ImportSection(reader) => { |
103 | 2.29k | info.imports = Some(info.raw_sections.len()); |
104 | 2.29k | info.section(SectionId::Import.into(), get_input_data(&reader.range())); |
105 | | |
106 | 25.1k | for ty in reader.into_imports() { |
107 | 25.1k | match ty?.ty { |
108 | 8.10k | wasmparser::TypeRef::Func(ty) | wasmparser::TypeRef::FuncExact(ty) => { |
109 | 8.10k | // Save imported functions |
110 | 8.10k | info.function_map.push(ty); |
111 | 8.10k | info.imported_functions_count += 1; |
112 | 8.10k | } |
113 | 11.6k | wasmparser::TypeRef::Global(ty) => { |
114 | 11.6k | let ty = PrimitiveTypeInfo::try_from(ty.content_type)?; |
115 | 11.5k | info.global_types.push(ty); |
116 | 11.5k | info.imported_globals_count += 1; |
117 | | } |
118 | 1.99k | wasmparser::TypeRef::Memory(ty) => { |
119 | 1.99k | info.memory_count += 1; |
120 | 1.99k | info.imported_memories_count += 1; |
121 | 1.99k | info.memory_types.push(ty); |
122 | 1.99k | } |
123 | 2.14k | wasmparser::TypeRef::Table(ty) => { |
124 | 2.14k | info.table_count += 1; |
125 | 2.14k | info.imported_tables_count += 1; |
126 | 2.14k | info.table_types.push(ty); |
127 | 2.14k | } |
128 | 1.32k | wasmparser::TypeRef::Tag(_ty) => { |
129 | 1.32k | info.tag_count += 1; |
130 | 1.32k | info.imported_tags_count += 1; |
131 | 1.32k | } |
132 | | } |
133 | | } |
134 | | } |
135 | 2.49k | Payload::FunctionSection(reader) => { |
136 | 2.49k | info.functions = Some(info.raw_sections.len()); |
137 | 2.49k | info.section(SectionId::Function.into(), get_input_data(&reader.range())); |
138 | | |
139 | 62.2k | for ty in reader { |
140 | 62.2k | info.function_map.push(ty?); |
141 | | } |
142 | | } |
143 | 1.35k | Payload::TableSection(reader) => { |
144 | 1.35k | info.tables = Some(info.raw_sections.len()); |
145 | 1.35k | info.table_count += reader.count(); |
146 | 1.35k | info.section(SectionId::Table.into(), get_input_data(&reader.range())); |
147 | | |
148 | 5.78k | for table in reader { |
149 | 5.78k | let table = table?; |
150 | 5.78k | info.table_types.push(table.ty); |
151 | | } |
152 | | } |
153 | 1.61k | Payload::MemorySection(reader) => { |
154 | 1.61k | info.memories = Some(info.raw_sections.len()); |
155 | 1.61k | info.memory_count += reader.count(); |
156 | 1.61k | info.section(SectionId::Memory.into(), get_input_data(&reader.range())); |
157 | | |
158 | 11.0k | for ty in reader { |
159 | 11.0k | info.memory_types.push(ty?); |
160 | | } |
161 | | } |
162 | 194 | Payload::TagSection(reader) => { |
163 | 194 | info.tag_count += reader.count(); |
164 | 194 | info.section(SectionId::Tag.into(), get_input_data(&reader.range())); |
165 | 194 | } |
166 | 2.39k | Payload::GlobalSection(reader) => { |
167 | 2.39k | info.globals = Some(info.raw_sections.len()); |
168 | 2.39k | info.section(SectionId::Global.into(), get_input_data(&reader.range())); |
169 | | |
170 | 35.5k | for ty in reader { |
171 | 35.5k | let ty = ty?; |
172 | | // We only need the type of the global, not necessarily if is mutable or not |
173 | 35.5k | let ty = PrimitiveTypeInfo::try_from(ty.ty.content_type)?; |
174 | 35.5k | info.global_types.push(ty); |
175 | | } |
176 | | } |
177 | 1.37k | Payload::ExportSection(reader) => { |
178 | 1.37k | info.exports = Some(info.raw_sections.len()); |
179 | 1.37k | info.exports_count = reader.count(); |
180 | | |
181 | 15.4k | for entry in reader.clone() { |
182 | 15.4k | info.export_names.insert(entry?.name.into()); |
183 | | } |
184 | | |
185 | 1.37k | info.section(SectionId::Export.into(), get_input_data(&reader.range())); |
186 | | } |
187 | 280 | Payload::StartSection { func, range } => { |
188 | 280 | info.start = Some(info.raw_sections.len()); |
189 | 280 | info.start_function = Some(func); |
190 | 280 | info.section(SectionId::Start.into(), get_input_data(&range)); |
191 | 280 | } |
192 | 850 | Payload::ElementSection(reader) => { |
193 | 850 | info.elements = Some(info.raw_sections.len()); |
194 | 850 | info.elements_count = reader.count(); |
195 | 850 | info.section(SectionId::Element.into(), get_input_data(&reader.range())); |
196 | 850 | } |
197 | 884 | Payload::DataSection(reader) => { |
198 | 884 | info.data = Some(info.raw_sections.len()); |
199 | 884 | info.data_segments_count = reader.count(); |
200 | 884 | info.section(SectionId::Data.into(), get_input_data(&reader.range())); |
201 | 884 | } |
202 | 0 | Payload::CustomSection(c) => { |
203 | 0 | info.section(SectionId::Custom.into(), get_input_data(&c.range())); |
204 | 0 | } |
205 | | Payload::UnknownSection { |
206 | 0 | id, |
207 | | contents: _, |
208 | 0 | range, |
209 | 0 | } => { |
210 | 0 | info.section(id, get_input_data(&range)); |
211 | 0 | } |
212 | 648 | Payload::DataCountSection { count: _, range } => { |
213 | 648 | info.data_count = Some(info.raw_sections.len()); |
214 | 648 | info.section(SectionId::DataCount.into(), get_input_data(&range)); |
215 | 648 | } |
216 | 3.86k | Payload::Version { .. } => {} |
217 | | Payload::End(_) => { |
218 | 3.36k | break; |
219 | | } |
220 | 0 | _ => return Err(Error::unsupported(format!("section: {payload:?}"))), |
221 | | } |
222 | 21.1k | wasm = &wasm[consumed..]; |
223 | | } |
224 | | |
225 | 3.36k | Ok(info) |
226 | 3.86k | } |
227 | | |
228 | 86 | pub fn has_nonempty_code(&self) -> bool { |
229 | 86 | if let Some(section) = self.code { |
230 | 22 | let section_data = self.raw_sections[section].data; |
231 | 22 | let reader = BinaryReader::new(section_data, 0); |
232 | 22 | wasmparser::CodeSectionReader::new(reader) |
233 | 22 | .map(|r| r.count() != 0) |
234 | 22 | .unwrap_or(false) |
235 | | } else { |
236 | 64 | false |
237 | | } |
238 | 86 | } |
239 | | |
240 | 1.44k | pub fn has_code(&self) -> bool { |
241 | 1.44k | self.code != None |
242 | 1.44k | } |
243 | | |
244 | | /// Does this module have any custom sections? |
245 | 451 | pub fn has_custom_section(&self) -> bool { |
246 | 451 | self.raw_sections |
247 | 451 | .iter() |
248 | 2.11k | .any(|s| s.id == SectionId::Custom as u8) |
249 | 451 | } |
250 | | |
251 | | /// Registers a new raw_section in the ModuleInfo |
252 | 20.2k | pub fn section(&mut self, id: u8, data: &'a [u8]) { |
253 | 20.2k | self.raw_sections.push(RawSection { id, data }); |
254 | 20.2k | } |
255 | | |
256 | 1.14k | pub fn get_code_section(&self) -> RawSection<'a> { |
257 | 1.14k | self.raw_sections[self.code.unwrap()] |
258 | 1.14k | } |
259 | | |
260 | 15.7k | pub fn get_binary_reader(&self, i: usize) -> wasmparser::BinaryReader<'a> { |
261 | 15.7k | BinaryReader::new(self.raw_sections[i].data, 0) |
262 | 15.7k | } |
263 | | |
264 | 95 | pub fn has_exports(&self) -> bool { |
265 | 95 | self.exports != None |
266 | 95 | } |
267 | | |
268 | | /// Returns the function type based on the index of the function type |
269 | | /// `types[functions[idx]]` |
270 | 2.12k | pub fn get_functype_idx(&self, idx: u32) -> &TypeInfo { |
271 | 2.12k | let functpeindex = self.function_map[idx as usize] as usize; |
272 | 2.12k | &self.types_map[functpeindex] |
273 | 2.12k | } |
274 | | |
275 | | /// Returns the number of globals used by the Wasm binary including imported |
276 | | /// glboals |
277 | 40.5k | pub fn get_global_count(&self) -> usize { |
278 | 40.5k | self.global_types.len() |
279 | 40.5k | } |
280 | | |
281 | | /// Insert a new section as the `i`th section in the Wasm module. |
282 | 428 | pub fn insert_section( |
283 | 428 | &self, |
284 | 428 | i: usize, |
285 | 428 | new_section: &impl wasm_encoder::Section, |
286 | 428 | ) -> wasm_encoder::Module { |
287 | 428 | log::trace!("inserting new section at {i}"); |
288 | 428 | let mut module = wasm_encoder::Module::new(); |
289 | 1.31k | self.raw_sections.iter().enumerate().for_each(|(j, s)| { |
290 | 1.31k | if i == j { |
291 | 263 | module.section(new_section); |
292 | 1.05k | } |
293 | 1.31k | module.section(s); |
294 | 1.31k | }); <wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::types::TypeSection>::{closure#0}Line | Count | Source | 289 | 115 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | 115 | if i == j { | 291 | 48 | module.section(new_section); | 292 | 67 | } | 293 | 115 | module.section(s); | 294 | 115 | }); |
<wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::custom::CustomSection>::{closure#0}Line | Count | Source | 289 | 1.04k | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | 1.04k | if i == j { | 291 | 197 | module.section(new_section); | 292 | 844 | } | 293 | 1.04k | module.section(s); | 294 | 1.04k | }); |
<wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::exports::ExportSection>::{closure#0}Line | Count | Source | 289 | 103 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | 103 | if i == j { | 291 | 8 | module.section(new_section); | 292 | 95 | } | 293 | 103 | module.section(s); | 294 | 103 | }); |
<wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::globals::GlobalSection>::{closure#0}Line | Count | Source | 289 | 60 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | 60 | if i == j { | 291 | 10 | module.section(new_section); | 292 | 50 | } | 293 | 60 | module.section(s); | 294 | 60 | }); |
|
295 | 428 | if self.raw_sections.len() == i { |
296 | 165 | module.section(new_section); |
297 | 263 | } |
298 | 428 | module |
299 | 428 | } <wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::types::TypeSection> Line | Count | Source | 282 | 101 | pub fn insert_section( | 283 | 101 | &self, | 284 | 101 | i: usize, | 285 | 101 | new_section: &impl wasm_encoder::Section, | 286 | 101 | ) -> wasm_encoder::Module { | 287 | 101 | log::trace!("inserting new section at {i}"); | 288 | 101 | let mut module = wasm_encoder::Module::new(); | 289 | 101 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | | if i == j { | 291 | | module.section(new_section); | 292 | | } | 293 | | module.section(s); | 294 | | }); | 295 | 101 | if self.raw_sections.len() == i { | 296 | 53 | module.section(new_section); | 297 | 53 | } | 298 | 101 | module | 299 | 101 | } |
<wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::custom::CustomSection> Line | Count | Source | 282 | 275 | pub fn insert_section( | 283 | 275 | &self, | 284 | 275 | i: usize, | 285 | 275 | new_section: &impl wasm_encoder::Section, | 286 | 275 | ) -> wasm_encoder::Module { | 287 | 275 | log::trace!("inserting new section at {i}"); | 288 | 275 | let mut module = wasm_encoder::Module::new(); | 289 | 275 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | | if i == j { | 291 | | module.section(new_section); | 292 | | } | 293 | | module.section(s); | 294 | | }); | 295 | 275 | if self.raw_sections.len() == i { | 296 | 78 | module.section(new_section); | 297 | 197 | } | 298 | 275 | module | 299 | 275 | } |
<wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::exports::ExportSection> Line | Count | Source | 282 | 35 | pub fn insert_section( | 283 | 35 | &self, | 284 | 35 | i: usize, | 285 | 35 | new_section: &impl wasm_encoder::Section, | 286 | 35 | ) -> wasm_encoder::Module { | 287 | 35 | log::trace!("inserting new section at {i}"); | 288 | 35 | let mut module = wasm_encoder::Module::new(); | 289 | 35 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | | if i == j { | 291 | | module.section(new_section); | 292 | | } | 293 | | module.section(s); | 294 | | }); | 295 | 35 | if self.raw_sections.len() == i { | 296 | 27 | module.section(new_section); | 297 | 27 | } | 298 | 35 | module | 299 | 35 | } |
<wasm_mutate::info::ModuleInfo>::insert_section::<wasm_encoder::core::globals::GlobalSection> Line | Count | Source | 282 | 17 | pub fn insert_section( | 283 | 17 | &self, | 284 | 17 | i: usize, | 285 | 17 | new_section: &impl wasm_encoder::Section, | 286 | 17 | ) -> wasm_encoder::Module { | 287 | 17 | log::trace!("inserting new section at {i}"); | 288 | 17 | let mut module = wasm_encoder::Module::new(); | 289 | 17 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 290 | | if i == j { | 291 | | module.section(new_section); | 292 | | } | 293 | | module.section(s); | 294 | | }); | 295 | 17 | if self.raw_sections.len() == i { | 296 | 7 | module.section(new_section); | 297 | 10 | } | 298 | 17 | module | 299 | 17 | } |
|
300 | | |
301 | | /// Move a section from index `src_idx` to `dest_idx` in the Wasm module |
302 | 0 | pub fn move_section(&self, src_idx: usize, dest_idx: usize) -> wasm_encoder::Module { |
303 | 0 | log::trace!("moving section from index {src_idx} to index {dest_idx}"); |
304 | 0 | assert!(src_idx < self.raw_sections.len()); |
305 | 0 | assert!(dest_idx < self.raw_sections.len()); |
306 | 0 | assert_ne!(src_idx, dest_idx); |
307 | 0 | let mut sections = self.raw_sections.clone(); |
308 | 0 | let to_move = sections.remove(src_idx); |
309 | 0 | let mut module = wasm_encoder::Module::new(); |
310 | 0 | for (i, section) in sections.iter().enumerate() { |
311 | 0 | if i == dest_idx { |
312 | 0 | module.section(&to_move); |
313 | 0 | } |
314 | 0 | module.section(section); |
315 | | } |
316 | 0 | if sections.len() == dest_idx { |
317 | 0 | module.section(&to_move); |
318 | 0 | } |
319 | 0 | module |
320 | 0 | } |
321 | | |
322 | | /// Replace the `i`th section in this module with the given new section. |
323 | 527 | pub fn replace_section( |
324 | 527 | &self, |
325 | 527 | i: usize, |
326 | 527 | new_section: &impl wasm_encoder::Section, |
327 | 527 | ) -> wasm_encoder::Module { |
328 | 527 | log::trace!("replacing section {i}"); |
329 | 527 | let mut module = wasm_encoder::Module::new(); |
330 | 3.12k | for (j, s) in self.raw_sections.iter().enumerate() { |
331 | 3.12k | if i == j { |
332 | 527 | module.section(new_section); |
333 | 2.59k | } else { |
334 | 2.59k | module.section(s); |
335 | 2.59k | } |
336 | | } |
337 | 527 | module |
338 | 527 | } <wasm_mutate::info::ModuleInfo>::replace_section::<wasm_encoder::core::code::CodeSection> Line | Count | Source | 323 | 178 | pub fn replace_section( | 324 | 178 | &self, | 325 | 178 | i: usize, | 326 | 178 | new_section: &impl wasm_encoder::Section, | 327 | 178 | ) -> wasm_encoder::Module { | 328 | 178 | log::trace!("replacing section {i}"); | 329 | 178 | let mut module = wasm_encoder::Module::new(); | 330 | 1.17k | for (j, s) in self.raw_sections.iter().enumerate() { | 331 | 1.17k | if i == j { | 332 | 178 | module.section(new_section); | 333 | 994 | } else { | 334 | 994 | module.section(s); | 335 | 994 | } | 336 | | } | 337 | 178 | module | 338 | 178 | } |
<wasm_mutate::info::ModuleInfo>::replace_section::<wasm_encoder::core::data::DataSection> Line | Count | Source | 323 | 28 | pub fn replace_section( | 324 | 28 | &self, | 325 | 28 | i: usize, | 326 | 28 | new_section: &impl wasm_encoder::Section, | 327 | 28 | ) -> wasm_encoder::Module { | 328 | 28 | log::trace!("replacing section {i}"); | 329 | 28 | let mut module = wasm_encoder::Module::new(); | 330 | 174 | for (j, s) in self.raw_sections.iter().enumerate() { | 331 | 174 | if i == j { | 332 | 28 | module.section(new_section); | 333 | 146 | } else { | 334 | 146 | module.section(s); | 335 | 146 | } | 336 | | } | 337 | 28 | module | 338 | 28 | } |
<wasm_mutate::info::ModuleInfo>::replace_section::<wasm_encoder::core::types::TypeSection> Line | Count | Source | 323 | 229 | pub fn replace_section( | 324 | 229 | &self, | 325 | 229 | i: usize, | 326 | 229 | new_section: &impl wasm_encoder::Section, | 327 | 229 | ) -> wasm_encoder::Module { | 328 | 229 | log::trace!("replacing section {i}"); | 329 | 229 | let mut module = wasm_encoder::Module::new(); | 330 | 1.26k | for (j, s) in self.raw_sections.iter().enumerate() { | 331 | 1.26k | if i == j { | 332 | 229 | module.section(new_section); | 333 | 1.03k | } else { | 334 | 1.03k | module.section(s); | 335 | 1.03k | } | 336 | | } | 337 | 229 | module | 338 | 229 | } |
Unexecuted instantiation: <wasm_mutate::info::ModuleInfo>::replace_section::<wasm_encoder::core::custom::CustomSection> <wasm_mutate::info::ModuleInfo>::replace_section::<wasm_encoder::core::exports::ExportSection> Line | Count | Source | 323 | 33 | pub fn replace_section( | 324 | 33 | &self, | 325 | 33 | i: usize, | 326 | 33 | new_section: &impl wasm_encoder::Section, | 327 | 33 | ) -> wasm_encoder::Module { | 328 | 33 | log::trace!("replacing section {i}"); | 329 | 33 | let mut module = wasm_encoder::Module::new(); | 330 | 206 | for (j, s) in self.raw_sections.iter().enumerate() { | 331 | 206 | if i == j { | 332 | 33 | module.section(new_section); | 333 | 173 | } else { | 334 | 173 | module.section(s); | 335 | 173 | } | 336 | | } | 337 | 33 | module | 338 | 33 | } |
<wasm_mutate::info::ModuleInfo>::replace_section::<wasm_encoder::core::globals::GlobalSection> Line | Count | Source | 323 | 59 | pub fn replace_section( | 324 | 59 | &self, | 325 | 59 | i: usize, | 326 | 59 | new_section: &impl wasm_encoder::Section, | 327 | 59 | ) -> wasm_encoder::Module { | 328 | 59 | log::trace!("replacing section {i}"); | 329 | 59 | let mut module = wasm_encoder::Module::new(); | 330 | 304 | for (j, s) in self.raw_sections.iter().enumerate() { | 331 | 304 | if i == j { | 332 | 59 | module.section(new_section); | 333 | 245 | } else { | 334 | 245 | module.section(s); | 335 | 245 | } | 336 | | } | 337 | 59 | module | 338 | 59 | } |
Unexecuted instantiation: <wasm_mutate::info::ModuleInfo>::replace_section::<wasm_encoder::core::elements::ElementSection> |
339 | | |
340 | | /// Replaces raw sections in the passed indexes and return a new module |
341 | | /// |
342 | | /// This method will be helpful to add more than one custom section. For |
343 | | /// example, some code mutations might need to add a few globals. This |
344 | | /// method can be used to write a new or custom global section before the |
345 | | /// code section. |
346 | | /// * `section_writer` this callback should write the custom section and |
347 | | /// returns true if it was successful, if false is returned then the |
348 | | /// default section will be written to the module |
349 | 7.73k | pub fn replace_multiple_sections<P>(&self, mut section_writer: P) -> wasm_encoder::Module |
350 | 7.73k | where |
351 | 7.73k | P: FnMut(usize, u8, &mut wasm_encoder::Module) -> bool, |
352 | | { |
353 | 7.73k | let mut module = wasm_encoder::Module::new(); |
354 | 53.3k | self.raw_sections.iter().enumerate().for_each(|(j, s)| { |
355 | | // Write if the section_writer did not write a custom section |
356 | 53.3k | if !section_writer(j, s.id, &mut module) { |
357 | 39.2k | module.section(s); |
358 | 39.2k | } |
359 | 53.3k | }); <wasm_mutate::info::ModuleInfo>::replace_multiple_sections::<<wasm_mutate::mutators::peephole::PeepholeMutator>::random_mutate::{closure#1}::{closure#0}>::{closure#0}Line | Count | Source | 354 | 52.9k | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 355 | | // Write if the section_writer did not write a custom section | 356 | 52.9k | if !section_writer(j, s.id, &mut module) { | 357 | 38.9k | module.section(s); | 358 | 38.9k | } | 359 | 52.9k | }); |
<wasm_mutate::info::ModuleInfo>::replace_multiple_sections::<<wasm_mutate::mutators::add_function::AddFunctionMutator as wasm_mutate::mutators::Mutator>::mutate::{closure#0}>::{closure#0}Line | Count | Source | 354 | 348 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 355 | | // Write if the section_writer did not write a custom section | 356 | 348 | if !section_writer(j, s.id, &mut module) { | 357 | 238 | module.section(s); | 358 | 238 | } | 359 | 348 | }); |
<wasm_mutate::info::ModuleInfo>::replace_multiple_sections::<<wasm_mutate::mutators::add_function::AddFunctionMutator as wasm_mutate::mutators::Mutator>::mutate::{closure#1}>::{closure#0}Line | Count | Source | 354 | 48 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 355 | | // Write if the section_writer did not write a custom section | 356 | 48 | if !section_writer(j, s.id, &mut module) { | 357 | 48 | module.section(s); | 358 | 48 | } | 359 | 48 | }); |
|
360 | 7.73k | module |
361 | 7.73k | } <wasm_mutate::info::ModuleInfo>::replace_multiple_sections::<<wasm_mutate::mutators::peephole::PeepholeMutator>::random_mutate::{closure#1}::{closure#0}>Line | Count | Source | 349 | 7.66k | pub fn replace_multiple_sections<P>(&self, mut section_writer: P) -> wasm_encoder::Module | 350 | 7.66k | where | 351 | 7.66k | P: FnMut(usize, u8, &mut wasm_encoder::Module) -> bool, | 352 | | { | 353 | 7.66k | let mut module = wasm_encoder::Module::new(); | 354 | 7.66k | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 355 | | // Write if the section_writer did not write a custom section | 356 | | if !section_writer(j, s.id, &mut module) { | 357 | | module.section(s); | 358 | | } | 359 | | }); | 360 | 7.66k | module | 361 | 7.66k | } |
<wasm_mutate::info::ModuleInfo>::replace_multiple_sections::<<wasm_mutate::mutators::add_function::AddFunctionMutator as wasm_mutate::mutators::Mutator>::mutate::{closure#0}>Line | Count | Source | 349 | 55 | pub fn replace_multiple_sections<P>(&self, mut section_writer: P) -> wasm_encoder::Module | 350 | 55 | where | 351 | 55 | P: FnMut(usize, u8, &mut wasm_encoder::Module) -> bool, | 352 | | { | 353 | 55 | let mut module = wasm_encoder::Module::new(); | 354 | 55 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 355 | | // Write if the section_writer did not write a custom section | 356 | | if !section_writer(j, s.id, &mut module) { | 357 | | module.section(s); | 358 | | } | 359 | | }); | 360 | 55 | module | 361 | 55 | } |
<wasm_mutate::info::ModuleInfo>::replace_multiple_sections::<<wasm_mutate::mutators::add_function::AddFunctionMutator as wasm_mutate::mutators::Mutator>::mutate::{closure#1}>Line | Count | Source | 349 | 16 | pub fn replace_multiple_sections<P>(&self, mut section_writer: P) -> wasm_encoder::Module | 350 | 16 | where | 351 | 16 | P: FnMut(usize, u8, &mut wasm_encoder::Module) -> bool, | 352 | | { | 353 | 16 | let mut module = wasm_encoder::Module::new(); | 354 | 16 | self.raw_sections.iter().enumerate().for_each(|(j, s)| { | 355 | | // Write if the section_writer did not write a custom section | 356 | | if !section_writer(j, s.id, &mut module) { | 357 | | module.section(s); | 358 | | } | 359 | | }); | 360 | 16 | module | 361 | 16 | } |
|
362 | | |
363 | 2.53k | pub fn num_functions(&self) -> u32 { |
364 | 2.53k | self.function_map.len() as u32 |
365 | 2.53k | } |
366 | | |
367 | 1.14k | pub fn num_local_functions(&self) -> u32 { |
368 | 1.14k | self.num_functions() - self.num_imported_functions() |
369 | 1.14k | } |
370 | | |
371 | 5.04k | pub fn num_imported_functions(&self) -> u32 { |
372 | 5.04k | self.imported_functions_count |
373 | 5.04k | } |
374 | | |
375 | 509 | pub fn num_tables(&self) -> u32 { |
376 | 509 | self.table_count |
377 | 509 | } |
378 | | |
379 | 527 | pub fn num_imported_tables(&self) -> u32 { |
380 | 527 | self.imported_tables_count |
381 | 527 | } |
382 | | |
383 | 443 | pub fn num_memories(&self) -> u32 { |
384 | 443 | self.memory_count |
385 | 443 | } |
386 | | |
387 | 644 | pub fn num_imported_memories(&self) -> u32 { |
388 | 644 | self.imported_memories_count |
389 | 644 | } |
390 | | |
391 | 676 | pub fn num_globals(&self) -> u32 { |
392 | 676 | self.global_types.len() as u32 |
393 | 676 | } |
394 | | |
395 | 905 | pub fn num_imported_globals(&self) -> u32 { |
396 | 905 | self.imported_globals_count |
397 | 905 | } |
398 | | |
399 | 0 | pub fn num_local_globals(&self) -> u32 { |
400 | 0 | self.global_types.len() as u32 - self.imported_globals_count |
401 | 0 | } |
402 | | |
403 | 745 | pub fn num_tags(&self) -> u32 { |
404 | 745 | self.tag_count |
405 | 745 | } |
406 | | |
407 | 107 | pub fn num_imported_tags(&self) -> u32 { |
408 | 107 | self.imported_tags_count |
409 | 107 | } |
410 | | |
411 | 144 | pub fn num_data(&self) -> u32 { |
412 | 144 | self.data_segments_count |
413 | 144 | } |
414 | | |
415 | 64 | pub fn num_elements(&self) -> u32 { |
416 | 64 | self.elements_count |
417 | 64 | } |
418 | | |
419 | 578 | pub fn num_types(&self) -> u32 { |
420 | 578 | self.types_map.len() as u32 |
421 | 578 | } |
422 | | } |