gwasm_instrument/
utils.rs

1//! Auxiliary functions for working with WASM modules.
2
3use parity_wasm::elements::{IndexMap, Instruction, Internal, Module, Section};
4
5/// Rewrites module sections after inserting imports.
6pub fn rewrite_sections_after_insertion(
7	mut module: Module,
8	inserted_index: u32,
9	inserted_count: u32,
10) -> Result<Module, Module> {
11	if inserted_count == 0 {
12		return Err(module)
13	}
14
15	// Updating calling addresses (all calls to function index >= `inserted_index` should be
16	// incremented)
17	for section in module.sections_mut() {
18		match section {
19			Section::Code(code_section) =>
20				for func_body in code_section.bodies_mut().iter_mut() {
21					for instruction in func_body.code_mut().elements_mut().iter_mut() {
22						if let Instruction::Call(call_index) = instruction {
23							if *call_index >= inserted_index {
24								*call_index += inserted_count
25							}
26						}
27					}
28				},
29			Section::Export(export_section) =>
30				for export in export_section.entries_mut() {
31					if let Internal::Function(func_index) = export.internal_mut() {
32						if *func_index >= inserted_index {
33							*func_index += inserted_count
34						}
35					}
36				},
37			Section::Element(elements_section) => {
38				// Note that we do not need to check the element type referenced because in the
39				// WebAssembly 1.0 spec, the only allowed element type is funcref.
40				for segment in elements_section.entries_mut() {
41					// update all indirect call addresses initial values
42					for func_index in segment.members_mut() {
43						if *func_index >= inserted_index {
44							*func_index += inserted_count
45						}
46					}
47				}
48			},
49			Section::Start(start_idx) =>
50				if *start_idx >= inserted_index {
51					*start_idx += inserted_count
52				},
53			Section::Name(s) =>
54				for functions in s.functions_mut() {
55					*functions.names_mut() =
56						IndexMap::from_iter(functions.names().iter().map(|(mut idx, name)| {
57							if idx >= inserted_index {
58								idx += inserted_count;
59							}
60
61							(idx, name.clone())
62						}));
63				},
64			_ => {},
65		}
66	}
67
68	Ok(module)
69}