Skip to main content

wasmer_compiler_singlepass/
elf.rs

1use crate::unwind::UnwindFrame;
2#[cfg(feature = "unwind")]
3use crate::unwind::create_systemv_cie;
4#[cfg(feature = "unwind")]
5use gimli::{
6    constants,
7    write::{EhFrame, FrameTable},
8};
9use object::{
10    SymbolFlags, SymbolKind, SymbolScope,
11    write::{StandardSection, Symbol, SymbolSection},
12};
13
14#[cfg(feature = "unwind")]
15use wasmer_compiler::dwarf::{DwarfState, WriterRelocate};
16#[cfg(feature = "unwind")]
17use wasmer_compiler::elf::emit_eh_frame_section;
18use wasmer_compiler::{
19    elf::{add_relocations, emit_trap_section},
20    misc::{CompiledFunctionExt, CompiledKind},
21    object::get_object_for_target,
22    types::function::CompiledFunction,
23};
24use wasmer_types::{CompileError, LocalFunctionIndex, target::Target};
25
26pub(crate) use wasmer_compiler::elf::{
27    CompileOutput, compile_output_in_memory, compile_output_objects, emit_function_body,
28    emit_import_trampoline, link_module,
29};
30
31pub(crate) fn emit_local_function(
32    target: &Target,
33    index: LocalFunctionIndex,
34    function: CompiledFunction,
35    fde: Option<UnwindFrame>,
36    #[cfg(feature = "unwind")] mut dwarf_state: Option<DwarfState>,
37) -> Result<Vec<u8>, CompileError> {
38    let kind = CompiledKind::Local(index, String::new());
39    let mut object = get_object_for_target(target.triple())
40        .map_err(|e| CompileError::Codegen(format!("cannot create object: {e}")))?;
41    let symbol = object.add_symbol(Symbol {
42        name: kind.linkage_name().into_bytes(),
43        value: 0,
44        size: function.body.body.len() as u64,
45        kind: SymbolKind::Text,
46        scope: SymbolScope::Linkage,
47        weak: false,
48        section: SymbolSection::Undefined,
49        flags: SymbolFlags::None,
50    });
51    let text = object.section_id(StandardSection::Text);
52    object.add_symbol_data(symbol, text, &function.body.body, 4);
53    add_relocations(
54        &mut object,
55        text,
56        &function.relocations,
57        Some((index, symbol)),
58    )?;
59
60    #[cfg(feature = "unwind")]
61    if let Some(dwarf_state) = dwarf_state.as_mut() {
62        dwarf_state.write_sections(
63            &mut object,
64            symbol,
65            function.body.body.len() as u64,
66            target.triple().endianness().ok(),
67        )?;
68    }
69
70    emit_trap_section(&mut object, &kind, &function.frame_info.traps);
71
72    #[cfg(feature = "unwind")]
73    if let Some(fde) = fde
74        && let Some(mut cie) = create_systemv_cie(target.triple().architecture)
75    {
76        // The ELF image may be mapped at any base address, so make the FDE's
77        // function reference position-independent.
78        cie.fde_address_encoding = constants::DW_EH_PE_pcrel | constants::DW_EH_PE_sdata4;
79        let mut frametable = FrameTable::default();
80        let cie_id = frametable.add_cie(cie);
81        match fde {
82            UnwindFrame::SystemV(fde) => {
83                frametable.add_fde(cie_id, fde);
84            }
85        }
86        let mut eh_frame = EhFrame(WriterRelocate::new());
87        frametable
88            .write_eh_frame(&mut eh_frame)
89            .map_err(|e| CompileError::Codegen(format!("failed to write .eh_frame: {e}")))?;
90
91        let relocations = eh_frame.0.relocs.clone();
92        emit_eh_frame_section(
93            &mut object,
94            &eh_frame.0.into_bytes(),
95            &relocations,
96            symbol,
97            None,
98        )?;
99    }
100    #[cfg(not(feature = "unwind"))]
101    let _ = fde;
102
103    object
104        .write()
105        .map_err(|e| CompileError::Codegen(format!("failed to serialize object: {e}")))
106}