1use crate::ast;
2use log::debug;
3use std::collections::HashMap;
4use std::sync::Arc;
5use std::sync::Mutex;
6use threadpool::ThreadPool;
7
8type BoxError = Box<dyn std::error::Error>;
9
10pub struct WasmModule {
11 pub inner: Arc<ast::Module>,
12 types: Mutex<HashMap<u32, ast::Type>>,
13 func_locals: HashMap<u32, Vec<ast::CodeLocal>>,
15 func_to_typeidx: Mutex<Vec<u32>>,
16 func_code: HashMap<u32, ast::Code>,
17 pub func_starts: HashMap<u32, usize>,
18 pub func_names: Mutex<HashMap<u32, String>>,
19 global_names: Mutex<HashMap<u32, String>>,
20 imports: Vec<ast::Import>,
21 globals: Vec<ast::Global>,
22 exports: Vec<ast::Export>,
23 custom_sections: Vec<ast::CustomSection>,
24 build_id: Option<Vec<u8>>,
25 imported_func_count: u32,
26}
27impl WasmModule {
28 pub fn new(inner: Arc<ast::Module>) -> Self {
29 let mut types = HashMap::new();
30 let mut func_locals = HashMap::new();
31 let mut func_to_typeidx = Vec::new();
32 let mut imports = Vec::new();
33 let mut globals = Vec::new();
34 let mut exports = Vec::new();
35 let mut custom_sections = Vec::new();
36 let mut func_starts = HashMap::new();
37 let mut func_code = HashMap::new();
38 let mut func_names = HashMap::new();
39 let mut global_names = HashMap::new();
40 let mut build_id = None;
41 let mut imported_func_count = 0;
42
43 let mut funcidx = 0;
44
45 for section in inner.sections.lock().unwrap().iter() {
46 match §ion.value {
47 ast::Section::Type((_size, content)) => {
48 let mut typeidx = 0;
49 for t in &*content.lock().unwrap() {
50 types.insert(typeidx, t.to_owned());
51 typeidx += 1;
52 }
53 }
54
55 ast::Section::Import((_size, content)) => {
56 imports = content.lock().unwrap().clone();
57
58 for import in &imports {
59 match import.import_type {
60 ast::ImportType::Func(_) => {
61 imported_func_count += 1;
62 funcidx += 1;
63 }
64 _ => {}
65 }
66 }
67 }
68
69 ast::Section::Global((_size, content)) => {
70 globals = content.lock().unwrap().clone();
71 }
72
73 ast::Section::Func((_size, content)) => {
74 func_to_typeidx = content.lock().unwrap().clone();
75 }
76
77 ast::Section::Export((_section_size, content)) => {
78 exports = content.lock().unwrap().clone();
79 }
80
81 ast::Section::Code((_section_size, content)) => {
82 for c in &content.lock().unwrap().value {
83 func_code.insert(funcidx, c.clone());
84
85 func_starts.insert(funcidx as u32, c.body.lock().unwrap().start_offset);
86 func_locals.insert(funcidx, c.locals.clone());
87 funcidx += 1;
88 }
89 }
90
91 ast::Section::Custom((_size, section)) => {
92 custom_sections.push(section.lock().unwrap().clone());
93
94 match &*section.lock().unwrap() {
95 ast::CustomSection::Name(names) => {
96 if let Some(v) = &names.func_names {
97 func_names = v.lock().unwrap().clone();
98 }
99
100 global_names = names.global_names.lock().unwrap().clone();
101 }
102 ast::CustomSection::BuildId(id) => {
103 build_id = Some(id.clone());
104 }
105 _ => {}
106 }
107 }
108 _ => {}
109 }
110 }
111
112 Self {
113 inner,
114 imports,
115 globals,
116 exports,
117 func_locals,
118 func_starts,
119 func_code,
120 custom_sections,
121 build_id,
122 imported_func_count,
123 func_names: Mutex::new(func_names),
124 global_names: Mutex::new(global_names),
125 types: Mutex::new(types),
126 func_to_typeidx: Mutex::new(func_to_typeidx),
127 }
128 }
129
130 pub fn into_inner(self) -> ast::Module {
131 Arc::into_inner(self.inner).unwrap()
132 }
133
134 pub fn add_func_name(&self, funcidx: u32, name: &str) {
135 let mut func_names = self.func_names.lock().unwrap();
136 func_names.insert(funcidx, name.to_owned());
137
138 for section in self.inner.sections.lock().unwrap().iter() {
139 match §ion.value {
140 ast::Section::Custom((_size, section)) => match &*section.lock().unwrap() {
141 ast::CustomSection::Name(names) => {
142 if let Some(names) = &names.func_names {
143 let mut names = names.lock().unwrap();
144 names.insert(funcidx, name.to_owned());
145 }
146 }
147 _ => {}
148 },
149 _ => {}
150 }
151 }
152 }
153
154 pub fn add_global_name(&self, globalidx: u32, name: &str) {
155 let mut global_names = self.global_names.lock().unwrap();
156 global_names.insert(globalidx, name.to_owned());
157
158 for section in self.inner.sections.lock().unwrap().iter() {
159 match §ion.value {
160 ast::Section::Custom((_size, section)) => match &*section.lock().unwrap() {
161 ast::CustomSection::Name(section) => {
162 let mut names = section.global_names.lock().unwrap();
163 names.insert(globalidx, name.to_owned());
164 }
165 _ => {}
166 },
167 _ => {}
168 }
169 }
170 }
171
172 pub fn get_coredump(&self) -> Result<wasm_coredump_types::Coredump, BoxError> {
173 let mut data = vec![];
174 let mut stacks = vec![];
175 let mut process_info = None;
176 let mut memory = vec![];
177
178 for section in self.inner.sections.lock().unwrap().iter() {
179 match §ion.value {
180 ast::Section::Data((_section_size, content)) => {
181 let content = content.lock().unwrap();
182 let segment = content.first().unwrap();
183 let offset = segment.compute_offset();
184 debug!("data offset: {}", offset);
185 let padding = vec![0u8; offset as usize];
186 data = [padding, segment.bytes.clone()].concat();
187 }
188
189 ast::Section::Memory((_section_size, content)) => {
190 for m in content {
191 memory.push((m.min.value, m.max))
192 }
193 }
194
195 ast::Section::Custom((_size, section)) => match &*section.lock().unwrap() {
196 ast::CustomSection::CoredumpCore(info) => process_info = Some(info.clone()),
197 ast::CustomSection::CoredumpCoreStack(stack) => stacks.push(stack.clone()),
198
199 _ => {}
200 },
201
202 _ => {}
203 }
204
205 debug!("data size: {:?}", data.len());
206 }
207
208 let process_info = process_info.ok_or("Wasm module is not a coredump")?;
209
210 Ok(wasm_coredump_types::Coredump {
211 data,
212 stacks,
213 process_info,
214 memory,
215 })
216 }
217
218 pub fn add_data(&self, offset: u32, bytes: &[u8]) -> (u32, u32) {
219 for section in self.inner.sections.lock().unwrap().iter() {
220 match §ion.value {
221 ast::Section::Data((_section_size, content)) => {
222 let segment = ast::DataSegment {
223 offset: Some(ast::Value::new(vec![
224 ast::Value::new(ast::Instr::i32_const(offset as i64)),
225 ast::Value::new(ast::Instr::end),
226 ])),
227 bytes: bytes.to_vec(),
228 mode: ast::DataSegmentMode::Active,
229 };
230 content.lock().unwrap().push(segment);
231 }
232 _ => {}
233 }
234 }
235
236 (offset, offset + bytes.len() as u32)
237 }
238
239 pub fn is_func_imported(&self, funcidx: u32) -> bool {
240 funcidx <= self.imported_func_count
241 }
242
243 pub fn imports(&self) -> &Vec<ast::Import> {
244 &self.imports
245 }
246
247 pub fn globals(&self) -> &Vec<ast::Global> {
248 &self.globals
249 }
250
251 pub fn func_locals_count(&self, funcidx: u32) -> u32 {
252 let locals = self.func_locals(funcidx);
253 let mut count = 0;
254 for local in locals {
255 count += local.count;
256 }
257
258 count
259 }
260
261 pub fn func_locals(&self, funcidx: u32) -> Vec<ast::CodeLocal> {
262 let locals = self
263 .func_locals
264 .get(&funcidx)
265 .expect(&format!("locals for funcidx {}", funcidx));
266 locals.to_owned()
267 }
268
269 pub fn is_func_exported(&self, funcidx: u32) -> bool {
270 for export in &self.exports {
271 match &export.descr {
272 ast::ExportDescr::Func(f) => {
273 if *f.lock().unwrap() == funcidx {
274 return true;
275 }
276 }
277 _ => {}
278 }
279 }
280
281 false
282 }
283
284 pub fn get_export_func(&self, name: &str) -> Result<(&ast::Code, ast::Type), BoxError> {
285 for export in &self.exports {
286 if export.name == name {
287 match &export.descr {
288 ast::ExportDescr::Func(f) => {
289 let funcidx = &*f.lock().unwrap();
290 let code = self
291 .func_code
292 .get(funcidx)
293 .ok_or("exported function not found")?;
294 let t = self.get_func_type(*funcidx);
295 return Ok((code, t.clone()));
296 }
297 _ => return Err("export is not a function".into()),
298 }
299 }
300 }
301
302 Err("export not found".into())
303 }
304
305 pub fn get_func_type(&self, funcidx: u32) -> ast::Type {
309 let typeidx = self.get_func_typeidx(funcidx);
310 let types = self.types.lock().unwrap();
311 types.get(&typeidx).expect("type not found").clone()
312 }
313
314 pub fn add_func_local(&self, target_funcidx: u32, local: ast::CodeLocal) -> bool {
315 let mut funcidx = self.imported_func_count;
316
317 for section in self.inner.sections.lock().unwrap().iter() {
318 match §ion.value {
319 ast::Section::Code((_section_size, content)) => {
320 for c in &mut content.lock().unwrap().value {
321 if funcidx == target_funcidx {
322 c.locals.push(local);
323 return true;
324 }
325
326 funcidx += 1;
327 }
328 }
329 _ => {}
330 }
331 }
332
333 false
334 }
335
336 pub fn get_type(&self, typeidx: u32) -> Option<ast::Type> {
337 let types = self.types.lock().unwrap();
338 types.get(&typeidx).cloned()
339 }
340
341 pub fn get_func_typeidx(&self, funcidx: u32) -> u32 {
342 let func_to_typeidx = self.func_to_typeidx.lock().unwrap();
343
344 if funcidx < self.imported_func_count {
345 todo!()
346 } else {
347 let funcidx = funcidx - self.imported_func_count;
349
350 *func_to_typeidx
351 .get(funcidx as usize)
352 .expect(&format!("type not found for funcidx: {}", funcidx))
353 }
354 }
355
356 pub fn get_start_of_func(&self, funcidx: u32) -> Option<usize> {
358 self.func_starts.get(&funcidx).cloned()
359 }
360
361 pub fn get_custom_section(&self, name: &str) -> Option<Vec<u8>> {
362 for section in self.inner.sections.lock().unwrap().iter() {
363 match §ion.value {
364 ast::Section::Custom((_size, section)) => match &*section.lock().unwrap() {
365 ast::CustomSection::Unknown(section_name, bytes) => {
366 if section_name == name {
367 return Some(bytes.to_owned());
368 }
369 }
370 _ => {}
371 },
372 _ => {}
373 }
374 }
375
376 None
377 }
378
379 pub fn get_custom_sections(&self) -> &Vec<ast::CustomSection> {
380 &self.custom_sections
381 }
382
383 pub fn remove_custom_section(&self, name: &str) -> Option<()> {
384 let mut idx = None;
385 let mut i = 0;
386
387 for section in self.inner.sections.lock().unwrap().iter() {
388 match §ion.value {
389 ast::Section::Custom((_size, section)) => match &*section.lock().unwrap() {
390 ast::CustomSection::Unknown(section_name, _) => {
391 if section_name == name {
392 idx = Some(i)
393 }
394 }
395
396 ast::CustomSection::Name(_) if name == "name" => idx = Some(i),
397 _ => {}
398 },
399 _ => {}
400 }
401
402 i += 1;
403 }
404
405 if let Some(idx) = idx {
406 let mut sections = self.inner.sections.lock().unwrap();
407 sections.remove(idx);
408
409 Some(())
410 } else {
411 None
412 }
413 }
414
415 pub fn get_func_name(&self, funcidx: u32) -> Option<String> {
416 for section in self.inner.sections.lock().unwrap().iter() {
417 match §ion.value {
418 ast::Section::Custom((_size, section)) => match &*section.lock().unwrap() {
419 ast::CustomSection::Name(names) => {
420 if let Some(v) = &names.func_names {
421 if let Some(name) = v.lock().unwrap().get(&funcidx) {
422 return Some(name.clone());
423 }
424 }
425 }
426 _ => {}
427 },
428 _ => {}
429 }
430 }
431
432 None
433 }
434
435 pub fn find_import(&self, name: &str) -> u32 {
436 let mut funcidx = 0;
437 for section in self.inner.sections.lock().unwrap().iter() {
438 match §ion.value {
439 ast::Section::Import((_section_size, content)) => {
440 for import in &*content.lock().unwrap() {
441 if import.name == name {
442 return funcidx;
443 }
444 funcidx += 1;
445 }
446 }
447 _ => {}
448 }
449 }
450
451 0
452 }
453
454 pub fn add_global_import(&self, module: &str, name: &str, ty: &ast::GlobalType) -> u32 {
455 let import = ast::Import {
456 module: module.to_owned(),
457 name: name.to_owned(),
458 import_type: ast::ImportType::Global(ty.to_owned()),
459 };
460
461 todo!()
462 }
463
464 pub fn add_import(&self, _import: &ast::Import) -> u32 {
465 unimplemented!("Adding an import requires to shifts all references to functions by one, which is unsafe (func tables) or inconvenient (name section).");
466 }
467
468 pub fn add_global(&self, global: &ast::Global) -> Option<u32> {
469 let mut globalidx = 0;
470
471 for section in self.inner.sections.lock().unwrap().iter() {
473 match §ion.value {
474 ast::Section::Import((_section_size, content)) => {
475 let imports = content.lock().unwrap();
476 for import in imports.iter() {
477 match import.import_type {
478 ast::ImportType::Global(_) => globalidx += 1,
479 _ => {}
480 }
481 }
482 }
483
484 ast::Section::Global((_section_size, content)) => {
485 globalidx += content.lock().unwrap().len() as u32;
486 content.lock().unwrap().push(global.to_owned());
487 return Some(globalidx);
488 }
489 _ => {}
490 }
491 }
492
493 let globals = vec![global.to_owned()];
494 let global_section = ast::Section::Global((
495 ast::Value::new(0), Arc::new(Mutex::new(globals)),
497 ));
498
499 self.add_section(global_section);
500 return Some(globalidx);
501 }
502
503 pub fn add_export_func(&self, name: &str, funcidx: u32) {
504 for section in self.inner.sections.lock().unwrap().iter() {
505 match §ion.value {
506 ast::Section::Export((_section_size, content)) => {
507 let export = ast::Export {
508 name: name.to_owned(),
509 descr: ast::ExportDescr::Func(Arc::new(Mutex::new(funcidx))),
510 };
511 content.lock().unwrap().push(export.to_owned());
512 return;
513 }
514 _ => {}
515 }
516 }
517
518 unimplemented!("no export section")
519 }
520
521 pub fn add_function(&self, func: &ast::Code, typeidx: u32) -> u32 {
522 let mut funcidx = self.imported_func_count;
523
524 for section in self.inner.sections.lock().unwrap().iter() {
525 match §ion.value {
526 ast::Section::Code((_section_size, content)) => {
527 funcidx += content.lock().unwrap().value.len() as u32;
528 content.lock().unwrap().value.push(func.to_owned());
529 }
530 ast::Section::Func((_section_size, content)) => {
531 content.lock().unwrap().push(typeidx);
532 }
533 _ => {}
534 }
535 }
536
537 self.func_to_typeidx.lock().unwrap().push(typeidx);
538 funcidx
539 }
540
541 pub fn add_type(&self, t: &ast::Type) -> u32 {
542 let mut typeidx = 0;
543
544 for section in self.inner.sections.lock().unwrap().iter() {
545 match §ion.value {
546 ast::Section::Type((_section_size, content)) => {
547 typeidx = content.lock().unwrap().len() as u32;
548 content.lock().unwrap().push(t.clone());
549
550 self.types.lock().unwrap().insert(typeidx, t.to_owned());
551 }
552 _ => {}
553 }
554 }
555
556 typeidx
557 }
558
559 pub fn add_section(&self, s: ast::Section) {
560 let mut sections = self.inner.sections.lock().unwrap();
561 sections.push(ast::Value::new(s));
562 sections.sort_by(|a, b| a.pos().cmp(&b.pos()));
563 }
564
565 pub fn add_custom_section(&self, s: ast::CustomSection) {
566 let section = ast::Section::Custom((ast::Value::new(0), Arc::new(Mutex::new(s))));
567 self.add_section(section);
568 }
569
570 pub fn get_build_id(&self) -> &Option<Vec<u8>> {
571 &self.build_id
572 }
573
574 pub fn set_build_id(&self, build_id: &[u8]) {
575 let section = ast::CustomSection::BuildId(build_id.to_owned());
576 self.add_custom_section(section);
577 }
578}
579
580pub struct VisitorContext<'a, T> {
581 pub module: Arc<WasmModule>,
582 insert_nodes_after: Vec<T>,
583 insert_nodes_before: Vec<T>,
584 replace_node: Option<T>,
585 pub curr_funcidx: Option<u32>,
586 pub node: &'a T,
587 traverse_stop: bool,
588}
589impl<'a, T> VisitorContext<'a, T> {
590 pub fn new(module: Arc<WasmModule>, node: &'a T) -> Self {
591 Self {
592 node,
593 module,
594 insert_nodes_after: vec![],
595 insert_nodes_before: vec![],
596 replace_node: None,
597 curr_funcidx: None,
598 traverse_stop: false,
599 }
600 }
601}
602
603impl<'a, T> VisitorContext<'a, Vec<T>> {
604 pub fn insert_node_after(&mut self, new_node: T) {
605 self.insert_nodes_after.push(vec![new_node]);
606 }
607
608 pub fn insert_node_before(&mut self, new_node: T) {
609 self.insert_nodes_before.push(vec![new_node]);
610 }
611}
612
613impl<'a> VisitorContext<'a, ast::Value<ast::Instr>> {
614 pub fn stop_traversal(&mut self) {
615 self.traverse_stop = true;
616 }
617
618 pub fn insert_node_after(&mut self, new_node: ast::Instr) {
619 self.insert_nodes_after.push(ast::Value::new(new_node));
620 }
621
622 pub fn insert_node_before(&mut self, new_node: ast::Instr) {
623 self.insert_nodes_before.push(ast::Value::new(new_node));
624 }
625
626 pub fn replace_node(&mut self, new_node: ast::Instr) {
627 self.replace_node = Some(ast::Value::new(new_node));
628 }
629}
630
631pub trait Visitor {
632 fn visit_instr<'a>(&self, _ctx: &'_ mut VisitorContext<'a, ast::Value<ast::Instr>>) {}
633 fn visit_type<'a>(&self, _ctx: &'_ mut VisitorContext<'a, ast::Type>, _typeidx: u32) {}
634 fn visit_code_section<'a>(&self, _ctx: &'_ mut VisitorContext<'a, Vec<ast::Code>>) {}
635 fn visit_import_section<'a>(&self, _ctx: &'_ mut VisitorContext<'a, Vec<ast::Import>>) {}
636 fn visit_func_section<'a>(&self, _ctx: &'_ mut VisitorContext<'a, Vec<u32>>) {}
637 fn visit_data_section<'a>(&self, _ctx: &'_ mut VisitorContext<'a, Vec<ast::DataSegment>>) {}
638 fn visit_table<'a>(&self, _ctx: &'_ mut VisitorContext<'a, ast::Table>) {}
639 fn visit_export<'a>(&self, _ctx: &'_ mut VisitorContext<'a, ast::Export>) {}
640 fn visit_element<'a>(&self, _ctx: &'_ mut VisitorContext<'a, ast::Element>) {}
641 fn visit_code<'a>(&self, _ctx: &'_ mut VisitorContext<'a, ast::Code>, _funcidx: u32) {}
642}
643
644pub fn traverse(module: Arc<ast::Module>, visitor: Arc<dyn Visitor + Send + Sync>) {
645 let pool = ThreadPool::new(num_cpus::get());
646
647 let mut curr_funcidx = 0;
648
649 let module_ast = Arc::new(WasmModule::new(Arc::clone(&module)));
650
651 for section in module.sections.lock().unwrap().iter() {
652 match §ion.value {
653 ast::Section::Func((_section_size, funcs)) => {
654 let nodes = funcs.lock().unwrap().clone();
655 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), &nodes);
656 Arc::clone(&visitor).visit_func_section(&mut ctx);
657 assert!(ctx.insert_nodes_before.is_empty());
658
659 {
660 let mut new_nodes = ctx.insert_nodes_after;
661 new_nodes.reverse();
662
663 for new_node in new_nodes {
664 debug!("inject new func: {:?}", new_node);
665 funcs.lock().unwrap().extend_from_slice(&new_node);
666 }
667 }
668 }
669 ast::Section::Export((_section_size, exports)) => {
670 for export in exports.lock().unwrap().iter() {
671 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), export);
672 visitor.visit_export(&mut ctx);
673 assert!(ctx.insert_nodes_before.is_empty());
674 assert!(ctx.insert_nodes_after.is_empty());
675 }
676 }
677 ast::Section::Element((_section_size, elements)) => {
678 for element in elements.lock().unwrap().iter() {
679 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), element);
680 visitor.visit_element(&mut ctx);
681 assert!(ctx.insert_nodes_before.is_empty());
682 assert!(ctx.insert_nodes_after.is_empty());
683 }
684 }
685 ast::Section::Table((_section_size, tables)) => {
686 let module_ast = Arc::clone(&module_ast);
687 for table in tables.lock().unwrap().iter() {
688 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), table);
689 visitor.visit_table(&mut ctx);
690 assert!(ctx.insert_nodes_before.is_empty());
691 assert!(ctx.insert_nodes_after.is_empty());
692 }
693 }
694 ast::Section::Type((_section_size, types)) => {
695 let mut typeidx = 0;
696 let types_copy = types.lock().unwrap().clone();
697 for t in types_copy {
698 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), &t);
699 visitor.visit_type(&mut ctx, typeidx);
700 typeidx += 1;
701
702 assert!(ctx.insert_nodes_before.is_empty());
703 assert!(ctx.insert_nodes_after.is_empty());
704 }
705 }
706 ast::Section::Import((_section_size, content)) => {
707 let nodes = content.lock().unwrap().clone();
708 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), &nodes);
709 Arc::clone(&visitor).visit_import_section(&mut ctx);
710 assert!(ctx.insert_nodes_before.is_empty());
711
712 {
713 for new_node in ctx.insert_nodes_after {
714 debug!("inject new import: {:?}", new_node);
715 content.lock().unwrap().extend_from_slice(&new_node);
716 }
717 }
718
719 for import in &nodes {
720 match import.import_type {
721 ast::ImportType::Func(_) => {
722 curr_funcidx += 1;
723 }
724 _ => {}
725 }
726 }
727 }
728 ast::Section::Code((_section_size, codes)) => {
729 {
730 let nodes = codes.lock().unwrap().clone().value;
731 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), &nodes);
732 Arc::clone(&visitor).visit_code_section(&mut ctx);
733 assert!(ctx.insert_nodes_before.is_empty());
734
735 let mut new_nodes = ctx.insert_nodes_after;
736 new_nodes.reverse();
737
738 for new_node in new_nodes {
739 debug!("inject new code: {:?}", new_node);
740 codes.lock().unwrap().value.extend_from_slice(&new_node);
741 }
742 }
743
744 let codes = codes.lock().unwrap().clone();
745 for code in codes.value {
746 {
747 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), &code);
748 Arc::clone(&visitor).visit_code(&mut ctx, curr_funcidx);
749 }
750
751 {
752 let visitor = Arc::clone(&visitor);
753 let module_ast = Arc::clone(&module_ast);
754 pool.execute(move || {
755 visit_expr(
756 Arc::clone(&module_ast),
757 Arc::clone(&code.body),
758 Arc::clone(&visitor),
759 curr_funcidx,
760 );
761 });
762 }
763
764 curr_funcidx += 1;
765 }
766 }
767 ast::Section::Data((_section_size, segments)) => {
768 let nodes = segments.lock().unwrap().clone();
769 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), &nodes);
770 Arc::clone(&visitor).visit_data_section(&mut ctx);
771 assert!(ctx.insert_nodes_before.is_empty());
772
773 let mut new_nodes = ctx.insert_nodes_after;
774 new_nodes.reverse();
775
776 for new_node in new_nodes {
777 debug!("inject new data: {:?}", new_node);
778 segments.lock().unwrap().extend_from_slice(&new_node);
779 }
780 }
781 _ => {}
782 }
783 }
784
785 pool.join();
786}
787
788fn visit_expr(
789 module_ast: Arc<WasmModule>,
790 expr: ast::MutableValue<Vec<ast::Value<ast::Instr>>>,
791 visitor: Arc<dyn Visitor + Send + Sync>,
792 curr_funcidx: u32,
793) {
794 let expr_copy = expr.lock().unwrap().clone();
795
796 let mut added = 0;
800
801 for i in 0..expr_copy.value.len() {
802 let instr = expr_copy.value[i].clone();
803 if let ast::Instr::Block(_, body) = instr.value {
804 visit_expr(Arc::clone(&module_ast), body, visitor.clone(), curr_funcidx);
805 } else if let ast::Instr::If(_, body) = instr.value {
806 visit_expr(Arc::clone(&module_ast), body, visitor.clone(), curr_funcidx);
807 } else if let ast::Instr::Loop(_, body) = instr.value {
808 visit_expr(Arc::clone(&module_ast), body, visitor.clone(), curr_funcidx);
809 } else {
810 let mut ctx = VisitorContext::new(Arc::clone(&module_ast), &instr);
811 ctx.curr_funcidx = Some(curr_funcidx);
812 visitor.visit_instr(&mut ctx);
813
814 if let Some(replace_node) = ctx.replace_node {
815 debug!("replace instr: {:?}", replace_node);
816 expr.lock().unwrap().value[i + added] = replace_node;
817 }
818
819 if ctx.insert_nodes_after.len() > 0 {
820 debug!("insert instr(s): {:?}", ctx.insert_nodes_after);
821 expr.lock().unwrap().value.splice(
822 (i + added + 1)..(i + added + 1),
823 ctx.insert_nodes_after.clone(),
824 );
825 added += ctx.insert_nodes_after.len();
826 }
827
828 if ctx.insert_nodes_before.len() > 0 {
829 debug!("insert instr(s): {:?}", ctx.insert_nodes_before);
830
831 expr.lock()
832 .unwrap()
833 .value
834 .splice((i + added)..(i + added), ctx.insert_nodes_before.clone());
835 added += ctx.insert_nodes_before.len();
836 }
837
838 if ctx.traverse_stop {
839 break;
840 }
841 }
842 }
843}