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