1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! Auxiliary functions for working with WASM modules.

use parity_wasm::elements::{IndexMap, Instruction, Internal, Module, Section};

/// Rewrites module sections after inserting imports.
pub fn rewrite_sections_after_insertion(
	mut module: Module,
	inserted_index: u32,
	inserted_count: u32,
) -> Result<Module, Module> {
	if inserted_count == 0 {
		return Err(module)
	}

	// Updating calling addresses (all calls to function index >= `inserted_index` should be
	// incremented)
	for section in module.sections_mut() {
		match section {
			Section::Code(code_section) =>
				for func_body in code_section.bodies_mut().iter_mut() {
					for instruction in func_body.code_mut().elements_mut().iter_mut() {
						if let Instruction::Call(call_index) = instruction {
							if *call_index >= inserted_index {
								*call_index += inserted_count
							}
						}
					}
				},
			Section::Export(export_section) =>
				for export in export_section.entries_mut() {
					if let Internal::Function(func_index) = export.internal_mut() {
						if *func_index >= inserted_index {
							*func_index += inserted_count
						}
					}
				},
			Section::Element(elements_section) => {
				// Note that we do not need to check the element type referenced because in the
				// WebAssembly 1.0 spec, the only allowed element type is funcref.
				for segment in elements_section.entries_mut() {
					// update all indirect call addresses initial values
					for func_index in segment.members_mut() {
						if *func_index >= inserted_index {
							*func_index += inserted_count
						}
					}
				}
			},
			Section::Start(start_idx) =>
				if *start_idx >= inserted_index {
					*start_idx += inserted_count
				},
			Section::Name(s) =>
				for functions in s.functions_mut() {
					*functions.names_mut() =
						IndexMap::from_iter(functions.names().iter().map(|(mut idx, name)| {
							if idx >= inserted_index {
								idx += inserted_count;
							}

							(idx, name.clone())
						}));
				},
			_ => {},
		}
	}

	Ok(module)
}