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, RelocationFlags, RelocationKind, SectionKind, SymbolFlags,
13    SymbolKind, 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_flags = match r.kind {
318                Reloc::Abs4 => RelocationFlags::Generic {
319                    kind: RelocationKind::Absolute,
320                    encoding: RelocationEncoding::Generic,
321                    size: 32,
322                },
323
324                Reloc::Abs8 => RelocationFlags::Generic {
325                    kind: RelocationKind::Absolute,
326                    encoding: RelocationEncoding::Generic,
327                    size: 64,
328                },
329                Reloc::X86PCRel4 => RelocationFlags::Generic {
330                    kind: RelocationKind::Relative,
331                    encoding: RelocationEncoding::Generic,
332                    size: 32,
333                },
334                Reloc::X86CallPCRel4 => RelocationFlags::Generic {
335                    kind: RelocationKind::Relative,
336                    encoding: RelocationEncoding::X86Branch,
337                    size: 32,
338                },
339                Reloc::X86CallPLTRel4 => RelocationFlags::Generic {
340                    kind: RelocationKind::PltRelative,
341                    encoding: RelocationEncoding::X86Branch,
342                    size: 32,
343                },
344                Reloc::X86GOTPCRel4 => RelocationFlags::Generic {
345                    kind: RelocationKind::GotRelative,
346                    encoding: RelocationEncoding::Generic,
347                    size: 32,
348                },
349                Reloc::Arm64Call => match obj.format() {
350                    object::BinaryFormat::Elf => RelocationFlags::Elf {
351                        r_type: elf::R_AARCH64_CALL26,
352                    },
353                    object::BinaryFormat::MachO => RelocationFlags::MachO {
354                        r_type: macho::ARM64_RELOC_BRANCH26,
355                        r_pcrel: true,
356                        r_length: 32,
357                    },
358                    fmt => panic!("unsupported binary format {fmt:?}"),
359                },
360                Reloc::ElfX86_64TlsGd => RelocationFlags::Elf {
361                    r_type: elf::R_X86_64_TLSGD,
362                },
363                Reloc::MachoArm64RelocBranch26 => RelocationFlags::MachO {
364                    r_type: macho::ARM64_RELOC_BRANCH26,
365                    r_pcrel: true,
366                    r_length: 32,
367                },
368
369                Reloc::MachoArm64RelocUnsigned => RelocationFlags::MachO {
370                    r_type: macho::ARM64_RELOC_UNSIGNED,
371                    r_pcrel: true,
372                    r_length: 32,
373                },
374                Reloc::MachoArm64RelocSubtractor => RelocationFlags::MachO {
375                    r_type: macho::ARM64_RELOC_SUBTRACTOR,
376                    r_pcrel: false,
377                    r_length: 64,
378                },
379                Reloc::MachoArm64RelocPage21 => RelocationFlags::MachO {
380                    r_type: macho::ARM64_RELOC_PAGE21,
381                    r_pcrel: true,
382                    r_length: 32,
383                },
384                Reloc::MachoArm64RelocPageoff12 => RelocationFlags::MachO {
385                    r_type: macho::ARM64_RELOC_PAGEOFF12,
386                    r_pcrel: false,
387                    r_length: 32,
388                },
389                Reloc::MachoArm64RelocGotLoadPage21 => RelocationFlags::MachO {
390                    r_type: macho::ARM64_RELOC_GOT_LOAD_PAGE21,
391                    r_pcrel: true,
392                    r_length: 32,
393                },
394                Reloc::MachoArm64RelocGotLoadPageoff12 => RelocationFlags::MachO {
395                    r_type: macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
396                    r_pcrel: true,
397                    r_length: 32,
398                },
399                Reloc::MachoArm64RelocPointerToGot => RelocationFlags::MachO {
400                    r_type: macho::ARM64_RELOC_POINTER_TO_GOT,
401                    r_pcrel: true,
402                    r_length: 32,
403                },
404                Reloc::MachoArm64RelocTlvpLoadPage21 => RelocationFlags::MachO {
405                    r_type: macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
406                    r_pcrel: true,
407                    r_length: 32,
408                },
409                Reloc::MachoArm64RelocTlvpLoadPageoff12 => RelocationFlags::MachO {
410                    r_type: macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
411                    r_pcrel: true,
412                    r_length: 32,
413                },
414                Reloc::MachoArm64RelocAddend => RelocationFlags::MachO {
415                    r_type: macho::ARM64_RELOC_ADDEND,
416                    r_pcrel: false,
417                    r_length: 32,
418                },
419                other => {
420                    return Err(ObjectError::UnsupportedArchitecture(format!(
421                        "{} (relocation: {})",
422                        triple.architecture, other
423                    )));
424                }
425            };
426
427            match r.reloc_target {
428                RelocationTarget::LocalFunc(index) => {
429                    let (_, target_symbol) = function_symbol_ids.get(index).unwrap();
430                    obj.add_relocation(
431                        section_id,
432                        Relocation {
433                            offset: relocation_address,
434                            flags: relocation_flags,
435                            symbol: *target_symbol,
436                            addend: r.addend,
437                        },
438                    )
439                    .map_err(ObjectError::Write)?;
440                }
441                RelocationTarget::DynamicTrampoline(_) => todo!("Not supported yet"),
442                RelocationTarget::LibCall(libcall) => {
443                    let mut libcall_fn_name = libcall.to_function_name().to_string();
444                    if matches!(triple.binary_format, BinaryFormat::Macho) {
445                        libcall_fn_name = format!("_{libcall_fn_name}");
446                    }
447
448                    let libcall_fn_name = libcall_fn_name.as_bytes();
449
450                    // We add the symols lazily as we see them
451                    let target_symbol = obj.symbol_id(libcall_fn_name).unwrap_or_else(|| {
452                        obj.add_symbol(ObjSymbol {
453                            name: libcall_fn_name.to_vec(),
454                            value: 0,
455                            size: 0,
456                            kind: SymbolKind::Unknown,
457                            scope: SymbolScope::Unknown,
458                            weak: false,
459                            section: SymbolSection::Undefined,
460                            flags: SymbolFlags::None,
461                        })
462                    });
463                    obj.add_relocation(
464                        section_id,
465                        Relocation {
466                            offset: relocation_address,
467                            flags: relocation_flags,
468                            symbol: target_symbol,
469                            addend: r.addend,
470                        },
471                    )
472                    .map_err(ObjectError::Write)?;
473                }
474                RelocationTarget::CustomSection(section_index) => {
475                    let (_, target_symbol) = custom_section_ids.get(section_index).unwrap();
476                    obj.add_relocation(
477                        section_id,
478                        Relocation {
479                            offset: relocation_address,
480                            flags: relocation_flags,
481                            symbol: *target_symbol,
482                            addend: r.addend,
483                        },
484                    )
485                    .map_err(ObjectError::Write)?;
486                }
487            };
488        }
489    }
490
491    Ok(())
492}
493
494/// Emit the compilation result into an existing object.
495///
496/// # Usage
497///
498/// ```rust
499/// # use wasmer_compiler::types::{ symbols::SymbolRegistry, function::{Compilation} };
500/// # use wasmer_types::target::Triple;
501/// # use wasmer_compiler::object::{ObjectError, get_object_for_target, emit_serialized};
502///
503/// # fn emit_compilation_into_object(
504/// #     triple: &Triple,
505/// #     compilation: Compilation,
506/// #     symbol_registry: impl SymbolRegistry,
507/// # ) -> Result<(), ObjectError> {
508/// let bytes = &[ /* compilation bytes */];
509/// let mut object = get_object_for_target(&triple)?;
510/// emit_serialized(&mut object, bytes, &triple, "WASMER_MODULE")?;
511/// # Ok(())
512/// # }
513/// ```
514pub fn emit_serialized(
515    obj: &mut Object,
516    sercomp: &[u8],
517    triple: &Triple,
518    object_name: &str,
519) -> Result<(), ObjectError> {
520    obj.set_mangling(object::write::Mangling::None);
521    //let module_name = module.compile_info.module.name.clone();
522    let len_name = format!("{object_name}_LENGTH");
523    let data_name = format!("{object_name}_DATA");
524    //let metadata_name = "WASMER_MODULE_METADATA";
525
526    let align = match triple.architecture {
527        Architecture::X86_64 => 1,
528        // In Arm64 is recommended a 4-byte alignment
529        Architecture::Aarch64(_) => 4,
530        _ => 1,
531    };
532
533    let len = sercomp.len();
534    let section_id = obj.section_id(StandardSection::Data);
535    let symbol_id = obj.add_symbol(ObjSymbol {
536        name: len_name.as_bytes().to_vec(),
537        value: 0,
538        size: len.to_le_bytes().len() as _,
539        kind: SymbolKind::Data,
540        scope: SymbolScope::Dynamic,
541        weak: false,
542        section: SymbolSection::Section(section_id),
543        flags: SymbolFlags::None,
544    });
545    obj.add_symbol_data(symbol_id, section_id, &len.to_le_bytes(), align);
546
547    let section_id = obj.section_id(StandardSection::Data);
548    let symbol_id = obj.add_symbol(ObjSymbol {
549        name: data_name.as_bytes().to_vec(),
550        value: 0,
551        size: sercomp.len() as _,
552        kind: SymbolKind::Data,
553        scope: SymbolScope::Dynamic,
554        weak: false,
555        section: SymbolSection::Section(section_id),
556        flags: SymbolFlags::None,
557    });
558    obj.add_symbol_data(symbol_id, section_id, sercomp, align);
559
560    Ok(())
561}
562
563/// ObjectMetadataBuilder builds serialized module metadata include in
564/// an object. In addition, it also relies on information from ModuleInfo
565/// to build a table of function pointers, trmampolines and dynamic function
566/// trampoline pointers. ObjectMetadataBuilder takes care of setting up
567/// relocations, so a linker can automatically fill in actuall addesses of
568/// all relavant functions. There is no need to piece the information together
569/// in the glue C file.
570pub struct ObjectMetadataBuilder {
571    placeholder_data: Vec<u8>,
572    metadata_length: u64,
573    section_offset: u64,
574    num_function_pointers: u64,
575    num_trampolines: u64,
576    num_dynamic_function_trampoline_pointers: u64,
577    endianness: Endianness,
578    pointer_width: PointerWidth,
579}
580
581impl ObjectMetadataBuilder {
582    /// Creates a new FunctionRelocsBuilder
583    pub fn new(metadata: &ModuleMetadata, triple: &Triple) -> Result<Self, ObjectError> {
584        let serialized_data = metadata.serialize()?;
585        let mut metadata_binary = vec![];
586        metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
587        metadata_binary.extend(serialized_data);
588        let metadata_length = metadata_binary.len() as u64;
589
590        let pointer_width = triple.pointer_width().unwrap();
591        let endianness = triple
592            .endianness()
593            .map_err(|_| ObjectError::UnknownEndianness)?;
594
595        let module = &metadata.compile_info.module;
596        let num_function_pointers = module
597            .functions
598            .iter()
599            .filter(|(f_index, _)| module.local_func_index(*f_index).is_some())
600            .count() as u64;
601        let num_trampolines = module.signatures.len() as u64;
602        let num_dynamic_function_trampoline_pointers = module.num_imported_functions as u64;
603
604        let mut aself = Self {
605            placeholder_data: metadata_binary,
606            metadata_length,
607            section_offset: 0,
608            num_function_pointers,
609            num_trampolines,
610            num_dynamic_function_trampoline_pointers,
611            endianness,
612            pointer_width,
613        };
614
615        aself
616            .placeholder_data
617            .extend_from_slice(&aself.serialize_value(aself.num_function_pointers));
618        aself.placeholder_data.extend_from_slice(&vec![
619            0u8;
620            (aself.pointer_bytes() * aself.num_function_pointers)
621                as usize
622        ]);
623        aself
624            .placeholder_data
625            .extend_from_slice(&aself.serialize_value(aself.num_trampolines));
626        aself.placeholder_data.extend_from_slice(&vec![
627            0u8;
628            (aself.pointer_bytes() * aself.num_trampolines)
629                as usize
630        ]);
631        aself.placeholder_data.extend_from_slice(
632            &aself.serialize_value(aself.num_dynamic_function_trampoline_pointers),
633        );
634        aself.placeholder_data.extend_from_slice(&vec![
635            0u8;
636            (aself.pointer_bytes() * aself.num_dynamic_function_trampoline_pointers)
637                as usize
638        ]);
639
640        Ok(aself)
641    }
642
643    /// Sets section offset used in relocations
644    pub fn set_section_offset(&mut self, offset: u64) {
645        self.section_offset = offset;
646    }
647
648    /// Placeholder data for emit_data call
649    pub fn placeholder_data(&self) -> &[u8] {
650        &self.placeholder_data
651    }
652
653    /// Bytes of a pointer for target architecture
654    pub fn pointer_bytes(&self) -> u64 {
655        self.pointer_width.bytes() as u64
656    }
657
658    /// Sets up relocation for a function pointer
659    pub fn setup_function_pointer(
660        &self,
661        obj: &mut Object,
662        index: usize,
663        symbol_id: SymbolId,
664    ) -> Result<(), ObjectError> {
665        let section_id = obj.section_id(StandardSection::Data);
666        obj.add_relocation(
667            section_id,
668            Relocation {
669                offset: self.function_pointers_start_offset()
670                    + self.pointer_bytes() * (index as u64),
671                flags: RelocationFlags::Generic {
672                    kind: RelocationKind::Absolute,
673                    encoding: RelocationEncoding::Generic,
674                    size: self.pointer_width.bits(),
675                },
676                symbol: symbol_id,
677                addend: 0,
678            },
679        )
680        .map_err(ObjectError::Write)
681    }
682
683    /// Sets up relocation for a trampoline
684    pub fn setup_trampoline(
685        &self,
686        obj: &mut Object,
687        index: usize,
688        symbol_id: SymbolId,
689    ) -> Result<(), ObjectError> {
690        let section_id = obj.section_id(StandardSection::Data);
691        obj.add_relocation(
692            section_id,
693            Relocation {
694                offset: self.trampolines_start_offset() + self.pointer_bytes() * (index as u64),
695                flags: RelocationFlags::Generic {
696                    kind: RelocationKind::Absolute,
697                    encoding: RelocationEncoding::Generic,
698                    size: self.pointer_width.bits(),
699                },
700                symbol: symbol_id,
701                addend: 0,
702            },
703        )
704        .map_err(ObjectError::Write)
705    }
706
707    /// Sets up relocation for a dynamic function trampoline pointer
708    pub fn setup_dynamic_function_trampoline_pointer(
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.dynamic_function_trampoline_pointers_start_offset()
719                    + self.pointer_bytes() * (index as u64),
720                flags: RelocationFlags::Generic {
721                    kind: RelocationKind::Absolute,
722                    encoding: RelocationEncoding::Generic,
723                    size: self.pointer_width.bits(),
724                },
725                symbol: symbol_id,
726                addend: 0,
727            },
728        )
729        .map_err(ObjectError::Write)
730    }
731
732    fn function_pointers_start_offset(&self) -> u64 {
733        self.section_offset + self.metadata_length + self.pointer_bytes()
734    }
735
736    fn trampolines_start_offset(&self) -> u64 {
737        self.function_pointers_start_offset()
738            + self.pointer_bytes() * self.num_function_pointers
739            + self.pointer_bytes()
740    }
741
742    fn dynamic_function_trampoline_pointers_start_offset(&self) -> u64 {
743        self.trampolines_start_offset()
744            + self.pointer_bytes() * self.num_trampolines
745            + self.pointer_bytes()
746    }
747
748    fn serialize_value(&self, value: u64) -> Vec<u8> {
749        match (self.endianness, self.pointer_width) {
750            (Endianness::Little, PointerWidth::U16) => (value as u16).to_le_bytes().to_vec(),
751            (Endianness::Big, PointerWidth::U16) => (value as u16).to_be_bytes().to_vec(),
752            (Endianness::Little, PointerWidth::U32) => (value as u32).to_le_bytes().to_vec(),
753            (Endianness::Big, PointerWidth::U32) => (value as u32).to_be_bytes().to_vec(),
754            (Endianness::Little, PointerWidth::U64) => value.to_le_bytes().to_vec(),
755            (Endianness::Big, PointerWidth::U64) => value.to_be_bytes().to_vec(),
756        }
757    }
758}