wasmer_compiler/object/
module.rs

1use super::error::ObjectError;
2use crate::{
3    serialize::MetadataHeader,
4    types::{
5        function::Compilation,
6        relocation::{RelocationKind as Reloc, RelocationTarget},
7        section::{CustomSectionProtection, SectionIndex},
8        symbols::{ModuleMetadata, Symbol, SymbolRegistry},
9    },
10};
11use object::{
12    elf, macho,
13    write::{
14        Object, Relocation, StandardSection, StandardSegment, Symbol as ObjSymbol, SymbolId,
15        SymbolSection,
16    },
17    FileFlags, RelocationEncoding, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
18    SymbolScope,
19};
20use wasmer_types::entity::{EntityRef, PrimaryMap};
21use wasmer_types::target::{Architecture, BinaryFormat, Endianness, PointerWidth, Triple};
22use wasmer_types::LocalFunctionIndex;
23
24const DWARF_SECTION_NAME: &[u8] = b".eh_frame";
25
26/// Create an object for a given target `Triple`.
27///
28/// # Usage
29///
30/// ```rust
31/// # use wasmer_types::target::Triple;
32/// # use wasmer_compiler::object::{ObjectError, get_object_for_target};
33///
34/// # fn generate_object_for_target(triple: &Triple) -> Result<(), ObjectError> {
35/// let mut object = get_object_for_target(&triple)?;
36///
37/// # Ok(())
38/// # }
39/// ```
40pub fn get_object_for_target(triple: &Triple) -> Result<Object, ObjectError> {
41    let obj_binary_format = match triple.binary_format {
42        BinaryFormat::Elf => object::BinaryFormat::Elf,
43        BinaryFormat::Macho => object::BinaryFormat::MachO,
44        BinaryFormat::Coff => object::BinaryFormat::Coff,
45        binary_format => {
46            return Err(ObjectError::UnsupportedBinaryFormat(format!(
47                "{binary_format}"
48            )));
49        }
50    };
51    let obj_architecture = match triple.architecture {
52        Architecture::X86_64 => object::Architecture::X86_64,
53        Architecture::Aarch64(_) => object::Architecture::Aarch64,
54        Architecture::Riscv64(_) => object::Architecture::Riscv64,
55        Architecture::LoongArch64 => object::Architecture::LoongArch64,
56        architecture => {
57            return Err(ObjectError::UnsupportedArchitecture(format!(
58                "{architecture}"
59            )));
60        }
61    };
62    let obj_endianness = match triple
63        .endianness()
64        .map_err(|_| ObjectError::UnknownEndianness)?
65    {
66        Endianness::Little => object::Endianness::Little,
67        Endianness::Big => object::Endianness::Big,
68    };
69
70    let mut object = Object::new(obj_binary_format, obj_architecture, obj_endianness);
71
72    if let Architecture::Riscv64(_) = triple.architecture {
73        object.flags = FileFlags::Elf {
74            e_flags: elf::EF_RISCV_FLOAT_ABI_DOUBLE,
75            os_abi: 2,
76            abi_version: 0,
77        };
78    }
79
80    Ok(object)
81}
82
83/// Write data into an existing object.
84///
85/// # Usage
86///
87/// ```rust
88/// # use wasmer_types::target::Triple;
89/// # use wasmer_compiler::object::{ObjectError, get_object_for_target, emit_data};
90///
91/// # fn emit_data_into_object(triple: &Triple) -> Result<(), ObjectError> {
92/// let mut object = get_object_for_target(&triple)?;
93/// emit_data(&mut object, b"WASMER_METADATA", &b"Hello, World!"[..], 1)?;
94///
95/// # Ok(())
96/// # }
97/// ```
98pub fn emit_data(
99    obj: &mut Object,
100    name: &[u8],
101    data: &[u8],
102    align: u64,
103) -> Result<u64, ObjectError> {
104    let symbol_id = obj.add_symbol(ObjSymbol {
105        name: name.to_vec(),
106        value: 0,
107        size: 0,
108        kind: SymbolKind::Data,
109        scope: SymbolScope::Dynamic,
110        weak: false,
111        section: SymbolSection::Undefined,
112        flags: SymbolFlags::None,
113    });
114    let section_id = obj.section_id(StandardSection::Data);
115    let offset = obj.add_symbol_data(symbol_id, section_id, data, align);
116
117    Ok(offset)
118}
119
120/// Emit the compilation result into an existing object.
121///
122/// # Usage
123///
124/// ```rust
125/// # use wasmer_compiler::types::{ symbols::SymbolRegistry, function::{Compilation} };
126/// # use wasmer_types::target::Triple;
127/// # use wasmer_compiler::object::{ObjectError, ObjectMetadataBuilder, get_object_for_target, emit_compilation};
128///
129/// # fn emit_compilation_into_object(
130/// #     triple: &Triple,
131/// #     compilation: Compilation,
132/// #     builder: ObjectMetadataBuilder,
133/// #     symbol_registry: impl SymbolRegistry,
134/// # ) -> Result<(), ObjectError> {
135/// let mut object = get_object_for_target(&triple)?;
136/// emit_compilation(&mut object, compilation, &symbol_registry, &triple, &builder)?;
137/// # Ok(())
138/// # }
139/// ```
140pub fn emit_compilation(
141    obj: &mut Object,
142    compilation: Compilation,
143    symbol_registry: &impl SymbolRegistry,
144    triple: &Triple,
145    relocs_builder: &ObjectMetadataBuilder,
146) -> Result<(), ObjectError> {
147    let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
148    let mut function_relocations = PrimaryMap::with_capacity(compilation.functions.len());
149    for (_, func) in compilation.functions.into_iter() {
150        function_bodies.push(func.body);
151        function_relocations.push(func.relocations);
152    }
153    let custom_section_relocations = compilation
154        .custom_sections
155        .iter()
156        .map(|(_, section)| section.relocations.clone())
157        .collect::<PrimaryMap<SectionIndex, _>>();
158
159    let debug_index = compilation.unwind_info.eh_frame;
160
161    let default_align = match triple.architecture {
162        target_lexicon::Architecture::Aarch64(_) => {
163            if matches!(
164                triple.operating_system,
165                target_lexicon::OperatingSystem::Darwin
166            ) {
167                8
168            } else {
169                4
170            }
171        }
172        _ => 1,
173    };
174
175    // Add sections
176    let custom_section_ids = compilation
177        .custom_sections
178        .into_iter()
179        .map(|(section_index, custom_section)| {
180            if debug_index.map_or(false, |d| d == section_index) {
181                // If this is the debug section
182                let segment = obj.segment_name(StandardSegment::Debug).to_vec();
183                let section_id =
184                    obj.add_section(segment, DWARF_SECTION_NAME.to_vec(), SectionKind::Debug);
185                obj.append_section_data(section_id, custom_section.bytes.as_slice(), default_align);
186                let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
187                let symbol_id = obj.add_symbol(ObjSymbol {
188                    name: section_name.into_bytes(),
189                    value: 0,
190                    size: custom_section.bytes.len() as _,
191                    kind: SymbolKind::Data,
192                    scope: SymbolScope::Compilation,
193                    weak: false,
194                    section: SymbolSection::Section(section_id),
195                    flags: SymbolFlags::None,
196                });
197                (section_id, symbol_id)
198            } else {
199                let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
200                let (section_kind, standard_section) = match custom_section.protection {
201                    CustomSectionProtection::ReadExecute => {
202                        (SymbolKind::Text, StandardSection::Text)
203                    }
204                    CustomSectionProtection::Read => (SymbolKind::Data, StandardSection::Data),
205                };
206                let section_id = obj.section_id(standard_section);
207                let symbol_id = obj.add_symbol(ObjSymbol {
208                    name: section_name.into_bytes(),
209                    value: 0,
210                    size: custom_section.bytes.len() as _,
211                    kind: section_kind,
212                    scope: SymbolScope::Dynamic,
213                    weak: false,
214                    section: SymbolSection::Section(section_id),
215                    flags: SymbolFlags::None,
216                });
217                obj.add_symbol_data(
218                    symbol_id,
219                    section_id,
220                    custom_section.bytes.as_slice(),
221                    custom_section.alignment.unwrap_or(default_align),
222                );
223                (section_id, symbol_id)
224            }
225        })
226        .collect::<PrimaryMap<SectionIndex, _>>();
227
228    // Add functions
229    let function_symbol_ids = function_bodies
230        .into_iter()
231        .map(|(function_local_index, function)| {
232            let function_name =
233                symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index));
234            let section_id = obj.section_id(StandardSection::Text);
235            let symbol_id = obj.add_symbol(ObjSymbol {
236                name: function_name.into_bytes(),
237                value: 0,
238                size: function.body.len() as _,
239                kind: SymbolKind::Text,
240                scope: SymbolScope::Dynamic,
241                weak: false,
242                section: SymbolSection::Section(section_id),
243                flags: SymbolFlags::None,
244            });
245            obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
246            (section_id, symbol_id)
247        })
248        .collect::<PrimaryMap<LocalFunctionIndex, _>>();
249    for (i, (_, symbol_id)) in function_symbol_ids.iter() {
250        relocs_builder.setup_function_pointer(obj, i.index(), *symbol_id)?;
251    }
252
253    // Add function call trampolines
254    for (signature_index, function) in compilation.function_call_trampolines.into_iter() {
255        let function_name =
256            symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(signature_index));
257        let section_id = obj.section_id(StandardSection::Text);
258        let symbol_id = obj.add_symbol(ObjSymbol {
259            name: function_name.into_bytes(),
260            value: 0,
261            size: function.body.len() as _,
262            kind: SymbolKind::Text,
263            scope: SymbolScope::Dynamic,
264            weak: false,
265            section: SymbolSection::Section(section_id),
266            flags: SymbolFlags::None,
267        });
268        obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
269
270        relocs_builder.setup_trampoline(obj, signature_index.index(), symbol_id)?;
271    }
272
273    // Add dynamic function trampolines
274    for (func_index, function) in compilation.dynamic_function_trampolines.into_iter() {
275        let function_name =
276            symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
277        let section_id = obj.section_id(StandardSection::Text);
278        let symbol_id = obj.add_symbol(ObjSymbol {
279            name: function_name.into_bytes(),
280            value: 0,
281            size: function.body.len() as _,
282            kind: SymbolKind::Text,
283            scope: SymbolScope::Dynamic,
284            weak: false,
285            section: SymbolSection::Section(section_id),
286            flags: SymbolFlags::None,
287        });
288        obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
289
290        relocs_builder.setup_dynamic_function_trampoline_pointer(
291            obj,
292            func_index.index(),
293            symbol_id,
294        )?;
295    }
296
297    let mut all_relocations = Vec::new();
298
299    for (function_local_index, relocations) in function_relocations.into_iter() {
300        let (section_id, symbol_id) = function_symbol_ids.get(function_local_index).unwrap();
301        all_relocations.push((*section_id, *symbol_id, relocations))
302    }
303
304    for (section_index, relocations) in custom_section_relocations.into_iter() {
305        if !debug_index.map_or(false, |d| d == section_index) {
306            // Skip DWARF relocations just yet
307            let (section_id, symbol_id) = custom_section_ids.get(section_index).unwrap();
308            all_relocations.push((*section_id, *symbol_id, relocations));
309        }
310    }
311
312    for (section_id, symbol_id, relocations) in all_relocations.into_iter() {
313        let (_symbol_id, section_offset) = obj.symbol_section_and_offset(symbol_id).unwrap();
314
315        for r in relocations {
316            let relocation_address = section_offset + r.offset as u64;
317
318            let (relocation_kind, relocation_encoding, relocation_size) = match r.kind {
319                Reloc::Abs4 => (RelocationKind::Absolute, RelocationEncoding::Generic, 32),
320                Reloc::Abs8 => (RelocationKind::Absolute, RelocationEncoding::Generic, 64),
321                Reloc::X86PCRel4 => (RelocationKind::Relative, RelocationEncoding::Generic, 32),
322                Reloc::X86CallPCRel4 => {
323                    (RelocationKind::Relative, RelocationEncoding::X86Branch, 32)
324                }
325                Reloc::X86CallPLTRel4 => (
326                    RelocationKind::PltRelative,
327                    RelocationEncoding::X86Branch,
328                    32,
329                ),
330                Reloc::X86GOTPCRel4 => {
331                    (RelocationKind::GotRelative, RelocationEncoding::Generic, 32)
332                }
333                Reloc::Arm64Call => (
334                    match obj.format() {
335                        object::BinaryFormat::Elf => RelocationKind::Elf(elf::R_AARCH64_CALL26),
336                        object::BinaryFormat::MachO => RelocationKind::MachO {
337                            value: macho::ARM64_RELOC_BRANCH26,
338                            relative: true,
339                        },
340                        fmt => panic!("unsupported binary format {fmt:?}"),
341                    },
342                    RelocationEncoding::Generic,
343                    32,
344                ),
345                Reloc::ElfX86_64TlsGd => (
346                    RelocationKind::Elf(elf::R_X86_64_TLSGD),
347                    RelocationEncoding::Generic,
348                    32,
349                ),
350                Reloc::MachoArm64RelocBranch26 => (
351                    RelocationKind::MachO {
352                        value: macho::ARM64_RELOC_BRANCH26,
353                        relative: true,
354                    },
355                    RelocationEncoding::Generic,
356                    32,
357                ),
358                Reloc::MachoArm64RelocUnsigned => (
359                    RelocationKind::MachO {
360                        value: object::macho::ARM64_RELOC_UNSIGNED,
361                        relative: true,
362                    },
363                    RelocationEncoding::Generic,
364                    32,
365                ),
366                Reloc::MachoArm64RelocSubtractor => (
367                    RelocationKind::MachO {
368                        value: object::macho::ARM64_RELOC_SUBTRACTOR,
369                        relative: false,
370                    },
371                    RelocationEncoding::Generic,
372                    64,
373                ),
374                Reloc::MachoArm64RelocPage21 => (
375                    RelocationKind::MachO {
376                        value: object::macho::ARM64_RELOC_PAGE21,
377                        relative: true,
378                    },
379                    RelocationEncoding::Generic,
380                    32,
381                ),
382
383                Reloc::MachoArm64RelocPageoff12 => (
384                    RelocationKind::MachO {
385                        value: object::macho::ARM64_RELOC_PAGEOFF12,
386                        relative: false,
387                    },
388                    RelocationEncoding::Generic,
389                    32,
390                ),
391                Reloc::MachoArm64RelocGotLoadPage21 => (
392                    RelocationKind::MachO {
393                        value: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
394                        relative: true,
395                    },
396                    RelocationEncoding::Generic,
397                    32,
398                ),
399                Reloc::MachoArm64RelocGotLoadPageoff12 => (
400                    RelocationKind::MachO {
401                        value: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
402                        relative: true,
403                    },
404                    RelocationEncoding::Generic,
405                    32,
406                ),
407                Reloc::MachoArm64RelocPointerToGot => (
408                    RelocationKind::MachO {
409                        value: object::macho::ARM64_RELOC_POINTER_TO_GOT,
410                        relative: true,
411                    },
412                    RelocationEncoding::Generic,
413                    32,
414                ),
415                Reloc::MachoArm64RelocTlvpLoadPage21 => (
416                    RelocationKind::MachO {
417                        value: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
418                        relative: true,
419                    },
420                    RelocationEncoding::Generic,
421                    32,
422                ),
423                Reloc::MachoArm64RelocTlvpLoadPageoff12 => (
424                    RelocationKind::MachO {
425                        value: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
426                        relative: true,
427                    },
428                    RelocationEncoding::Generic,
429                    32,
430                ),
431                Reloc::MachoArm64RelocAddend => (
432                    RelocationKind::MachO {
433                        value: object::macho::ARM64_RELOC_ADDEND,
434                        relative: false,
435                    },
436                    RelocationEncoding::Generic,
437                    32,
438                ),
439
440                other => {
441                    return Err(ObjectError::UnsupportedArchitecture(format!(
442                        "{} (relocation: {})",
443                        triple.architecture, other
444                    )))
445                }
446            };
447
448            match r.reloc_target {
449                RelocationTarget::LocalFunc(index) => {
450                    let (_, target_symbol) = function_symbol_ids.get(index).unwrap();
451                    obj.add_relocation(
452                        section_id,
453                        Relocation {
454                            offset: relocation_address,
455                            size: relocation_size,
456                            kind: relocation_kind,
457                            encoding: relocation_encoding,
458                            symbol: *target_symbol,
459                            addend: r.addend,
460                        },
461                    )
462                    .map_err(ObjectError::Write)?;
463                }
464                RelocationTarget::LibCall(libcall) => {
465                    let mut libcall_fn_name = libcall.to_function_name().to_string();
466                    if matches!(triple.binary_format, BinaryFormat::Macho) {
467                        libcall_fn_name = format!("_{libcall_fn_name}");
468                    }
469
470                    let libcall_fn_name = libcall_fn_name.as_bytes();
471
472                    // We add the symols lazily as we see them
473                    let target_symbol = obj.symbol_id(libcall_fn_name).unwrap_or_else(|| {
474                        obj.add_symbol(ObjSymbol {
475                            name: libcall_fn_name.to_vec(),
476                            value: 0,
477                            size: 0,
478                            kind: SymbolKind::Unknown,
479                            scope: SymbolScope::Unknown,
480                            weak: false,
481                            section: SymbolSection::Undefined,
482                            flags: SymbolFlags::None,
483                        })
484                    });
485                    obj.add_relocation(
486                        section_id,
487                        Relocation {
488                            offset: relocation_address,
489                            size: relocation_size,
490                            kind: relocation_kind,
491                            encoding: relocation_encoding,
492                            symbol: target_symbol,
493                            addend: r.addend,
494                        },
495                    )
496                    .map_err(ObjectError::Write)?;
497                }
498                RelocationTarget::CustomSection(section_index) => {
499                    let (_, target_symbol) = custom_section_ids.get(section_index).unwrap();
500                    obj.add_relocation(
501                        section_id,
502                        Relocation {
503                            offset: relocation_address,
504                            size: relocation_size,
505                            kind: relocation_kind,
506                            encoding: relocation_encoding,
507                            symbol: *target_symbol,
508                            addend: r.addend,
509                        },
510                    )
511                    .map_err(ObjectError::Write)?;
512                }
513            };
514        }
515    }
516
517    Ok(())
518}
519
520/// Emit the compilation result into an existing object.
521///
522/// # Usage
523///
524/// ```rust
525/// # use wasmer_compiler::types::{ symbols::SymbolRegistry, function::{Compilation} };
526/// # use wasmer_types::target::Triple;
527/// # use wasmer_compiler::object::{ObjectError, get_object_for_target, emit_serialized};
528///
529/// # fn emit_compilation_into_object(
530/// #     triple: &Triple,
531/// #     compilation: Compilation,
532/// #     symbol_registry: impl SymbolRegistry,
533/// # ) -> Result<(), ObjectError> {
534/// let bytes = &[ /* compilation bytes */];
535/// let mut object = get_object_for_target(&triple)?;
536/// emit_serialized(&mut object, bytes, &triple, "WASMER_MODULE")?;
537/// # Ok(())
538/// # }
539/// ```
540pub fn emit_serialized(
541    obj: &mut Object,
542    sercomp: &[u8],
543    triple: &Triple,
544    object_name: &str,
545) -> Result<(), ObjectError> {
546    obj.set_mangling(object::write::Mangling::None);
547    //let module_name = module.compile_info.module.name.clone();
548    let len_name = format!("{object_name}_LENGTH");
549    let data_name = format!("{object_name}_DATA");
550    //let metadata_name = "WASMER_MODULE_METADATA";
551
552    let align = match triple.architecture {
553        Architecture::X86_64 => 1,
554        // In Arm64 is recommended a 4-byte alignment
555        Architecture::Aarch64(_) => 4,
556        _ => 1,
557    };
558
559    let len = sercomp.len();
560    let section_id = obj.section_id(StandardSection::Data);
561    let symbol_id = obj.add_symbol(ObjSymbol {
562        name: len_name.as_bytes().to_vec(),
563        value: 0,
564        size: len.to_le_bytes().len() as _,
565        kind: SymbolKind::Data,
566        scope: SymbolScope::Dynamic,
567        weak: false,
568        section: SymbolSection::Section(section_id),
569        flags: SymbolFlags::None,
570    });
571    obj.add_symbol_data(symbol_id, section_id, &len.to_le_bytes(), align);
572
573    let section_id = obj.section_id(StandardSection::Data);
574    let symbol_id = obj.add_symbol(ObjSymbol {
575        name: data_name.as_bytes().to_vec(),
576        value: 0,
577        size: sercomp.len() as _,
578        kind: SymbolKind::Data,
579        scope: SymbolScope::Dynamic,
580        weak: false,
581        section: SymbolSection::Section(section_id),
582        flags: SymbolFlags::None,
583    });
584    obj.add_symbol_data(symbol_id, section_id, sercomp, align);
585
586    Ok(())
587}
588
589/// ObjectMetadataBuilder builds serialized module metadata include in
590/// an object. In addition, it also relies on information from ModuleInfo
591/// to build a table of function pointers, trmampolines and dynamic function
592/// trampoline pointers. ObjectMetadataBuilder takes care of setting up
593/// relocations, so a linker can automatically fill in actuall addesses of
594/// all relavant functions. There is no need to piece the information together
595/// in the glue C file.
596pub struct ObjectMetadataBuilder {
597    placeholder_data: Vec<u8>,
598    metadata_length: u64,
599    section_offset: u64,
600    num_function_pointers: u64,
601    num_trampolines: u64,
602    num_dynamic_function_trampoline_pointers: u64,
603    endianness: Endianness,
604    pointer_width: PointerWidth,
605}
606
607impl ObjectMetadataBuilder {
608    /// Creates a new FunctionRelocsBuilder
609    pub fn new(metadata: &ModuleMetadata, triple: &Triple) -> Result<Self, ObjectError> {
610        let serialized_data = metadata.serialize()?;
611        let mut metadata_binary = vec![];
612        metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
613        metadata_binary.extend(serialized_data);
614        let metadata_length = metadata_binary.len() as u64;
615
616        let pointer_width = triple.pointer_width().unwrap();
617        let endianness = triple
618            .endianness()
619            .map_err(|_| ObjectError::UnknownEndianness)?;
620
621        let module = &metadata.compile_info.module;
622        let num_function_pointers = module
623            .functions
624            .iter()
625            .filter(|(f_index, _)| module.local_func_index(*f_index).is_some())
626            .count() as u64;
627        let num_trampolines = module.signatures.len() as u64;
628        let num_dynamic_function_trampoline_pointers = module.num_imported_functions as u64;
629
630        let mut aself = Self {
631            placeholder_data: metadata_binary,
632            metadata_length,
633            section_offset: 0,
634            num_function_pointers,
635            num_trampolines,
636            num_dynamic_function_trampoline_pointers,
637            endianness,
638            pointer_width,
639        };
640
641        aself
642            .placeholder_data
643            .extend_from_slice(&aself.serialize_value(aself.num_function_pointers));
644        aself.placeholder_data.extend_from_slice(&vec![
645            0u8;
646            (aself.pointer_bytes() * aself.num_function_pointers)
647                as usize
648        ]);
649        aself
650            .placeholder_data
651            .extend_from_slice(&aself.serialize_value(aself.num_trampolines));
652        aself.placeholder_data.extend_from_slice(&vec![
653            0u8;
654            (aself.pointer_bytes() * aself.num_trampolines)
655                as usize
656        ]);
657        aself.placeholder_data.extend_from_slice(
658            &aself.serialize_value(aself.num_dynamic_function_trampoline_pointers),
659        );
660        aself.placeholder_data.extend_from_slice(&vec![
661            0u8;
662            (aself.pointer_bytes() * aself.num_dynamic_function_trampoline_pointers)
663                as usize
664        ]);
665
666        Ok(aself)
667    }
668
669    /// Sets section offset used in relocations
670    pub fn set_section_offset(&mut self, offset: u64) {
671        self.section_offset = offset;
672    }
673
674    /// Placeholder data for emit_data call
675    pub fn placeholder_data(&self) -> &[u8] {
676        &self.placeholder_data
677    }
678
679    /// Bytes of a pointer for target architecture
680    pub fn pointer_bytes(&self) -> u64 {
681        self.pointer_width.bytes() as u64
682    }
683
684    /// Sets up relocation for a function pointer
685    pub fn setup_function_pointer(
686        &self,
687        obj: &mut Object,
688        index: usize,
689        symbol_id: SymbolId,
690    ) -> Result<(), ObjectError> {
691        let section_id = obj.section_id(StandardSection::Data);
692        obj.add_relocation(
693            section_id,
694            Relocation {
695                offset: self.function_pointers_start_offset()
696                    + self.pointer_bytes() * (index as u64),
697                size: self.pointer_width.bits(),
698                kind: RelocationKind::Absolute,
699                encoding: RelocationEncoding::Generic,
700                symbol: symbol_id,
701                addend: 0,
702            },
703        )
704        .map_err(ObjectError::Write)
705    }
706
707    /// Sets up relocation for a trampoline
708    pub fn setup_trampoline(
709        &self,
710        obj: &mut Object,
711        index: usize,
712        symbol_id: SymbolId,
713    ) -> Result<(), ObjectError> {
714        let section_id = obj.section_id(StandardSection::Data);
715        obj.add_relocation(
716            section_id,
717            Relocation {
718                offset: self.trampolines_start_offset() + self.pointer_bytes() * (index as u64),
719                size: self.pointer_width.bits(),
720                kind: RelocationKind::Absolute,
721                encoding: RelocationEncoding::Generic,
722                symbol: symbol_id,
723                addend: 0,
724            },
725        )
726        .map_err(ObjectError::Write)
727    }
728
729    /// Sets up relocation for a dynamic function trampoline pointer
730    pub fn setup_dynamic_function_trampoline_pointer(
731        &self,
732        obj: &mut Object,
733        index: usize,
734        symbol_id: SymbolId,
735    ) -> Result<(), ObjectError> {
736        let section_id = obj.section_id(StandardSection::Data);
737        obj.add_relocation(
738            section_id,
739            Relocation {
740                offset: self.dynamic_function_trampoline_pointers_start_offset()
741                    + self.pointer_bytes() * (index as u64),
742                size: self.pointer_width.bits(),
743                kind: RelocationKind::Absolute,
744                encoding: RelocationEncoding::Generic,
745                symbol: symbol_id,
746                addend: 0,
747            },
748        )
749        .map_err(ObjectError::Write)
750    }
751
752    fn function_pointers_start_offset(&self) -> u64 {
753        self.section_offset + self.metadata_length + self.pointer_bytes()
754    }
755
756    fn trampolines_start_offset(&self) -> u64 {
757        self.function_pointers_start_offset()
758            + self.pointer_bytes() * self.num_function_pointers
759            + self.pointer_bytes()
760    }
761
762    fn dynamic_function_trampoline_pointers_start_offset(&self) -> u64 {
763        self.trampolines_start_offset()
764            + self.pointer_bytes() * self.num_trampolines
765            + self.pointer_bytes()
766    }
767
768    fn serialize_value(&self, value: u64) -> Vec<u8> {
769        match (self.endianness, self.pointer_width) {
770            (Endianness::Little, PointerWidth::U16) => (value as u16).to_le_bytes().to_vec(),
771            (Endianness::Big, PointerWidth::U16) => (value as u16).to_be_bytes().to_vec(),
772            (Endianness::Little, PointerWidth::U32) => (value as u32).to_le_bytes().to_vec(),
773            (Endianness::Big, PointerWidth::U32) => (value as u32).to_be_bytes().to_vec(),
774            (Endianness::Little, PointerWidth::U64) => value.to_le_bytes().to_vec(),
775            (Endianness::Big, PointerWidth::U64) => value.to_be_bytes().to_vec(),
776        }
777    }
778}