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
25pub 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::Riscv32(_) => object::Architecture::Riscv32,
55 Architecture::LoongArch64 => object::Architecture::LoongArch64,
56 architecture => {
57 return Err(ObjectError::UnsupportedArchitecture(format!(
58 "{architecture}"
59 )));
60 }
61 };
62 let obj_endianness = match triple
63 .endianness()
64 .map_err(|_| ObjectError::UnknownEndianness)?
65 {
66 Endianness::Little => object::Endianness::Little,
67 Endianness::Big => object::Endianness::Big,
68 };
69
70 let mut object = Object::new(obj_binary_format, obj_architecture, obj_endianness);
71
72 if let Architecture::Riscv64(_) = triple.architecture {
73 object.flags = FileFlags::Elf {
74 e_flags: elf::EF_RISCV_FLOAT_ABI_DOUBLE,
75 os_abi: 2,
76 abi_version: 0,
77 };
78 }
79
80 Ok(object)
81}
82
83pub fn emit_data(
99 obj: &mut Object,
100 name: &[u8],
101 data: &[u8],
102 align: u64,
103) -> Result<u64, ObjectError> {
104 let symbol_id = obj.add_symbol(ObjSymbol {
105 name: name.to_vec(),
106 value: 0,
107 size: 0,
108 kind: SymbolKind::Data,
109 scope: SymbolScope::Dynamic,
110 weak: false,
111 section: SymbolSection::Undefined,
112 flags: SymbolFlags::None,
113 });
114 let section_id = obj.section_id(StandardSection::Data);
115 let offset = obj.add_symbol_data(symbol_id, section_id, data, align);
116
117 Ok(offset)
118}
119
120pub fn emit_compilation(
141 obj: &mut Object,
142 compilation: Compilation,
143 symbol_registry: &impl SymbolRegistry,
144 triple: &Triple,
145 relocs_builder: &ObjectMetadataBuilder,
146) -> Result<(), ObjectError> {
147 let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
148 let mut function_relocations = PrimaryMap::with_capacity(compilation.functions.len());
149 for (_, func) in compilation.functions.into_iter() {
150 function_bodies.push(func.body);
151 function_relocations.push(func.relocations);
152 }
153 let custom_section_relocations = compilation
154 .custom_sections
155 .iter()
156 .map(|(_, section)| section.relocations.clone())
157 .collect::<PrimaryMap<SectionIndex, _>>();
158
159 let debug_index = compilation.unwind_info.eh_frame;
160
161 let default_align = match triple.architecture {
162 target_lexicon::Architecture::Aarch64(_) => {
163 if matches!(
164 triple.operating_system,
165 target_lexicon::OperatingSystem::Darwin(_)
166 ) {
167 8
168 } else {
169 4
170 }
171 }
172 _ => 1,
173 };
174
175 let custom_section_ids = compilation
177 .custom_sections
178 .into_iter()
179 .map(|(section_index, custom_section)| {
180 if debug_index == Some(section_index) {
181 let segment = obj.segment_name(StandardSegment::Debug).to_vec();
183 let section_id =
184 obj.add_section(segment, DWARF_SECTION_NAME.to_vec(), SectionKind::Debug);
185 obj.append_section_data(section_id, custom_section.bytes.as_slice(), default_align);
186 let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
187 let symbol_id = obj.add_symbol(ObjSymbol {
188 name: section_name.into_bytes(),
189 value: 0,
190 size: custom_section.bytes.len() as _,
191 kind: SymbolKind::Data,
192 scope: SymbolScope::Compilation,
193 weak: false,
194 section: SymbolSection::Section(section_id),
195 flags: SymbolFlags::None,
196 });
197 (section_id, symbol_id)
198 } else {
199 let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
200 let (section_kind, standard_section) = match custom_section.protection {
201 CustomSectionProtection::ReadExecute => {
202 (SymbolKind::Text, StandardSection::Text)
203 }
204 CustomSectionProtection::Read => (SymbolKind::Data, StandardSection::Data),
205 };
206 let section_id = obj.section_id(standard_section);
207 let symbol_id = obj.add_symbol(ObjSymbol {
208 name: section_name.into_bytes(),
209 value: 0,
210 size: custom_section.bytes.len() as _,
211 kind: section_kind,
212 scope: SymbolScope::Dynamic,
213 weak: false,
214 section: SymbolSection::Section(section_id),
215 flags: SymbolFlags::None,
216 });
217 obj.add_symbol_data(
218 symbol_id,
219 section_id,
220 custom_section.bytes.as_slice(),
221 custom_section.alignment.unwrap_or(default_align),
222 );
223 (section_id, symbol_id)
224 }
225 })
226 .collect::<PrimaryMap<SectionIndex, _>>();
227
228 let function_symbol_ids = function_bodies
230 .into_iter()
231 .map(|(function_local_index, function)| {
232 let function_name =
233 symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index));
234 let section_id = obj.section_id(StandardSection::Text);
235 let symbol_id = obj.add_symbol(ObjSymbol {
236 name: function_name.into_bytes(),
237 value: 0,
238 size: function.body.len() as _,
239 kind: SymbolKind::Text,
240 scope: SymbolScope::Dynamic,
241 weak: false,
242 section: SymbolSection::Section(section_id),
243 flags: SymbolFlags::None,
244 });
245 let symbol_offset =
246 obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
247 (section_id, symbol_id, symbol_offset)
248 })
249 .collect::<PrimaryMap<LocalFunctionIndex, _>>();
250 for (i, (_, symbol_id, _)) in function_symbol_ids.iter() {
251 relocs_builder.setup_function_pointer(obj, i.index(), *symbol_id)?;
252 }
253
254 for (signature_index, function) in compilation.function_call_trampolines.into_iter() {
256 let function_name =
257 symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(signature_index));
258 let section_id = obj.section_id(StandardSection::Text);
259 let symbol_id = obj.add_symbol(ObjSymbol {
260 name: function_name.into_bytes(),
261 value: 0,
262 size: function.body.len() as _,
263 kind: SymbolKind::Text,
264 scope: SymbolScope::Dynamic,
265 weak: false,
266 section: SymbolSection::Section(section_id),
267 flags: SymbolFlags::None,
268 });
269 obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
270
271 relocs_builder.setup_trampoline(obj, signature_index.index(), symbol_id)?;
272 }
273
274 for (func_index, function) in compilation.dynamic_function_trampolines.into_iter() {
276 let function_name =
277 symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
278 let section_id = obj.section_id(StandardSection::Text);
279 let symbol_id = obj.add_symbol(ObjSymbol {
280 name: function_name.into_bytes(),
281 value: 0,
282 size: function.body.len() as _,
283 kind: SymbolKind::Text,
284 scope: SymbolScope::Dynamic,
285 weak: false,
286 section: SymbolSection::Section(section_id),
287 flags: SymbolFlags::None,
288 });
289 obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
290
291 relocs_builder.setup_dynamic_function_trampoline_pointer(
292 obj,
293 func_index.index(),
294 symbol_id,
295 )?;
296 }
297
298 let mut all_relocations = Vec::new();
299
300 for (function_local_index, relocations) in function_relocations.into_iter() {
301 let (section_id, symbol_id, _) = function_symbol_ids.get(function_local_index).unwrap();
302 all_relocations.push((*section_id, *symbol_id, relocations))
303 }
304
305 for (section_index, relocations) in custom_section_relocations.into_iter() {
306 if debug_index != Some(section_index) {
307 let (section_id, symbol_id) = custom_section_ids.get(section_index).unwrap();
309 all_relocations.push((*section_id, *symbol_id, relocations));
310 }
311 }
312
313 for (section_id, symbol_id, relocations) in all_relocations.into_iter() {
314 let (_symbol_id, section_offset) = obj.symbol_section_and_offset(symbol_id).unwrap();
315
316 for r in relocations {
317 let relocation_address = section_offset + r.offset as u64;
318
319 let relocation_flags = match r.kind {
320 Reloc::Abs4 => RelocationFlags::Generic {
321 kind: RelocationKind::Absolute,
322 encoding: RelocationEncoding::Generic,
323 size: 32,
324 },
325 Reloc::Abs8 => RelocationFlags::Generic {
326 kind: RelocationKind::Absolute,
327 encoding: RelocationEncoding::Generic,
328 size: 64,
329 },
330 Reloc::PCRel4 => RelocationFlags::Generic {
331 kind: RelocationKind::Relative,
332 encoding: RelocationEncoding::Generic,
333 size: 32,
334 },
335 Reloc::X86CallPCRel4 => RelocationFlags::Generic {
336 kind: RelocationKind::Relative,
337 encoding: RelocationEncoding::X86Branch,
338 size: 32,
339 },
340 Reloc::X86CallPLTRel4 => RelocationFlags::Generic {
341 kind: RelocationKind::PltRelative,
342 encoding: RelocationEncoding::X86Branch,
343 size: 32,
344 },
345 Reloc::X86GOTPCRel4 => RelocationFlags::Generic {
346 kind: RelocationKind::GotRelative,
347 encoding: RelocationEncoding::Generic,
348 size: 32,
349 },
350 Reloc::Arm64Call => match obj.format() {
351 object::BinaryFormat::Elf => RelocationFlags::Elf {
352 r_type: elf::R_AARCH64_CALL26,
353 },
354 object::BinaryFormat::MachO => RelocationFlags::MachO {
355 r_type: macho::ARM64_RELOC_BRANCH26,
356 r_pcrel: true,
357 r_length: 32,
358 },
359 fmt => panic!("unsupported binary format {fmt:?}"),
360 },
361 Reloc::ElfX86_64TlsGd => RelocationFlags::Elf {
362 r_type: elf::R_X86_64_TLSGD,
363 },
364 Reloc::MachoArm64RelocBranch26 => RelocationFlags::MachO {
365 r_type: macho::ARM64_RELOC_BRANCH26,
366 r_pcrel: true,
367 r_length: 32,
368 },
369
370 Reloc::MachoArm64RelocUnsigned => RelocationFlags::MachO {
371 r_type: macho::ARM64_RELOC_UNSIGNED,
372 r_pcrel: true,
373 r_length: 32,
374 },
375 Reloc::MachoArm64RelocSubtractor => RelocationFlags::MachO {
376 r_type: macho::ARM64_RELOC_SUBTRACTOR,
377 r_pcrel: false,
378 r_length: 64,
379 },
380 Reloc::MachoArm64RelocPage21 => RelocationFlags::MachO {
381 r_type: macho::ARM64_RELOC_PAGE21,
382 r_pcrel: true,
383 r_length: 32,
384 },
385 Reloc::MachoArm64RelocPageoff12 => RelocationFlags::MachO {
386 r_type: macho::ARM64_RELOC_PAGEOFF12,
387 r_pcrel: false,
388 r_length: 32,
389 },
390 Reloc::MachoArm64RelocGotLoadPage21 => RelocationFlags::MachO {
391 r_type: macho::ARM64_RELOC_GOT_LOAD_PAGE21,
392 r_pcrel: true,
393 r_length: 32,
394 },
395 Reloc::MachoArm64RelocGotLoadPageoff12 => RelocationFlags::MachO {
396 r_type: macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
397 r_pcrel: true,
398 r_length: 32,
399 },
400 Reloc::MachoArm64RelocPointerToGot => RelocationFlags::MachO {
401 r_type: macho::ARM64_RELOC_POINTER_TO_GOT,
402 r_pcrel: true,
403 r_length: 32,
404 },
405 Reloc::MachoArm64RelocTlvpLoadPage21 => RelocationFlags::MachO {
406 r_type: macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
407 r_pcrel: true,
408 r_length: 32,
409 },
410 Reloc::MachoArm64RelocTlvpLoadPageoff12 => RelocationFlags::MachO {
411 r_type: macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
412 r_pcrel: true,
413 r_length: 32,
414 },
415 Reloc::MachoArm64RelocAddend => RelocationFlags::MachO {
416 r_type: macho::ARM64_RELOC_ADDEND,
417 r_pcrel: false,
418 r_length: 32,
419 },
420 Reloc::RiscvPCRelHi20 => RelocationFlags::Elf {
423 r_type: elf::R_RISCV_PCREL_HI20,
424 },
425 Reloc::RiscvPCRelLo12I => RelocationFlags::Elf {
426 r_type: elf::R_RISCV_PCREL_LO12_I,
427 },
428 Reloc::RiscvCall => RelocationFlags::Elf {
429 r_type: elf::R_RISCV_CALL_PLT,
430 },
431 other => {
432 return Err(ObjectError::UnsupportedArchitecture(format!(
433 "{} (relocation: {other:?})",
434 triple.architecture
435 )));
436 }
437 };
438
439 match r.reloc_target {
440 RelocationTarget::LocalFunc(index) => {
441 let (target_section, target_symbol, target_symbol_offset) =
442 function_symbol_ids.get(index).unwrap();
443 if r.kind == Reloc::RiscvPCRelLo12I && r.addend != 0 {
444 let function_name =
448 symbol_registry.symbol_to_name(Symbol::LocalFunction(index));
449 let hi_symbol_name = format!("{}_offset_{}", function_name, r.addend);
450 let hi_symbol =
451 obj.symbol_id(hi_symbol_name.as_bytes()).unwrap_or_else(|| {
452 obj.add_symbol(ObjSymbol {
453 name: hi_symbol_name.as_bytes().to_vec(),
454 value: *target_symbol_offset + r.addend as u64,
455 size: 0,
456 kind: SymbolKind::Label,
457 scope: SymbolScope::Compilation,
458 weak: false,
459 section: SymbolSection::Section(*target_section),
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: hi_symbol,
469 addend: 0,
470 },
471 )
472 .map_err(ObjectError::Write)?;
473 } else {
474 obj.add_relocation(
475 section_id,
476 Relocation {
477 offset: relocation_address,
478 flags: relocation_flags,
479 symbol: *target_symbol,
480 addend: r.addend,
481 },
482 )
483 .map_err(ObjectError::Write)?;
484 }
485 }
486 RelocationTarget::DynamicTrampoline(_) => todo!("Not supported yet"),
487 RelocationTarget::LibCall(libcall) => {
488 let mut libcall_fn_name = libcall.to_function_name().to_string();
489 if matches!(triple.binary_format, BinaryFormat::Macho) {
490 libcall_fn_name = format!("_{libcall_fn_name}");
491 }
492
493 let libcall_fn_name = libcall_fn_name.as_bytes();
494
495 let target_symbol = obj.symbol_id(libcall_fn_name).unwrap_or_else(|| {
497 obj.add_symbol(ObjSymbol {
498 name: libcall_fn_name.to_vec(),
499 value: 0,
500 size: 0,
501 kind: SymbolKind::Unknown,
502 scope: SymbolScope::Unknown,
503 weak: false,
504 section: SymbolSection::Undefined,
505 flags: SymbolFlags::None,
506 })
507 });
508 obj.add_relocation(
509 section_id,
510 Relocation {
511 offset: relocation_address,
512 flags: relocation_flags,
513 symbol: target_symbol,
514 addend: r.addend,
515 },
516 )
517 .map_err(ObjectError::Write)?;
518 }
519 RelocationTarget::CustomSection(section_index) => {
520 let (_, target_symbol) = custom_section_ids.get(section_index).unwrap();
521 obj.add_relocation(
522 section_id,
523 Relocation {
524 offset: relocation_address,
525 flags: relocation_flags,
526 symbol: *target_symbol,
527 addend: r.addend,
528 },
529 )
530 .map_err(ObjectError::Write)?;
531 }
532 };
533 }
534 }
535
536 Ok(())
537}
538
539pub fn emit_serialized(
560 obj: &mut Object,
561 sercomp: &[u8],
562 triple: &Triple,
563 object_name: &str,
564) -> Result<(), ObjectError> {
565 obj.set_mangling(object::write::Mangling::None);
566 let len_name = format!("{object_name}_LENGTH");
568 let data_name = format!("{object_name}_DATA");
569 let align = match triple.architecture {
572 Architecture::X86_64 => 1,
573 Architecture::Aarch64(_) => 4,
575 _ => 1,
576 };
577
578 let len = sercomp.len();
579 let section_id = obj.section_id(StandardSection::Data);
580 let symbol_id = obj.add_symbol(ObjSymbol {
581 name: len_name.as_bytes().to_vec(),
582 value: 0,
583 size: len.to_le_bytes().len() as _,
584 kind: SymbolKind::Data,
585 scope: SymbolScope::Dynamic,
586 weak: false,
587 section: SymbolSection::Section(section_id),
588 flags: SymbolFlags::None,
589 });
590 obj.add_symbol_data(symbol_id, section_id, &len.to_le_bytes(), align);
591
592 let section_id = obj.section_id(StandardSection::Data);
593 let symbol_id = obj.add_symbol(ObjSymbol {
594 name: data_name.as_bytes().to_vec(),
595 value: 0,
596 size: sercomp.len() as _,
597 kind: SymbolKind::Data,
598 scope: SymbolScope::Dynamic,
599 weak: false,
600 section: SymbolSection::Section(section_id),
601 flags: SymbolFlags::None,
602 });
603 obj.add_symbol_data(symbol_id, section_id, sercomp, align);
604
605 Ok(())
606}
607
608pub struct ObjectMetadataBuilder {
616 placeholder_data: Vec<u8>,
617 metadata_length: u64,
618 section_offset: u64,
619 num_function_pointers: u64,
620 num_trampolines: u64,
621 num_dynamic_function_trampoline_pointers: u64,
622 endianness: Endianness,
623 pointer_width: PointerWidth,
624}
625
626impl ObjectMetadataBuilder {
627 pub fn new(metadata: &ModuleMetadata, triple: &Triple) -> Result<Self, ObjectError> {
629 let serialized_data = metadata.serialize()?;
630 let mut metadata_binary = vec![];
631 metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
632 metadata_binary.extend(serialized_data);
633 let metadata_length = metadata_binary.len() as u64;
634
635 let pointer_width = triple.pointer_width().unwrap();
636 let endianness = triple
637 .endianness()
638 .map_err(|_| ObjectError::UnknownEndianness)?;
639
640 let module = &metadata.compile_info.module;
641 let num_function_pointers = module
642 .functions
643 .iter()
644 .filter(|(f_index, _)| module.local_func_index(*f_index).is_some())
645 .count() as u64;
646 let num_trampolines = module.signatures.len() as u64;
647 let num_dynamic_function_trampoline_pointers = module.num_imported_functions as u64;
648
649 let mut aself = Self {
650 placeholder_data: metadata_binary,
651 metadata_length,
652 section_offset: 0,
653 num_function_pointers,
654 num_trampolines,
655 num_dynamic_function_trampoline_pointers,
656 endianness,
657 pointer_width,
658 };
659
660 aself
661 .placeholder_data
662 .extend_from_slice(&aself.serialize_value(aself.num_function_pointers));
663 aself.placeholder_data.extend_from_slice(&vec![
664 0u8;
665 (aself.pointer_bytes() * aself.num_function_pointers)
666 as usize
667 ]);
668 aself
669 .placeholder_data
670 .extend_from_slice(&aself.serialize_value(aself.num_trampolines));
671 aself.placeholder_data.extend_from_slice(&vec![
672 0u8;
673 (aself.pointer_bytes() * aself.num_trampolines)
674 as usize
675 ]);
676 aself.placeholder_data.extend_from_slice(
677 &aself.serialize_value(aself.num_dynamic_function_trampoline_pointers),
678 );
679 aself.placeholder_data.extend_from_slice(&vec![
680 0u8;
681 (aself.pointer_bytes() * aself.num_dynamic_function_trampoline_pointers)
682 as usize
683 ]);
684
685 Ok(aself)
686 }
687
688 pub fn set_section_offset(&mut self, offset: u64) {
690 self.section_offset = offset;
691 }
692
693 pub fn placeholder_data(&self) -> &[u8] {
695 &self.placeholder_data
696 }
697
698 pub fn pointer_bytes(&self) -> u64 {
700 self.pointer_width.bytes() as u64
701 }
702
703 pub fn setup_function_pointer(
705 &self,
706 obj: &mut Object,
707 index: usize,
708 symbol_id: SymbolId,
709 ) -> Result<(), ObjectError> {
710 let section_id = obj.section_id(StandardSection::Data);
711 obj.add_relocation(
712 section_id,
713 Relocation {
714 offset: self.function_pointers_start_offset()
715 + self.pointer_bytes() * (index as u64),
716 flags: RelocationFlags::Generic {
717 kind: RelocationKind::Absolute,
718 encoding: RelocationEncoding::Generic,
719 size: self.pointer_width.bits(),
720 },
721 symbol: symbol_id,
722 addend: 0,
723 },
724 )
725 .map_err(ObjectError::Write)
726 }
727
728 pub fn setup_trampoline(
730 &self,
731 obj: &mut Object,
732 index: usize,
733 symbol_id: SymbolId,
734 ) -> Result<(), ObjectError> {
735 let section_id = obj.section_id(StandardSection::Data);
736 obj.add_relocation(
737 section_id,
738 Relocation {
739 offset: self.trampolines_start_offset() + self.pointer_bytes() * (index as u64),
740 flags: RelocationFlags::Generic {
741 kind: RelocationKind::Absolute,
742 encoding: RelocationEncoding::Generic,
743 size: self.pointer_width.bits(),
744 },
745 symbol: symbol_id,
746 addend: 0,
747 },
748 )
749 .map_err(ObjectError::Write)
750 }
751
752 pub fn setup_dynamic_function_trampoline_pointer(
754 &self,
755 obj: &mut Object,
756 index: usize,
757 symbol_id: SymbolId,
758 ) -> Result<(), ObjectError> {
759 let section_id = obj.section_id(StandardSection::Data);
760 obj.add_relocation(
761 section_id,
762 Relocation {
763 offset: self.dynamic_function_trampoline_pointers_start_offset()
764 + self.pointer_bytes() * (index as u64),
765 flags: RelocationFlags::Generic {
766 kind: RelocationKind::Absolute,
767 encoding: RelocationEncoding::Generic,
768 size: self.pointer_width.bits(),
769 },
770 symbol: symbol_id,
771 addend: 0,
772 },
773 )
774 .map_err(ObjectError::Write)
775 }
776
777 fn function_pointers_start_offset(&self) -> u64 {
778 self.section_offset + self.metadata_length + self.pointer_bytes()
779 }
780
781 fn trampolines_start_offset(&self) -> u64 {
782 self.function_pointers_start_offset()
783 + self.pointer_bytes() * self.num_function_pointers
784 + self.pointer_bytes()
785 }
786
787 fn dynamic_function_trampoline_pointers_start_offset(&self) -> u64 {
788 self.trampolines_start_offset()
789 + self.pointer_bytes() * self.num_trampolines
790 + self.pointer_bytes()
791 }
792
793 fn serialize_value(&self, value: u64) -> Vec<u8> {
794 match (self.endianness, self.pointer_width) {
795 (Endianness::Little, PointerWidth::U16) => (value as u16).to_le_bytes().to_vec(),
796 (Endianness::Big, PointerWidth::U16) => (value as u16).to_be_bytes().to_vec(),
797 (Endianness::Little, PointerWidth::U32) => (value as u32).to_le_bytes().to_vec(),
798 (Endianness::Big, PointerWidth::U32) => (value as u32).to_be_bytes().to_vec(),
799 (Endianness::Little, PointerWidth::U64) => value.to_le_bytes().to_vec(),
800 (Endianness::Big, PointerWidth::U64) => value.to_be_bytes().to_vec(),
801 }
802 }
803}