wasmtime_obj/
module.rs

1use crate::builder::{ObjectBuilder, ObjectBuilderTarget};
2use crate::context::layout_vmcontext;
3use crate::data_segment::{declare_data_segment, emit_data_segment};
4use crate::table::{declare_table, emit_table};
5use anyhow::Result;
6use object::write::{Object, Relocation, StandardSection, Symbol, SymbolSection};
7use object::{RelocationEncoding, RelocationKind, SymbolFlags, SymbolKind, SymbolScope};
8use wasmtime_debug::DwarfSection;
9use wasmtime_environ::isa::TargetFrontendConfig;
10use wasmtime_environ::{CompiledFunctions, MemoryInitialization, Module};
11
12fn emit_vmcontext_init(
13    obj: &mut Object,
14    module: &Module,
15    target_config: &TargetFrontendConfig,
16) -> Result<()> {
17    let (data, table_relocs) = layout_vmcontext(module, target_config);
18    let symbol_id = obj.add_symbol(Symbol {
19        name: "_vmcontext_init".as_bytes().to_vec(),
20        value: 0,
21        size: 0,
22        kind: SymbolKind::Data,
23        scope: SymbolScope::Linkage,
24        weak: false,
25        section: SymbolSection::Undefined,
26        flags: SymbolFlags::None,
27    });
28    let section_id = obj.section_id(StandardSection::Data);
29    let section_offset = obj.add_symbol_data(symbol_id, section_id, &data, 1);
30
31    for reloc in table_relocs.iter() {
32        let target_name = format!("_table_{}", reloc.index);
33        let target_symbol = obj.symbol_id(target_name.as_bytes()).unwrap();
34        obj.add_relocation(
35            section_id,
36            Relocation {
37                offset: section_offset + reloc.offset as u64,
38                size: 64, // FIXME for all targets
39                kind: RelocationKind::Absolute,
40                encoding: RelocationEncoding::Generic,
41                symbol: target_symbol,
42                addend: 0,
43            },
44        )?;
45    }
46    Ok(())
47}
48
49/// Emits a module that has been emitted with the `wasmtime-environ` environment
50/// implementation to a native object file.
51pub fn emit_module(
52    target: ObjectBuilderTarget,
53    module: &Module,
54    target_config: &TargetFrontendConfig,
55    compilation: CompiledFunctions,
56    dwarf_sections: Vec<DwarfSection>,
57) -> Result<Object> {
58    let mut builder = ObjectBuilder::new(target, module, &compilation);
59    builder.set_dwarf_sections(dwarf_sections);
60    let mut obj = builder.build()?;
61
62    // Append data, table and vmcontext_init code to the object file.
63    match &module.memory_initialization {
64        MemoryInitialization::Segmented(initializers) => {
65            for (i, initializer) in initializers.iter().enumerate() {
66                declare_data_segment(&mut obj, initializer, i)?;
67            }
68        }
69        _ => unimplemented!(),
70    }
71
72    for i in 0..module.table_plans.len() {
73        declare_table(&mut obj, i)?;
74    }
75
76    match &module.memory_initialization {
77        MemoryInitialization::Segmented(initializers) => {
78            for (i, initializer) in initializers.iter().enumerate() {
79                emit_data_segment(&mut obj, initializer, i)?;
80            }
81        }
82        _ => unimplemented!(),
83    }
84
85    for i in 0..module.table_plans.len() {
86        emit_table(&mut obj, i)?;
87    }
88
89    emit_vmcontext_init(&mut obj, module, target_config)?;
90
91    Ok(obj)
92}