1 use anyhow::Result;
2 use faerie::{Artifact, Decl, Link};
3 use wasmtime_environ::entity::EntityRef;
4 use wasmtime_environ::settings;
5 use wasmtime_environ::settings::Configurable;
6 use wasmtime_environ::{Compilation, Module, RelocationTarget, Relocations};
7 
8 /// Defines module functions
declare_functions( obj: &mut Artifact, module: &Module, relocations: &Relocations, ) -> Result<()>9 pub fn declare_functions(
10     obj: &mut Artifact,
11     module: &Module,
12     relocations: &Relocations,
13 ) -> Result<()> {
14     for i in 0..module.local.num_imported_funcs {
15         let string_name = format!("_wasm_function_{}", i);
16         obj.declare(string_name, Decl::function_import())?;
17     }
18     for (i, _function_relocs) in relocations.iter().rev() {
19         let func_index = module.local.func_index(i);
20         let string_name = format!("_wasm_function_{}", func_index.index());
21         obj.declare(string_name, Decl::function().global())?;
22     }
23     Ok(())
24 }
25 
26 /// Emits module functions
emit_functions( obj: &mut Artifact, module: &Module, compilation: &Compilation, relocations: &Relocations, ) -> Result<()>27 pub fn emit_functions(
28     obj: &mut Artifact,
29     module: &Module,
30     compilation: &Compilation,
31     relocations: &Relocations,
32 ) -> Result<()> {
33     debug_assert!(
34         module.start_func.is_none()
35             || module.start_func.unwrap().index() >= module.local.num_imported_funcs,
36         "imported start functions not supported yet"
37     );
38 
39     let mut shared_builder = settings::builder();
40     shared_builder
41         .enable("enable_verifier")
42         .expect("Missing enable_verifier setting");
43 
44     for (i, _function_relocs) in relocations.iter() {
45         let body = &compilation.get(i).body;
46         let func_index = module.local.func_index(i);
47         let string_name = format!("_wasm_function_{}", func_index.index());
48 
49         obj.define(string_name, body.clone())?;
50     }
51 
52     for (i, function_relocs) in relocations.iter() {
53         let func_index = module.local.func_index(i);
54         let string_name = format!("_wasm_function_{}", func_index.index());
55         for r in function_relocs {
56             debug_assert_eq!(r.addend, 0);
57             match r.reloc_target {
58                 RelocationTarget::UserFunc(target_index) => {
59                     let target_name = format!("_wasm_function_{}", target_index.index());
60                     obj.link(Link {
61                         from: &string_name,
62                         to: &target_name,
63                         at: r.offset as u64,
64                     })?;
65                 }
66                 RelocationTarget::JumpTable(_, _) => {
67                     // ignore relocations for jump tables
68                 }
69                 _ => panic!("relocations target not supported yet: {:?}", r.reloc_target),
70             };
71         }
72     }
73 
74     Ok(())
75 }
76