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