1use super::error::ObjectError;
2use crate::{
3 serialize::MetadataHeader,
4 types::{
5 function::RkyvCompilation,
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::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
82pub 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
119pub fn emit_compilation(
140 obj: &mut Object,
141 compilation: RkyvCompilation,
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 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 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 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 let symbol_offset =
245 obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
246 (section_id, symbol_id, symbol_offset)
247 })
248 .collect::<PrimaryMap<LocalFunctionIndex, _>>();
249 for (i, (_, symbol_id, _)) in function_symbol_ids.iter() {
250 relocs_builder.setup_function_pointer(obj, i.index(), *symbol_id)?;
251 }
252
253 for (signature_index, function) in compilation.function_call_trampolines.into_iter() {
255 let function_name =
256 symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(signature_index));
257 let section_id = obj.section_id(StandardSection::Text);
258 let symbol_id = obj.add_symbol(ObjSymbol {
259 name: function_name.into_bytes(),
260 value: 0,
261 size: function.body.len() as _,
262 kind: SymbolKind::Text,
263 scope: SymbolScope::Dynamic,
264 weak: false,
265 section: SymbolSection::Section(section_id),
266 flags: SymbolFlags::None,
267 });
268 obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
269
270 relocs_builder.setup_trampoline(obj, signature_index.index(), symbol_id)?;
271 }
272
273 for (func_index, function) in compilation.dynamic_function_trampolines.into_iter() {
275 let function_name =
276 symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
277 let section_id = obj.section_id(StandardSection::Text);
278 let symbol_id = obj.add_symbol(ObjSymbol {
279 name: function_name.into_bytes(),
280 value: 0,
281 size: function.body.len() as _,
282 kind: SymbolKind::Text,
283 scope: SymbolScope::Dynamic,
284 weak: false,
285 section: SymbolSection::Section(section_id),
286 flags: SymbolFlags::None,
287 });
288 obj.add_symbol_data(symbol_id, section_id, &function.body, default_align);
289
290 relocs_builder.setup_dynamic_function_trampoline_pointer(
291 obj,
292 func_index.index(),
293 symbol_id,
294 )?;
295 }
296
297 let mut all_relocations = Vec::new();
298
299 for (function_local_index, relocations) in function_relocations.into_iter() {
300 let (section_id, symbol_id, _) = function_symbol_ids.get(function_local_index).unwrap();
301 all_relocations.push((*section_id, *symbol_id, relocations))
302 }
303
304 for (section_index, relocations) in custom_section_relocations.into_iter() {
305 if debug_index != Some(section_index) {
306 let (section_id, symbol_id) = custom_section_ids.get(section_index).unwrap();
308 all_relocations.push((*section_id, *symbol_id, relocations));
309 }
310 }
311
312 for (section_id, symbol_id, relocations) in all_relocations.into_iter() {
313 let (_symbol_id, section_offset) = obj.symbol_section_and_offset(symbol_id).unwrap();
314
315 for r in relocations {
316 let relocation_address = section_offset + r.offset as u64;
317
318 let relocation_flags = match r.kind {
319 Reloc::Abs4 => RelocationFlags::Generic {
320 kind: RelocationKind::Absolute,
321 encoding: RelocationEncoding::Generic,
322 size: 32,
323 },
324 Reloc::Abs8 => RelocationFlags::Generic {
325 kind: RelocationKind::Absolute,
326 encoding: RelocationEncoding::Generic,
327 size: 64,
328 },
329 Reloc::PCRel4 => 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 Reloc::RiscvPCRelHi20 => RelocationFlags::Elf {
422 r_type: elf::R_RISCV_PCREL_HI20,
423 },
424 Reloc::RiscvPCRelLo12I => RelocationFlags::Elf {
425 r_type: elf::R_RISCV_PCREL_LO12_I,
426 },
427 Reloc::RiscvCall => RelocationFlags::Elf {
428 r_type: elf::R_RISCV_CALL_PLT,
429 },
430 other => {
431 return Err(ObjectError::UnsupportedArchitecture(format!(
432 "{} (relocation: {other:?})",
433 triple.architecture
434 )));
435 }
436 };
437
438 match r.reloc_target {
439 RelocationTarget::LocalFunc(index) => {
440 let (target_section, target_symbol, target_symbol_offset) =
441 function_symbol_ids.get(index).unwrap();
442 if r.kind == Reloc::RiscvPCRelLo12I && r.addend != 0 {
443 let function_name =
447 symbol_registry.symbol_to_name(Symbol::LocalFunction(index));
448 let hi_symbol_name = format!("{}_offset_{}", function_name, r.addend);
449 let hi_symbol =
450 obj.symbol_id(hi_symbol_name.as_bytes()).unwrap_or_else(|| {
451 obj.add_symbol(ObjSymbol {
452 name: hi_symbol_name.as_bytes().to_vec(),
453 value: *target_symbol_offset + r.addend as u64,
454 size: 0,
455 kind: SymbolKind::Label,
456 scope: SymbolScope::Compilation,
457 weak: false,
458 section: SymbolSection::Section(*target_section),
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: hi_symbol,
468 addend: 0,
469 },
470 )
471 .map_err(ObjectError::Write)?;
472 } else {
473 obj.add_relocation(
474 section_id,
475 Relocation {
476 offset: relocation_address,
477 flags: relocation_flags,
478 symbol: *target_symbol,
479 addend: r.addend,
480 },
481 )
482 .map_err(ObjectError::Write)?;
483 }
484 }
485 RelocationTarget::DynamicTrampoline(_) => todo!("Not supported yet"),
486 RelocationTarget::LibCall(libcall) => {
487 let mut libcall_fn_name = libcall.to_function_name().to_string();
488 if matches!(triple.binary_format, BinaryFormat::Macho) {
489 libcall_fn_name = format!("_{libcall_fn_name}");
490 }
491
492 let libcall_fn_name = libcall_fn_name.as_bytes();
493
494 let target_symbol = obj.symbol_id(libcall_fn_name).unwrap_or_else(|| {
496 obj.add_symbol(ObjSymbol {
497 name: libcall_fn_name.to_vec(),
498 value: 0,
499 size: 0,
500 kind: SymbolKind::Unknown,
501 scope: SymbolScope::Unknown,
502 weak: false,
503 section: SymbolSection::Undefined,
504 flags: SymbolFlags::None,
505 })
506 });
507 obj.add_relocation(
508 section_id,
509 Relocation {
510 offset: relocation_address,
511 flags: relocation_flags,
512 symbol: target_symbol,
513 addend: r.addend,
514 },
515 )
516 .map_err(ObjectError::Write)?;
517 }
518 RelocationTarget::CustomSection(section_index) => {
519 let (_, target_symbol) = custom_section_ids.get(section_index).unwrap();
520 obj.add_relocation(
521 section_id,
522 Relocation {
523 offset: relocation_address,
524 flags: relocation_flags,
525 symbol: *target_symbol,
526 addend: r.addend,
527 },
528 )
529 .map_err(ObjectError::Write)?;
530 }
531 };
532 }
533 }
534
535 Ok(())
536}
537
538pub fn emit_serialized(
559 obj: &mut Object,
560 sercomp: &[u8],
561 triple: &Triple,
562 object_name: &str,
563) -> Result<(), ObjectError> {
564 obj.set_mangling(object::write::Mangling::None);
565 let len_name = format!("{object_name}_LENGTH");
567 let data_name = format!("{object_name}_DATA");
568 let align = match triple.architecture {
571 Architecture::X86_64 => 1,
572 Architecture::Aarch64(_) => 4,
574 _ => 1,
575 };
576
577 let len = sercomp.len();
578 let section_id = obj.section_id(StandardSection::Data);
579 let symbol_id = obj.add_symbol(ObjSymbol {
580 name: len_name.as_bytes().to_vec(),
581 value: 0,
582 size: len.to_le_bytes().len() as _,
583 kind: SymbolKind::Data,
584 scope: SymbolScope::Dynamic,
585 weak: false,
586 section: SymbolSection::Section(section_id),
587 flags: SymbolFlags::None,
588 });
589 obj.add_symbol_data(symbol_id, section_id, &len.to_le_bytes(), align);
590
591 let section_id = obj.section_id(StandardSection::Data);
592 let symbol_id = obj.add_symbol(ObjSymbol {
593 name: data_name.as_bytes().to_vec(),
594 value: 0,
595 size: sercomp.len() as _,
596 kind: SymbolKind::Data,
597 scope: SymbolScope::Dynamic,
598 weak: false,
599 section: SymbolSection::Section(section_id),
600 flags: SymbolFlags::None,
601 });
602 obj.add_symbol_data(symbol_id, section_id, sercomp, align);
603
604 Ok(())
605}
606
607pub struct ObjectMetadataBuilder {
615 placeholder_data: Vec<u8>,
616 metadata_length: u64,
617 section_offset: u64,
618 num_function_pointers: u64,
619 num_trampolines: u64,
620 num_dynamic_function_trampoline_pointers: u64,
621 endianness: Endianness,
622 pointer_width: PointerWidth,
623}
624
625impl ObjectMetadataBuilder {
626 pub fn new(metadata: &ModuleMetadata, triple: &Triple) -> Result<Self, ObjectError> {
628 let serialized_data = metadata.serialize()?;
629 let mut metadata_binary = vec![];
630 metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
631 metadata_binary.extend(serialized_data);
632 let metadata_length = metadata_binary.len() as u64;
633
634 let pointer_width = triple.pointer_width().unwrap();
635 let endianness = triple
636 .endianness()
637 .map_err(|_| ObjectError::UnknownEndianness)?;
638
639 let module = &metadata.compile_info.module;
640 let num_function_pointers = module
641 .functions
642 .iter()
643 .filter(|(f_index, _)| module.local_func_index(*f_index).is_some())
644 .count() as u64;
645 let num_trampolines = module.signatures.len() as u64;
646 let num_dynamic_function_trampoline_pointers = module.num_imported_functions as u64;
647
648 let mut aself = Self {
649 placeholder_data: metadata_binary,
650 metadata_length,
651 section_offset: 0,
652 num_function_pointers,
653 num_trampolines,
654 num_dynamic_function_trampoline_pointers,
655 endianness,
656 pointer_width,
657 };
658
659 aself
660 .placeholder_data
661 .extend_from_slice(&aself.serialize_value(aself.num_function_pointers)?);
662 aself.placeholder_data.extend_from_slice(&vec![
663 0u8;
664 (aself.pointer_bytes() * aself.num_function_pointers)
665 as usize
666 ]);
667 aself
668 .placeholder_data
669 .extend_from_slice(&aself.serialize_value(aself.num_trampolines)?);
670 aself.placeholder_data.extend_from_slice(&vec![
671 0u8;
672 (aself.pointer_bytes() * aself.num_trampolines)
673 as usize
674 ]);
675 aself.placeholder_data.extend_from_slice(
676 &aself.serialize_value(aself.num_dynamic_function_trampoline_pointers)?,
677 );
678 aself.placeholder_data.extend_from_slice(&vec![
679 0u8;
680 (aself.pointer_bytes() * aself.num_dynamic_function_trampoline_pointers)
681 as usize
682 ]);
683
684 Ok(aself)
685 }
686
687 pub fn set_section_offset(&mut self, offset: u64) {
689 self.section_offset = offset;
690 }
691
692 pub fn placeholder_data(&self) -> &[u8] {
694 &self.placeholder_data
695 }
696
697 pub fn pointer_bytes(&self) -> u64 {
699 self.pointer_width.bytes() as u64
700 }
701
702 pub fn setup_function_pointer(
704 &self,
705 obj: &mut Object,
706 index: usize,
707 symbol_id: SymbolId,
708 ) -> Result<(), ObjectError> {
709 let section_id = obj.section_id(StandardSection::Data);
710 obj.add_relocation(
711 section_id,
712 Relocation {
713 offset: self.function_pointers_start_offset()
714 + self.pointer_bytes() * (index as u64),
715 flags: RelocationFlags::Generic {
716 kind: RelocationKind::Absolute,
717 encoding: RelocationEncoding::Generic,
718 size: self.pointer_width.bits(),
719 },
720 symbol: symbol_id,
721 addend: 0,
722 },
723 )
724 .map_err(ObjectError::Write)
725 }
726
727 pub fn setup_trampoline(
729 &self,
730 obj: &mut Object,
731 index: usize,
732 symbol_id: SymbolId,
733 ) -> Result<(), ObjectError> {
734 let section_id = obj.section_id(StandardSection::Data);
735 obj.add_relocation(
736 section_id,
737 Relocation {
738 offset: self.trampolines_start_offset() + self.pointer_bytes() * (index as u64),
739 flags: RelocationFlags::Generic {
740 kind: RelocationKind::Absolute,
741 encoding: RelocationEncoding::Generic,
742 size: self.pointer_width.bits(),
743 },
744 symbol: symbol_id,
745 addend: 0,
746 },
747 )
748 .map_err(ObjectError::Write)
749 }
750
751 pub fn setup_dynamic_function_trampoline_pointer(
753 &self,
754 obj: &mut Object,
755 index: usize,
756 symbol_id: SymbolId,
757 ) -> Result<(), ObjectError> {
758 let section_id = obj.section_id(StandardSection::Data);
759 obj.add_relocation(
760 section_id,
761 Relocation {
762 offset: self.dynamic_function_trampoline_pointers_start_offset()
763 + self.pointer_bytes() * (index as u64),
764 flags: RelocationFlags::Generic {
765 kind: RelocationKind::Absolute,
766 encoding: RelocationEncoding::Generic,
767 size: self.pointer_width.bits(),
768 },
769 symbol: symbol_id,
770 addend: 0,
771 },
772 )
773 .map_err(ObjectError::Write)
774 }
775
776 fn function_pointers_start_offset(&self) -> u64 {
777 self.section_offset + self.metadata_length + self.pointer_bytes()
778 }
779
780 fn trampolines_start_offset(&self) -> u64 {
781 self.function_pointers_start_offset()
782 + self.pointer_bytes() * self.num_function_pointers
783 + self.pointer_bytes()
784 }
785
786 fn dynamic_function_trampoline_pointers_start_offset(&self) -> u64 {
787 self.trampolines_start_offset()
788 + self.pointer_bytes() * self.num_trampolines
789 + self.pointer_bytes()
790 }
791
792 fn serialize_value(&self, value: u64) -> Result<Vec<u8>, ObjectError> {
793 match (self.endianness, self.pointer_width) {
794 (Endianness::Little, PointerWidth::U64) => Ok(value.to_le_bytes().to_vec()),
795 (Endianness::Big, PointerWidth::U64) => Ok(value.to_be_bytes().to_vec()),
796 (_, PointerWidth::U16 | PointerWidth::U32) => {
797 Err(ObjectError::UnsupportedArchitecture(
798 "only 64-bit targets are supported".to_string(),
799 ))
800 }
801 }
802 }
803}