1use anyhow::anyhow;
4use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
5use cranelift_codegen::entity::SecondaryMap;
6use cranelift_codegen::ir;
7use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
8use cranelift_control::ControlPlane;
9use cranelift_module::{
10 DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleDeclarations, ModuleError,
11 ModuleReloc, ModuleRelocTarget, ModuleResult,
12};
13use log::{info, warn};
14use object::write::{
15 Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
16};
17use object::{
18 RelocationEncoding, RelocationFlags, RelocationKind, SectionFlags, SectionKind, SymbolFlags,
19 SymbolKind, SymbolScope, elf,
20};
21use std::collections::HashMap;
22use std::collections::hash_map::Entry;
23use std::mem;
24use target_lexicon::{PointerWidth, Triple};
25
26pub struct ObjectBuilder {
28 isa: OwnedTargetIsa,
29 binary_format: object::BinaryFormat,
30 architecture: object::Architecture,
31 flags: object::FileFlags,
32 endian: object::Endianness,
33 name: Vec<u8>,
34 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
35 per_function_section: bool,
36 per_data_object_section: bool,
37 #[cfg(feature = "unwind")]
38 unwind_info: bool,
39}
40
41impl ObjectBuilder {
42 pub fn new<V: Into<Vec<u8>>>(
50 isa: OwnedTargetIsa,
51 name: V,
52 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
53 ) -> ModuleResult<Self> {
54 let mut file_flags = object::FileFlags::None;
55 let binary_format = match isa.triple().binary_format {
56 target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
57 target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
58 target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
59 target_lexicon::BinaryFormat::Wasm => {
60 return Err(ModuleError::Backend(anyhow!(
61 "binary format wasm is unsupported",
62 )));
63 }
64 target_lexicon::BinaryFormat::Unknown => {
65 return Err(ModuleError::Backend(anyhow!("binary format is unknown")));
66 }
67 other => {
68 return Err(ModuleError::Backend(anyhow!(
69 "binary format {other} not recognized"
70 )));
71 }
72 };
73 let architecture = match isa.triple().architecture {
74 target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
75 target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
76 target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
77 target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
78 target_lexicon::Architecture::Riscv64(_) => {
79 if binary_format != object::BinaryFormat::Elf {
80 return Err(ModuleError::Backend(anyhow!(
81 "binary format {binary_format:?} is not supported for riscv64",
82 )));
83 }
84
85 let mut eflags = object::elf::EF_RISCV_FLOAT_ABI_DOUBLE;
87
88 let has_c = isa
90 .isa_flags()
91 .iter()
92 .filter(|f| f.name == "has_zca" || f.name == "has_zcd")
93 .all(|f| f.as_bool().unwrap_or_default());
94 if has_c {
95 eflags |= object::elf::EF_RISCV_RVC;
96 }
97
98 file_flags = object::FileFlags::Elf {
99 os_abi: object::elf::ELFOSABI_NONE,
100 abi_version: 0,
101 e_flags: eflags,
102 };
103 object::Architecture::Riscv64
104 }
105 target_lexicon::Architecture::S390x => object::Architecture::S390x,
106 architecture => {
107 return Err(ModuleError::Backend(anyhow!(
108 "target architecture {architecture:?} is unsupported",
109 )));
110 }
111 };
112 let endian = match isa.triple().endianness().unwrap() {
113 target_lexicon::Endianness::Little => object::Endianness::Little,
114 target_lexicon::Endianness::Big => object::Endianness::Big,
115 };
116 Ok(Self {
117 isa,
118 binary_format,
119 architecture,
120 flags: file_flags,
121 endian,
122 name: name.into(),
123 libcall_names,
124 per_function_section: false,
125 per_data_object_section: false,
126 #[cfg(feature = "unwind")]
127 unwind_info: false,
128 })
129 }
130
131 pub fn per_function_section(&mut self, per_function_section: bool) -> &mut Self {
133 self.per_function_section = per_function_section;
134 self
135 }
136
137 pub fn per_data_object_section(&mut self, per_data_object_section: bool) -> &mut Self {
139 self.per_data_object_section = per_data_object_section;
140 self
141 }
142
143 #[cfg(feature = "unwind")]
168 pub fn unwind_info(&mut self, unwind_info: bool) -> &mut Self {
169 self.unwind_info = unwind_info;
170 self
171 }
172}
173
174fn macho_build_version(triple: &Triple) -> Option<object::write::MachOBuildVersion> {
177 use target_lexicon::{DeploymentTarget, OperatingSystem::*};
178
179 fn pack_version(v: DeploymentTarget) -> u32 {
180 let (major, minor, patch) = (v.major as u32, v.minor as u32, v.patch as u32);
181 (major << 16) | (minor << 8) | patch
182 }
183
184 match triple.operating_system {
185 Darwin(v) | MacOSX(v) | IOS(v) | TvOS(v) | VisionOS(v) | WatchOS(v) | XROS(v) => {
186 use object::macho::*;
187 use target_lexicon::Environment::*;
188 let platform = match (triple.operating_system, triple.environment) {
193 (Darwin(_), _) => PLATFORM_MACOS,
196 (MacOSX(_), _) => PLATFORM_MACOS,
197 (_, Macabi) => PLATFORM_MACCATALYST,
198 (IOS(_), Sim) => PLATFORM_IOSSIMULATOR,
199 (IOS(_), _) => PLATFORM_IOS,
200 (TvOS(_), Sim) => PLATFORM_TVOSSIMULATOR,
201 (TvOS(_), _) => PLATFORM_TVOS,
202 (VisionOS(_) | XROS(_), Sim) => PLATFORM_XROSSIMULATOR,
203 (VisionOS(_) | XROS(_), _) => PLATFORM_XROS,
204 (WatchOS(_), Sim) => PLATFORM_WATCHOSSIMULATOR,
205 (WatchOS(_), _) => PLATFORM_WATCHOS,
206 _ => {
207 warn!("unsupported OS/environment: {triple}");
208 0
209 }
210 };
211
212 let mut build_version = object::write::MachOBuildVersion::default();
213 build_version.platform = platform;
214
215 build_version.minos = if let Some(v) = v {
216 pack_version(v)
217 } else {
218 0
226 };
227
228 build_version.sdk = 0;
231
232 Some(build_version)
233 }
234 _ => None,
235 }
236}
237
238pub struct ObjectModule {
242 isa: OwnedTargetIsa,
243 object: Object<'static>,
244 declarations: ModuleDeclarations,
245 functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
246 data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
247 relocs: Vec<SymbolRelocs>,
248 libcalls: HashMap<ir::LibCall, SymbolId>,
249 libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
250 known_symbols: HashMap<ir::KnownSymbol, SymbolId>,
251 known_labels: HashMap<(FuncId, CodeOffset), SymbolId>,
252 per_function_section: bool,
253 per_data_object_section: bool,
254 #[cfg(feature = "unwind")]
255 unwind: Option<crate::unwind::UnwindBuilder>,
256}
257
258impl ObjectModule {
259 pub fn new(builder: ObjectBuilder) -> Self {
261 let mut object = Object::new(builder.binary_format, builder.architecture, builder.endian);
262 object.flags = builder.flags;
263 object.set_subsections_via_symbols();
264 object.add_file_symbol(builder.name);
265 if let Some(info) = macho_build_version(builder.isa.triple()) {
266 object.set_macho_build_version(info);
271 }
272 #[cfg(feature = "unwind")]
273 let unwind = builder
274 .unwind_info
275 .then(|| crate::unwind::UnwindBuilder::new(builder.endian));
276 Self {
277 isa: builder.isa,
278 object,
279 declarations: ModuleDeclarations::default(),
280 functions: SecondaryMap::new(),
281 data_objects: SecondaryMap::new(),
282 relocs: Vec::new(),
283 libcalls: HashMap::new(),
284 libcall_names: builder.libcall_names,
285 known_symbols: HashMap::new(),
286 known_labels: HashMap::new(),
287 per_function_section: builder.per_function_section,
288 per_data_object_section: builder.per_data_object_section,
289 #[cfg(feature = "unwind")]
290 unwind,
291 }
292 }
293}
294
295fn validate_symbol(name: &str) -> ModuleResult<()> {
296 if name.contains("\0") {
299 return Err(ModuleError::Backend(anyhow::anyhow!(
300 "Symbol {name:?} has a null byte, which is disallowed"
301 )));
302 }
303 Ok(())
304}
305
306impl Module for ObjectModule {
307 fn isa(&self) -> &dyn TargetIsa {
308 &*self.isa
309 }
310
311 fn declarations(&self) -> &ModuleDeclarations {
312 &self.declarations
313 }
314
315 fn declare_function(
316 &mut self,
317 name: &str,
318 linkage: Linkage,
319 signature: &ir::Signature,
320 ) -> ModuleResult<FuncId> {
321 validate_symbol(name)?;
322
323 let (id, linkage) = self
324 .declarations
325 .declare_function(name, linkage, signature)?;
326
327 let (scope, weak) = translate_linkage(linkage);
328
329 if let Some((function, _defined)) = self.functions[id] {
330 let symbol = self.object.symbol_mut(function);
331 symbol.scope = scope;
332 symbol.weak = weak;
333 } else {
334 let symbol_id = self.object.add_symbol(Symbol {
335 name: name.as_bytes().to_vec(),
336 value: 0,
337 size: 0,
338 kind: SymbolKind::Text,
339 scope,
340 weak,
341 section: SymbolSection::Undefined,
342 flags: SymbolFlags::None,
343 });
344 self.functions[id] = Some((symbol_id, false));
345 }
346
347 Ok(id)
348 }
349
350 fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
351 let id = self.declarations.declare_anonymous_function(signature)?;
352
353 let symbol_id = self.object.add_symbol(Symbol {
354 name: self
355 .declarations
356 .get_function_decl(id)
357 .linkage_name(id)
358 .into_owned()
359 .into_bytes(),
360 value: 0,
361 size: 0,
362 kind: SymbolKind::Text,
363 scope: SymbolScope::Compilation,
364 weak: false,
365 section: SymbolSection::Undefined,
366 flags: SymbolFlags::None,
367 });
368 self.functions[id] = Some((symbol_id, false));
369
370 Ok(id)
371 }
372
373 fn declare_data(
374 &mut self,
375 name: &str,
376 linkage: Linkage,
377 writable: bool,
378 tls: bool,
379 ) -> ModuleResult<DataId> {
380 validate_symbol(name)?;
381
382 let (id, linkage) = self
383 .declarations
384 .declare_data(name, linkage, writable, tls)?;
385
386 let kind = if tls {
389 SymbolKind::Tls
390 } else {
391 SymbolKind::Data
392 };
393 let (scope, weak) = translate_linkage(linkage);
394
395 if let Some((data, _defined)) = self.data_objects[id] {
396 let symbol = self.object.symbol_mut(data);
397 symbol.kind = kind;
398 symbol.scope = scope;
399 symbol.weak = weak;
400 } else {
401 let symbol_id = self.object.add_symbol(Symbol {
402 name: name.as_bytes().to_vec(),
403 value: 0,
404 size: 0,
405 kind,
406 scope,
407 weak,
408 section: SymbolSection::Undefined,
409 flags: SymbolFlags::None,
410 });
411 self.data_objects[id] = Some((symbol_id, false));
412 }
413
414 Ok(id)
415 }
416
417 fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
418 let id = self.declarations.declare_anonymous_data(writable, tls)?;
419
420 let kind = if tls {
421 SymbolKind::Tls
422 } else {
423 SymbolKind::Data
424 };
425
426 let symbol_id = self.object.add_symbol(Symbol {
427 name: self
428 .declarations
429 .get_data_decl(id)
430 .linkage_name(id)
431 .into_owned()
432 .into_bytes(),
433 value: 0,
434 size: 0,
435 kind,
436 scope: SymbolScope::Compilation,
437 weak: false,
438 section: SymbolSection::Undefined,
439 flags: SymbolFlags::None,
440 });
441 self.data_objects[id] = Some((symbol_id, false));
442
443 Ok(id)
444 }
445
446 fn define_function_with_control_plane(
447 &mut self,
448 func_id: FuncId,
449 ctx: &mut cranelift_codegen::Context,
450 ctrl_plane: &mut ControlPlane,
451 ) -> ModuleResult<()> {
452 info!("defining function {}: {}", func_id, ctx.func.display());
453
454 let res = ctx.compile(self.isa(), ctrl_plane)?;
455 let alignment = res.buffer.alignment as u64;
456
457 let compiled = ctx.compiled_code().unwrap();
458 #[cfg(feature = "unwind")]
459 let unwind_info = if self.unwind.is_some() {
460 compiled.create_unwind_info(self.isa())?
461 } else {
462 None
463 };
464 let buffer = &compiled.buffer;
465 let relocs = buffer
466 .relocs()
467 .iter()
468 .map(|reloc| {
469 self.process_reloc(&ModuleReloc::from_mach_reloc(&reloc, &ctx.func, func_id))
470 })
471 .collect::<Vec<_>>();
472 self.define_function_inner(func_id, alignment, buffer.data(), relocs)?;
473 #[cfg(feature = "unwind")]
474 if let (Some(builder), Some(info)) = (self.unwind.as_mut(), unwind_info) {
475 let symbol = self.functions[func_id].unwrap().0;
476 builder.add_function(&*self.isa, symbol, info);
477 }
478 Ok(())
479 }
480
481 fn define_function_bytes(
482 &mut self,
483 func_id: FuncId,
484 alignment: u64,
485 bytes: &[u8],
486 relocs: &[ModuleReloc],
487 ) -> ModuleResult<()> {
488 let relocs = relocs
489 .iter()
490 .map(|reloc| self.process_reloc(reloc))
491 .collect();
492 self.define_function_inner(func_id, alignment, bytes, relocs)
493 }
494
495 fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
496 let decl = self.declarations.get_data_decl(data_id);
497 if !decl.linkage.is_definable() {
498 return Err(ModuleError::InvalidImportDefinition(
499 decl.linkage_name(data_id).into_owned(),
500 ));
501 }
502
503 let &mut (symbol, ref mut defined) = self.data_objects[data_id].as_mut().unwrap();
504 if *defined {
505 return Err(ModuleError::DuplicateDefinition(
506 decl.linkage_name(data_id).into_owned(),
507 ));
508 }
509 *defined = true;
510
511 let &DataDescription {
512 ref init,
513 function_decls: _,
514 data_decls: _,
515 function_relocs: _,
516 data_relocs: _,
517 ref custom_segment_section,
518 align,
519 used,
520 } = data;
521
522 let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
523 PointerWidth::U16 => unimplemented!("16bit pointers"),
524 PointerWidth::U32 => Reloc::Abs4,
525 PointerWidth::U64 => Reloc::Abs8,
526 };
527 let relocs = data
528 .all_relocs(pointer_reloc)
529 .map(|record| self.process_reloc(&record))
530 .collect::<Vec<_>>();
531
532 let section = if custom_segment_section.is_none() {
533 let section_kind = if let Init::Zeros { .. } = *init {
534 if decl.tls {
535 StandardSection::UninitializedTls
536 } else {
537 StandardSection::UninitializedData
538 }
539 } else if decl.tls {
540 StandardSection::Tls
541 } else if decl.writable {
542 StandardSection::Data
543 } else if relocs.is_empty() {
544 StandardSection::ReadOnlyData
545 } else {
546 StandardSection::ReadOnlyDataWithRel
547 };
548 if self.per_data_object_section || used {
549 self.object.add_subsection(section_kind, b"subsection")
554 } else {
555 self.object.section_id(section_kind)
556 }
557 } else {
558 if decl.tls {
559 return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!(
560 "Custom section not supported for TLS"
561 )));
562 }
563 let (seg, sec, macho_flags) = &custom_segment_section.as_ref().unwrap();
564 let section = self.object.add_section(
565 seg.clone().into_bytes(),
566 sec.clone().into_bytes(),
567 if decl.writable {
568 SectionKind::Data
569 } else if relocs.is_empty() {
570 SectionKind::ReadOnlyData
571 } else {
572 SectionKind::ReadOnlyDataWithRel
573 },
574 );
575
576 match self.object.section_flags_mut(section) {
577 SectionFlags::MachO { flags } => {
578 assert_eq!(*flags, 0);
585 *flags = *macho_flags;
586 }
587 _ => {
588 if *macho_flags != 0 {
589 return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!(
590 "unsupported Mach-O flags for this platform: {macho_flags:?}"
591 )));
592 }
593 }
594 }
595
596 section
597 };
598
599 if used {
600 match self.object.format() {
601 object::BinaryFormat::Elf => match self.object.section_flags_mut(section) {
602 SectionFlags::Elf { sh_flags } => *sh_flags |= u64::from(elf::SHF_GNU_RETAIN),
603 _ => unreachable!(),
604 },
605 object::BinaryFormat::Coff => {}
606 object::BinaryFormat::MachO => match self.object.symbol_flags_mut(symbol) {
607 SymbolFlags::MachO { n_desc } => *n_desc |= object::macho::N_NO_DEAD_STRIP,
608 _ => unreachable!(),
609 },
610 _ => unreachable!(),
611 }
612 }
613
614 let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
615 let offset = match *init {
616 Init::Uninitialized => {
617 panic!("data is not initialized yet");
618 }
619 Init::Zeros { size } => self
620 .object
621 .add_symbol_bss(symbol, section, size as u64, align),
622 Init::Bytes { ref contents } => self
623 .object
624 .add_symbol_data(symbol, section, &contents, align),
625 };
626 if !relocs.is_empty() {
627 self.relocs.push(SymbolRelocs {
628 section,
629 offset,
630 relocs,
631 });
632 }
633 Ok(())
634 }
635}
636
637impl ObjectModule {
638 fn define_function_inner(
639 &mut self,
640 func_id: FuncId,
641 alignment: u64,
642 bytes: &[u8],
643 relocs: Vec<ObjectRelocRecord>,
644 ) -> Result<(), ModuleError> {
645 info!("defining function {func_id} with bytes");
646 let decl = self.declarations.get_function_decl(func_id);
647 let decl_name = decl.linkage_name(func_id);
648 if !decl.linkage.is_definable() {
649 return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned()));
650 }
651
652 let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();
653 if *defined {
654 return Err(ModuleError::DuplicateDefinition(decl_name.into_owned()));
655 }
656 *defined = true;
657
658 let align = alignment.max(self.isa.symbol_alignment());
659 let section = if self.per_function_section {
660 self.object
664 .add_subsection(StandardSection::Text, b"subsection")
665 } else {
666 self.object.section_id(StandardSection::Text)
667 };
668 let offset = self.object.add_symbol_data(symbol, section, bytes, align);
669
670 if !relocs.is_empty() {
671 self.relocs.push(SymbolRelocs {
672 section,
673 offset,
674 relocs,
675 });
676 }
677
678 Ok(())
679 }
680
681 pub fn finish(mut self) -> ObjectProduct {
683 if cfg!(debug_assertions) {
684 for (func_id, decl) in self.declarations.get_functions() {
685 if !decl.linkage.requires_definition() {
686 continue;
687 }
688
689 assert!(
690 self.functions[func_id].unwrap().1,
691 "function \"{}\" with linkage {:?} must be defined but is not",
692 decl.linkage_name(func_id),
693 decl.linkage,
694 );
695 }
696
697 for (data_id, decl) in self.declarations.get_data_objects() {
698 if !decl.linkage.requires_definition() {
699 continue;
700 }
701
702 assert!(
703 self.data_objects[data_id].unwrap().1,
704 "data object \"{}\" with linkage {:?} must be defined but is not",
705 decl.linkage_name(data_id),
706 decl.linkage,
707 );
708 }
709 }
710
711 let symbol_relocs = mem::take(&mut self.relocs);
712 for symbol in symbol_relocs {
713 for &ObjectRelocRecord {
714 offset,
715 ref name,
716 flags,
717 addend,
718 } in &symbol.relocs
719 {
720 let target_symbol = self.get_symbol(name);
721 self.object
722 .add_relocation(
723 symbol.section,
724 Relocation {
725 offset: symbol.offset + u64::from(offset),
726 flags,
727 symbol: target_symbol,
728 addend,
729 },
730 )
731 .unwrap();
732 }
733 }
734
735 if self.object.format() == object::BinaryFormat::Elf {
737 self.object.add_section(
738 vec![],
739 ".note.GNU-stack".as_bytes().to_vec(),
740 SectionKind::Linker,
741 );
742 }
743
744 #[cfg(feature = "unwind")]
745 if let Some(unwind) = self.unwind.take() {
746 unwind
747 .finish(&mut self.object, &*self.isa)
748 .expect("failed to emit .eh_frame section");
749 }
750
751 ObjectProduct {
752 object: self.object,
753 functions: self.functions,
754 data_objects: self.data_objects,
755 }
756 }
757
758 fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId {
761 match *name {
762 ModuleRelocTarget::User { .. } => {
763 if ModuleDeclarations::is_function(name) {
764 let id = FuncId::from_name(name);
765 self.functions[id].unwrap().0
766 } else {
767 let id = DataId::from_name(name);
768 self.data_objects[id].unwrap().0
769 }
770 }
771 ModuleRelocTarget::LibCall(ref libcall) => {
772 let name = (self.libcall_names)(*libcall);
773 if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {
774 symbol
775 } else if let Some(symbol) = self.libcalls.get(libcall) {
776 *symbol
777 } else {
778 let symbol = self.object.add_symbol(Symbol {
779 name: name.as_bytes().to_vec(),
780 value: 0,
781 size: 0,
782 kind: SymbolKind::Text,
783 scope: SymbolScope::Unknown,
784 weak: false,
785 section: SymbolSection::Undefined,
786 flags: SymbolFlags::None,
787 });
788 self.libcalls.insert(*libcall, symbol);
789 symbol
790 }
791 }
792 ModuleRelocTarget::KnownSymbol(ref known_symbol) => {
795 if let Some(symbol) = self.known_symbols.get(known_symbol) {
796 *symbol
797 } else {
798 let symbol = self.object.add_symbol(match known_symbol {
799 ir::KnownSymbol::ElfGlobalOffsetTable => Symbol {
800 name: b"_GLOBAL_OFFSET_TABLE_".to_vec(),
801 value: 0,
802 size: 0,
803 kind: SymbolKind::Data,
804 scope: SymbolScope::Unknown,
805 weak: false,
806 section: SymbolSection::Undefined,
807 flags: SymbolFlags::None,
808 },
809 ir::KnownSymbol::CoffTlsIndex => Symbol {
810 name: b"_tls_index".to_vec(),
811 value: 0,
812 size: 32,
813 kind: SymbolKind::Tls,
814 scope: SymbolScope::Unknown,
815 weak: false,
816 section: SymbolSection::Undefined,
817 flags: SymbolFlags::None,
818 },
819 });
820 self.known_symbols.insert(*known_symbol, symbol);
821 symbol
822 }
823 }
824
825 ModuleRelocTarget::FunctionOffset(func_id, offset) => {
826 match self.known_labels.entry((func_id, offset)) {
827 Entry::Occupied(o) => *o.get(),
828 Entry::Vacant(v) => {
829 let func_symbol_id = self.functions[func_id].unwrap().0;
830 let func_symbol = self.object.symbol(func_symbol_id);
831
832 let name = format!(".L{}_{}", func_id.as_u32(), offset);
833 let symbol_id = self.object.add_symbol(Symbol {
834 name: name.as_bytes().to_vec(),
835 value: func_symbol.value + offset as u64,
836 size: 0,
837 kind: SymbolKind::Label,
838 scope: SymbolScope::Compilation,
839 weak: false,
840 section: SymbolSection::Section(func_symbol.section.id().unwrap()),
841 flags: SymbolFlags::None,
842 });
843
844 v.insert(symbol_id);
845 symbol_id
846 }
847 }
848 }
849 }
850 }
851
852 fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord {
853 let flags = match record.kind {
854 Reloc::Abs4 => RelocationFlags::Generic {
855 kind: RelocationKind::Absolute,
856 encoding: RelocationEncoding::Generic,
857 size: 32,
858 },
859 Reloc::Abs8 => RelocationFlags::Generic {
860 kind: RelocationKind::Absolute,
861 encoding: RelocationEncoding::Generic,
862 size: 64,
863 },
864 Reloc::X86PCRel4 => RelocationFlags::Generic {
865 kind: RelocationKind::Relative,
866 encoding: RelocationEncoding::Generic,
867 size: 32,
868 },
869 Reloc::X86CallPCRel4 => RelocationFlags::Generic {
870 kind: RelocationKind::Relative,
871 encoding: RelocationEncoding::X86Branch,
872 size: 32,
873 },
874 Reloc::X86CallPLTRel4 => RelocationFlags::Generic {
877 kind: RelocationKind::PltRelative,
878 encoding: RelocationEncoding::X86Branch,
879 size: 32,
880 },
881 Reloc::X86SecRel => RelocationFlags::Generic {
882 kind: RelocationKind::SectionOffset,
883 encoding: RelocationEncoding::Generic,
884 size: 32,
885 },
886 Reloc::X86GOTPCRel4 => RelocationFlags::Generic {
887 kind: RelocationKind::GotRelative,
888 encoding: RelocationEncoding::Generic,
889 size: 32,
890 },
891 Reloc::Arm64Call => RelocationFlags::Generic {
892 kind: RelocationKind::Relative,
893 encoding: RelocationEncoding::AArch64Call,
894 size: 26,
895 },
896 Reloc::ElfX86_64TlsGd => {
897 assert_eq!(
898 self.object.format(),
899 object::BinaryFormat::Elf,
900 "ElfX86_64TlsGd is not supported for this file format"
901 );
902 RelocationFlags::Elf {
903 r_type: object::elf::R_X86_64_TLSGD,
904 }
905 }
906 Reloc::MachOX86_64Tlv => {
907 assert_eq!(
908 self.object.format(),
909 object::BinaryFormat::MachO,
910 "MachOX86_64Tlv is not supported for this file format"
911 );
912 RelocationFlags::MachO {
913 r_type: object::macho::X86_64_RELOC_TLV,
914 r_pcrel: true,
915 r_length: 2,
916 }
917 }
918 Reloc::MachOAarch64TlsAdrPage21 => {
919 assert_eq!(
920 self.object.format(),
921 object::BinaryFormat::MachO,
922 "MachOAarch64TlsAdrPage21 is not supported for this file format"
923 );
924 RelocationFlags::MachO {
925 r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
926 r_pcrel: true,
927 r_length: 2,
928 }
929 }
930 Reloc::MachOAarch64TlsAdrPageOff12 => {
931 assert_eq!(
932 self.object.format(),
933 object::BinaryFormat::MachO,
934 "MachOAarch64TlsAdrPageOff12 is not supported for this file format"
935 );
936 RelocationFlags::MachO {
937 r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
938 r_pcrel: false,
939 r_length: 2,
940 }
941 }
942 Reloc::Aarch64TlsDescAdrPage21 => {
943 assert_eq!(
944 self.object.format(),
945 object::BinaryFormat::Elf,
946 "Aarch64TlsDescAdrPage21 is not supported for this file format"
947 );
948 RelocationFlags::Elf {
949 r_type: object::elf::R_AARCH64_TLSDESC_ADR_PAGE21,
950 }
951 }
952 Reloc::Aarch64TlsDescLd64Lo12 => {
953 assert_eq!(
954 self.object.format(),
955 object::BinaryFormat::Elf,
956 "Aarch64TlsDescLd64Lo12 is not supported for this file format"
957 );
958 RelocationFlags::Elf {
959 r_type: object::elf::R_AARCH64_TLSDESC_LD64_LO12,
960 }
961 }
962 Reloc::Aarch64TlsDescAddLo12 => {
963 assert_eq!(
964 self.object.format(),
965 object::BinaryFormat::Elf,
966 "Aarch64TlsDescAddLo12 is not supported for this file format"
967 );
968 RelocationFlags::Elf {
969 r_type: object::elf::R_AARCH64_TLSDESC_ADD_LO12,
970 }
971 }
972 Reloc::Aarch64TlsDescCall => {
973 assert_eq!(
974 self.object.format(),
975 object::BinaryFormat::Elf,
976 "Aarch64TlsDescCall is not supported for this file format"
977 );
978 RelocationFlags::Elf {
979 r_type: object::elf::R_AARCH64_TLSDESC_CALL,
980 }
981 }
982
983 Reloc::Aarch64AdrGotPage21 => match self.object.format() {
984 object::BinaryFormat::Elf => RelocationFlags::Elf {
985 r_type: object::elf::R_AARCH64_ADR_GOT_PAGE,
986 },
987 object::BinaryFormat::MachO => RelocationFlags::MachO {
988 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
989 r_pcrel: true,
990 r_length: 2,
991 },
992 _ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"),
993 },
994 Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() {
995 object::BinaryFormat::Elf => RelocationFlags::Elf {
996 r_type: object::elf::R_AARCH64_LD64_GOT_LO12_NC,
997 },
998 object::BinaryFormat::MachO => RelocationFlags::MachO {
999 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
1000 r_pcrel: false,
1001 r_length: 2,
1002 },
1003 _ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"),
1004 },
1005 Reloc::Aarch64AdrPrelPgHi21 => match self.object.format() {
1006 object::BinaryFormat::Elf => RelocationFlags::Elf {
1007 r_type: object::elf::R_AARCH64_ADR_PREL_PG_HI21,
1008 },
1009 object::BinaryFormat::MachO => RelocationFlags::MachO {
1010 r_type: object::macho::ARM64_RELOC_PAGE21,
1011 r_pcrel: true,
1012 r_length: 2,
1013 },
1014 _ => unimplemented!("Aarch64AdrPrelPgHi21 is not supported for this file format"),
1015 },
1016 Reloc::Aarch64AddAbsLo12Nc => match self.object.format() {
1017 object::BinaryFormat::Elf => RelocationFlags::Elf {
1018 r_type: object::elf::R_AARCH64_ADD_ABS_LO12_NC,
1019 },
1020 object::BinaryFormat::MachO => RelocationFlags::MachO {
1021 r_type: object::macho::ARM64_RELOC_PAGEOFF12,
1022 r_pcrel: false,
1023 r_length: 2,
1024 },
1025 _ => unimplemented!("Aarch64AddAbsLo12Nc is not supported for this file format"),
1026 },
1027 Reloc::S390xPCRel32Dbl => RelocationFlags::Generic {
1028 kind: RelocationKind::Relative,
1029 encoding: RelocationEncoding::S390xDbl,
1030 size: 32,
1031 },
1032 Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic {
1033 kind: RelocationKind::PltRelative,
1034 encoding: RelocationEncoding::S390xDbl,
1035 size: 32,
1036 },
1037 Reloc::S390xTlsGd64 => {
1038 assert_eq!(
1039 self.object.format(),
1040 object::BinaryFormat::Elf,
1041 "S390xTlsGd64 is not supported for this file format"
1042 );
1043 RelocationFlags::Elf {
1044 r_type: object::elf::R_390_TLS_GD64,
1045 }
1046 }
1047 Reloc::S390xTlsGdCall => {
1048 assert_eq!(
1049 self.object.format(),
1050 object::BinaryFormat::Elf,
1051 "S390xTlsGdCall is not supported for this file format"
1052 );
1053 RelocationFlags::Elf {
1054 r_type: object::elf::R_390_TLS_GDCALL,
1055 }
1056 }
1057 Reloc::RiscvCallPlt => {
1058 assert_eq!(
1059 self.object.format(),
1060 object::BinaryFormat::Elf,
1061 "RiscvCallPlt is not supported for this file format"
1062 );
1063 RelocationFlags::Elf {
1064 r_type: object::elf::R_RISCV_CALL_PLT,
1065 }
1066 }
1067 Reloc::RiscvTlsGdHi20 => {
1068 assert_eq!(
1069 self.object.format(),
1070 object::BinaryFormat::Elf,
1071 "RiscvTlsGdHi20 is not supported for this file format"
1072 );
1073 RelocationFlags::Elf {
1074 r_type: object::elf::R_RISCV_TLS_GD_HI20,
1075 }
1076 }
1077 Reloc::RiscvPCRelLo12I => {
1078 assert_eq!(
1079 self.object.format(),
1080 object::BinaryFormat::Elf,
1081 "RiscvPCRelLo12I is not supported for this file format"
1082 );
1083 RelocationFlags::Elf {
1084 r_type: object::elf::R_RISCV_PCREL_LO12_I,
1085 }
1086 }
1087 Reloc::RiscvGotHi20 => {
1088 assert_eq!(
1089 self.object.format(),
1090 object::BinaryFormat::Elf,
1091 "RiscvGotHi20 is not supported for this file format"
1092 );
1093 RelocationFlags::Elf {
1094 r_type: object::elf::R_RISCV_GOT_HI20,
1095 }
1096 }
1097 Reloc::RiscvPCRelHi20 => {
1098 assert_eq!(
1099 self.object.format(),
1100 object::BinaryFormat::Elf,
1101 "RiscvPCRelHi20 is not supported for this file format"
1102 );
1103 RelocationFlags::Elf {
1104 r_type: object::elf::R_RISCV_PCREL_HI20,
1105 }
1106 }
1107 reloc => unimplemented!("{:?}", reloc),
1109 };
1110
1111 ObjectRelocRecord {
1112 offset: record.offset,
1113 name: record.name.clone(),
1114 flags,
1115 addend: record.addend,
1116 }
1117 }
1118}
1119
1120fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
1121 let scope = match linkage {
1122 Linkage::Import => SymbolScope::Unknown,
1123 Linkage::Local => SymbolScope::Compilation,
1124 Linkage::Hidden => SymbolScope::Linkage,
1125 Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,
1126 };
1127 let weak = linkage == Linkage::Preemptible;
1129 (scope, weak)
1130}
1131
1132pub struct ObjectProduct {
1137 pub object: Object<'static>,
1139 pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
1141 pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
1143}
1144
1145impl ObjectProduct {
1146 #[inline]
1148 pub fn function_symbol(&self, id: FuncId) -> SymbolId {
1149 self.functions[id].unwrap().0
1150 }
1151
1152 #[inline]
1154 pub fn data_symbol(&self, id: DataId) -> SymbolId {
1155 self.data_objects[id].unwrap().0
1156 }
1157
1158 #[inline]
1160 pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {
1161 self.object.write()
1162 }
1163}
1164
1165#[derive(Clone)]
1166struct SymbolRelocs {
1167 section: SectionId,
1168 offset: u64,
1169 relocs: Vec<ObjectRelocRecord>,
1170}
1171
1172#[derive(Clone)]
1173struct ObjectRelocRecord {
1174 offset: CodeOffset,
1175 name: ModuleRelocTarget,
1176 flags: RelocationFlags,
1177 addend: Addend,
1178}