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    FileFlags, RelocationEncoding, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
13    SymbolScope, elf, macho,
14    write::{
15        Object, Relocation, StandardSection, StandardSegment, Symbol as ObjSymbol, SymbolId,
16        SymbolSection,
17    },
18};
19use wasmer_types::LocalFunctionIndex;
20use wasmer_types::entity::{EntityRef, PrimaryMap};
21use wasmer_types::target::{Architecture, BinaryFormat, Endianness, PointerWidth, Triple};
22
23const DWARF_SECTION_NAME: &[u8] = b".eh_frame";
24
25/// Create an object for a given target `Triple`.
26///
27/// # Usage
28///
29/// ```rust
30/// # use wasmer_types::target::Triple;
31/// # use wasmer_compiler::object::{ObjectError, get_object_for_target};
32///
33/// # fn generate_object_for_target(triple: &Triple) -> Result<(), ObjectError> {
34/// let mut object = get_object_for_target(&triple)?;
35///
36/// # Ok(())
37/// # }
38/// ```
39pub fn get_object_for_target(triple: &Triple) -> Result<Object<'static>, ObjectError> {
40    let obj_binary_format = match triple.binary_format {
41        BinaryFormat::Elf => object::BinaryFormat::Elf,
42        BinaryFormat::Macho => object::BinaryFormat::MachO,
43        BinaryFormat::Coff => object::BinaryFormat::Coff,
44        binary_format => {
45            return Err(ObjectError::UnsupportedBinaryFormat(format!(
46                "{binary_format}"
47            )));
48        }
49    };
50    let obj_architecture = match triple.architecture {
51        Architecture::X86_64 => object::Architecture::X86_64,
52        Architecture::Aarch64(_) => object::Architecture::Aarch64,
53        Architecture::Riscv64(_) => object::Architecture::Riscv64,
54        Architecture::LoongArch64 => object::Architecture::LoongArch64,
55        architecture => {
56            return Err(ObjectError::UnsupportedArchitecture(format!(
57                "{architecture}"
58            )));
59        }
60    };
61    let obj_endianness = match triple
62        .endianness()
63        .map_err(|_| ObjectError::UnknownEndianness)?
64    {
65        Endianness::Little => object::Endianness::Little,
66        Endianness::Big => object::Endianness::Big,
67    };
68
69    let mut object = Object::new(obj_binary_format, obj_architecture, obj_endianness);
70
71    if let Architecture::Riscv64(_) = triple.architecture {
72        object.flags = FileFlags::Elf {
73            e_flags: elf::EF_RISCV_FLOAT_ABI_DOUBLE,
74            os_abi: 2,
75            abi_version: 0,
76        };
77    }
78
79    Ok(object)
80}
81
82/// Write data into an existing object.
83///
84/// # Usage
85///
86/// ```rust
87/// # use wasmer_types::target::Triple;
88/// # use wasmer_compiler::object::{ObjectError, get_object_for_target, emit_data};
89///
90/// # fn emit_data_into_object(triple: &Triple) -> Result<(), ObjectError> {
91/// let mut object = get_object_for_target(&triple)?;
92/// emit_data(&mut object, b"WASMER_METADATA", &b"Hello, World!"[..], 1)?;
93///
94/// # Ok(())
95/// # }
96/// ```
97pub fn emit_data(
98    obj: &mut Object,
99    name: &[u8],
100    data: &[u8],
101    align: u64,
102) -> Result<u64, ObjectError> {
103    let symbol_id = obj.add_symbol(ObjSymbol {
104        name: name.to_vec(),
105        value: 0,
106        size: 0,
107        kind: SymbolKind::Data,
108        scope: SymbolScope::Dynamic,
109        weak: false,
110        section: SymbolSection::Undefined,
111        flags: SymbolFlags::None,
112    });
113    let section_id = obj.section_id(StandardSection::Data);
114    let offset = obj.add_symbol_data(symbol_id, section_id, data, align);
115
116    Ok(offset)
117}
118
119/// Emit the compilation result into an existing object.
120///
121/// # Usage
122///
123/// ```rust
124/// # use wasmer_compiler::types::{ symbols::SymbolRegistry, function::{Compilation} };
125/// # use wasmer_types::target::Triple;
126/// # use wasmer_compiler::object::{ObjectError, ObjectMetadataBuilder, get_object_for_target, emit_compilation};
127///
128/// # fn emit_compilation_into_object(
129/// #     triple: &Triple,
130/// #     compilation: Compilation,
131/// #     builder: ObjectMetadataBuilder,
132/// #     symbol_registry: impl SymbolRegistry,
133/// # ) -> Result<(), ObjectError> {
134/// let mut object = get_object_for_target(&triple)?;
135/// emit_compilation(&mut object, compilation, &symbol_registry, &triple, &builder)?;
136/// # Ok(())
137/// # }
138/// ```
139pub fn emit_compilation(
140    obj: &mut Object,
141    compilation: Compilation,
142    symbol_registry: &impl SymbolRegistry,
143    triple: &Triple,
144    relocs_builder: &ObjectMetadataBuilder,
145) -> Result<(), ObjectError> {
146    let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
147    let mut function_relocations = PrimaryMap::with_capacity(compilation.functions.len());
148    for (_, func) in compilation.functions.into_iter() {
149        function_bodies.push(func.body);
150        function_relocations.push(func.relocations);
151    }
152    let custom_section_relocations = compilation
153        .custom_sections
154        .iter()
155        .map(|(_, section)| section.relocations.clone())
156        .collect::<PrimaryMap<SectionIndex, _>>();
157
158    let debug_index = compilation.unwind_info.eh_frame;
159
160    let default_align = match triple.architecture {
161        target_lexicon::Architecture::Aarch64(_) => {
162            if matches!(
163                triple.operating_system,
164                target_lexicon::OperatingSystem::Darwin(_)
165            ) {
166                8
167            } else {
168                4
169            }
170        }
171        _ => 1,
172    };
173
174    // Add sections
175    let custom_section_ids = compilation
176        .custom_sections
177        .into_iter()
178        .map(|(section_index, custom_section)| {
179            if debug_index == Some(section_index) {
180                // If this is the debug section
181                let segment = obj.segment_name(StandardSegment::Debug).to_vec();
182                let section_id =
183                    obj.add_section(segment, DWARF_SECTION_NAME.to_vec(), SectionKind::Debug);
184                obj.append_section_data(section_id, custom_section.bytes.as_slice(), default_align);
185                let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
186                let symbol_id = obj.add_symbol(ObjSymbol {
187                    name: section_name.into_bytes(),
188                    value: 0,
189                    size: custom_section.bytes.len() as _,
190                    kind: SymbolKind::Data,
191                    scope: SymbolScope::Compilation,
192                    weak: false,
193                    section: SymbolSection::Section(section_id),
194                    flags: SymbolFlags::None,
195                });
196                (section_id, symbol_id)
197            } else {
198                let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
199                let (section_kind, standard_section) = match custom_section.protection {
200                    CustomSectionProtection::ReadExecute => {
201                        (SymbolKind::Text, StandardSection::Text)
202                    }
203                    CustomSectionProtection::Read => (SymbolKind::Data, StandardSection::Data),
204                };
205                let section_id = obj.section_id(standard_section);
206                let symbol_id = obj.add_symbol(ObjSymbol {
207                    name: section_name.into_bytes(),
208                    value: 0,
209                    size: custom_section.bytes.len() as _,
210                    kind: section_kind,
211                    scope: SymbolScope::Dynamic,
212                    weak: false,
213                    section: SymbolSection::Section(section_id),
214                    flags: SymbolFlags::None,
215                });
216                obj.add_symbol_data(
217                    symbol_id,
218                    section_id,
219                    custom_section.bytes.as_slice(),
220                    custom_section.alignment.unwrap_or(default_align),
221                );
222                (section_id, symbol_id)
223            }
224        })
225        .collect::<PrimaryMap<SectionIndex, _>>();
226
227    // Add functions
228    let function_symbol_ids = function_bodies
229        .into_iter()
230        .map(|(function_local_index, function)| {
231            let function_name =
232                symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index));
233            let section_id = obj.section_id(StandardSection::Text);
234            let symbol_id = obj.add_symbol(ObjSymbol {
235                name: function_name.into_bytes(),
236                value: 0,
237                size: function.body.len() as _,
238                kind: SymbolKind::Text,
239                scope: SymbolScope::Dynamic,
240                weak: false,
241                section: SymbolSection::Section(section_id),
242                flags: SymbolFlags::None,
243            });
244            obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
245            (section_id, symbol_id)
246        })
247        .collect::<PrimaryMap<LocalFunctionIndex, _>>();
248    for (i, (_, symbol_id)) in function_symbol_ids.iter() {
249        relocs_builder.setup_function_pointer(obj, i.index(), *symbol_id)?;
250    }
251
252    // Add function call trampolines
253    for (signature_index, function) in compilation.function_call_trampolines.into_iter() {
254        let function_name =
255            symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(signature_index));
256        let section_id = obj.section_id(StandardSection::Text);
257        let symbol_id = obj.add_symbol(ObjSymbol {
258            name: function_name.into_bytes(),
259            value: 0,
260            size: function.body.len() as _,
261            kind: SymbolKind::Text,
262            scope: SymbolScope::Dynamic,
263            weak: false,
264            section: SymbolSection::Section(section_id),
265            flags: SymbolFlags::None,
266        });
267        obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
268
269        relocs_builder.setup_trampoline(obj, signature_index.index(), symbol_id)?;
270    }
271
272    // Add dynamic function trampolines
273    for (func_index, function) in compilation.dynamic_function_trampolines.into_iter() {
274        let function_name =
275            symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
276        let section_id = obj.section_id(StandardSection::Text);
277        let symbol_id = obj.add_symbol(ObjSymbol {
278            name: function_name.into_bytes(),
279            value: 0,
280            size: function.body.len() as _,
281            kind: SymbolKind::Text,
282            scope: SymbolScope::Dynamic,
283            weak: false,
284            section: SymbolSection::Section(section_id),
285            flags: SymbolFlags::None,
286        });
287        obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
288
289        relocs_builder.setup_dynamic_function_trampoline_pointer(
290            obj,
291            func_index.index(),
292            symbol_id,
293        )?;
294    }
295
296    let mut all_relocations = Vec::new();
297
298    for (function_local_index, relocations) in function_relocations.into_iter() {
299        let (section_id, symbol_id) = function_symbol_ids.get(function_local_index).unwrap();
300        all_relocations.push((*section_id, *symbol_id, relocations))
301    }
302
303    for (section_index, relocations) in custom_section_relocations.into_iter() {
304        if debug_index != Some(section_index) {
305            // Skip DWARF relocations just yet
306            let (section_id, symbol_id) = custom_section_ids.get(section_index).unwrap();
307            all_relocations.push((*section_id, *symbol_id, relocations));
308        }
309    }
310
311    for (section_id, symbol_id, relocations) in all_relocations.into_iter() {
312        let (_symbol_id, section_offset) = obj.symbol_section_and_offset(symbol_id).unwrap();
313
314        for r in relocations {
315            let relocation_address = section_offset + r.offset as u64;
316
317            let (relocation_kind, relocation_encoding, relocation_size) = match r.kind {
318                Reloc::Abs4 => (RelocationKind::Absolute, RelocationEncoding::Generic, 32),
319                Reloc::Abs8 => (RelocationKind::Absolute, RelocationEncoding::Generic, 64),
320                Reloc::X86PCRel4 => (RelocationKind::Relative, RelocationEncoding::Generic, 32),
321                Reloc::X86CallPCRel4 => {
322                    (RelocationKind::Relative, RelocationEncoding::X86Branch, 32)
323                }
324                Reloc::X86CallPLTRel4 => (
325                    RelocationKind::PltRelative,
326                    RelocationEncoding::X86Branch,
327                    32,
328                ),
329                Reloc::X86GOTPCRel4 => {
330                    (RelocationKind::GotRelative, RelocationEncoding::Generic, 32)
331                }
332                Reloc::Arm64Call => (
333                    match obj.format() {
334                        object::BinaryFormat::Elf => RelocationKind::Elf(elf::R_AARCH64_CALL26),
335                        object::BinaryFormat::MachO => RelocationKind::MachO {
336                            value: macho::ARM64_RELOC_BRANCH26,
337                            relative: true,
338                        },
339                        fmt => panic!("unsupported binary format {fmt:?}"),
340                    },
341                    RelocationEncoding::Generic,
342                    32,
343                ),
344                Reloc::ElfX86_64TlsGd => (
345                    RelocationKind::Elf(elf::R_X86_64_TLSGD),
346                    RelocationEncoding::Generic,
347                    32,
348                ),
349                Reloc::MachoArm64RelocBranch26 => (
350                    RelocationKind::MachO {
351                        value: macho::ARM64_RELOC_BRANCH26,
352                        relative: true,
353                    },
354                    RelocationEncoding::Generic,
355                    32,
356                ),
357                Reloc::MachoArm64RelocUnsigned => (
358                    RelocationKind::MachO {
359                        value: object::macho::ARM64_RELOC_UNSIGNED,
360                        relative: true,
361                    },
362                    RelocationEncoding::Generic,
363                    32,
364                ),
365                Reloc::MachoArm64RelocSubtractor => (
366                    RelocationKind::MachO {
367                        value: object::macho::ARM64_RELOC_SUBTRACTOR,
368                        relative: false,
369                    },
370                    RelocationEncoding::Generic,
371                    64,
372                ),
373                Reloc::MachoArm64RelocPage21 => (
374                    RelocationKind::MachO {
375                        value: object::macho::ARM64_RELOC_PAGE21,
376                        relative: true,
377                    },
378                    RelocationEncoding::Generic,
379                    32,
380                ),
381
382                Reloc::MachoArm64RelocPageoff12 => (
383                    RelocationKind::MachO {
384                        value: object::macho::ARM64_RELOC_PAGEOFF12,
385                        relative: false,
386                    },
387                    RelocationEncoding::Generic,
388                    32,
389                ),
390                Reloc::MachoArm64RelocGotLoadPage21 => (
391                    RelocationKind::MachO {
392                        value: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
393                        relative: true,
394                    },
395                    RelocationEncoding::Generic,
396                    32,
397                ),
398                Reloc::MachoArm64RelocGotLoadPageoff12 => (
399                    RelocationKind::MachO {
400                        value: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
401                        relative: true,
402                    },
403                    RelocationEncoding::Generic,
404                    32,
405                ),
406                Reloc::MachoArm64RelocPointerToGot => (
407                    RelocationKind::MachO {
408                        value: object::macho::ARM64_RELOC_POINTER_TO_GOT,
409                        relative: true,
410                    },
411                    RelocationEncoding::Generic,
412                    32,
413                ),
414                Reloc::MachoArm64RelocTlvpLoadPage21 => (
415                    RelocationKind::MachO {
416                        value: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
417                        relative: true,
418                    },
419                    RelocationEncoding::Generic,
420                    32,
421                ),
422                Reloc::MachoArm64RelocTlvpLoadPageoff12 => (
423                    RelocationKind::MachO {
424                        value: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
425                        relative: true,
426                    },
427                    RelocationEncoding::Generic,
428                    32,
429                ),
430                Reloc::MachoArm64RelocAddend => (
431                    RelocationKind::MachO {
432                        value: object::macho::ARM64_RELOC_ADDEND,
433                        relative: false,
434                    },
435                    RelocationEncoding::Generic,
436                    32,
437                ),
438
439                other => {
440                    return Err(ObjectError::UnsupportedArchitecture(format!(
441                        "{} (relocation: {})",
442                        triple.architecture, other
443                    )));
444                }
445            };
446
447            match r.reloc_target {
448                RelocationTarget::LocalFunc(index) => {
449                    let (_, target_symbol) = function_symbol_ids.get(index).unwrap();
450                    obj.add_relocation(
451                        section_id,
452                        Relocation {
453                            offset: relocation_address,
454                            size: relocation_size,
455                            kind: relocation_kind,
456                            encoding: relocation_encoding,
457                            symbol: *target_symbol,
458                            addend: r.addend,
459                        },
460                    )
461                    .map_err(ObjectError::Write)?;
462                }
463                RelocationTarget::DynamicTrampoline(_) => todo!("Not supported yet"),
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}