1 //! Defines `ObjectModule`.
2 
3 use anyhow::anyhow;
4 use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
5 use cranelift_codegen::entity::SecondaryMap;
6 use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
7 use cranelift_codegen::{self, ir, FinalizedMachReloc};
8 use cranelift_control::ControlPlane;
9 use cranelift_module::{
10     DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleDeclarations, ModuleError,
11     ModuleReloc, ModuleRelocTarget, ModuleResult,
12 };
13 use log::info;
14 use object::write::{
15     Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
16 };
17 use object::{
18     RelocationEncoding, RelocationKind, SectionKind, SymbolFlags, SymbolKind, SymbolScope,
19 };
20 use std::collections::hash_map::Entry;
21 use std::collections::HashMap;
22 use std::mem;
23 use target_lexicon::PointerWidth;
24 
25 /// A builder for `ObjectModule`.
26 pub struct ObjectBuilder {
27     isa: OwnedTargetIsa,
28     binary_format: object::BinaryFormat,
29     architecture: object::Architecture,
30     flags: object::FileFlags,
31     endian: object::Endianness,
32     name: Vec<u8>,
33     libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
34     per_function_section: bool,
35 }
36 
37 impl ObjectBuilder {
38     /// Create a new `ObjectBuilder` using the given Cranelift target, that
39     /// can be passed to [`ObjectModule::new`].
40     ///
41     /// The `libcall_names` function provides a way to translate `cranelift_codegen`'s [ir::LibCall]
42     /// enum to symbols. LibCalls are inserted in the IR as part of the legalization for certain
43     /// floating point instructions, and for stack probes. If you don't know what to use for this
44     /// argument, use [cranelift_module::default_libcall_names]().
45     pub fn new<V: Into<Vec<u8>>>(
46         isa: OwnedTargetIsa,
47         name: V,
48         libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
49     ) -> ModuleResult<Self> {
50         let mut file_flags = object::FileFlags::None;
51         let binary_format = match isa.triple().binary_format {
52             target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
53             target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
54             target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
55             target_lexicon::BinaryFormat::Wasm => {
56                 return Err(ModuleError::Backend(anyhow!(
57                     "binary format wasm is unsupported",
58                 )))
59             }
60             target_lexicon::BinaryFormat::Unknown => {
61                 return Err(ModuleError::Backend(anyhow!("binary format is unknown")))
62             }
63             other => {
64                 return Err(ModuleError::Backend(anyhow!(
65                     "binary format {} not recognized",
66                     other
67                 )))
68             }
69         };
70         let architecture = match isa.triple().architecture {
71             target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
72             target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
73             target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
74             target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
75             target_lexicon::Architecture::Riscv64(_) => {
76                 if binary_format != object::BinaryFormat::Elf {
77                     return Err(ModuleError::Backend(anyhow!(
78                         "binary format {:?} is not supported for riscv64",
79                         binary_format,
80                     )));
81                 }
82 
83                 // FIXME(#4994): Get the right float ABI variant from the TargetIsa
84                 let mut eflags = object::elf::EF_RISCV_FLOAT_ABI_DOUBLE;
85 
86                 // Set the RVC eflag if we have the C extension enabled.
87                 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 {:?} is unsupported",
107                     architecture,
108                 )))
109             }
110         };
111         let endian = match isa.triple().endianness().unwrap() {
112             target_lexicon::Endianness::Little => object::Endianness::Little,
113             target_lexicon::Endianness::Big => object::Endianness::Big,
114         };
115         Ok(Self {
116             isa,
117             binary_format,
118             architecture,
119             flags: file_flags,
120             endian,
121             name: name.into(),
122             libcall_names,
123             per_function_section: false,
124         })
125     }
126 
127     /// Set if every function should end up in their own section.
128     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 
134 /// An `ObjectModule` implements `Module` and emits ".o" files using the `object` library.
135 ///
136 /// See the `ObjectBuilder` for a convenient way to construct `ObjectModule` instances.
137 pub struct ObjectModule {
138     isa: OwnedTargetIsa,
139     object: Object<'static>,
140     declarations: ModuleDeclarations,
141     functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
142     data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
143     relocs: Vec<SymbolRelocs>,
144     libcalls: HashMap<ir::LibCall, SymbolId>,
145     libcall_names: Box<dyn Fn(ir::LibCall) -> String + Send + Sync>,
146     known_symbols: HashMap<ir::KnownSymbol, SymbolId>,
147     known_labels: HashMap<(FuncId, CodeOffset), SymbolId>,
148     per_function_section: bool,
149 }
150 
151 impl ObjectModule {
152     /// Create a new `ObjectModule` using the given Cranelift target.
153     pub fn new(builder: ObjectBuilder) -> Self {
154         let mut object = Object::new(builder.binary_format, builder.architecture, builder.endian);
155         object.flags = builder.flags;
156         object.add_file_symbol(builder.name);
157         Self {
158             isa: builder.isa,
159             object,
160             declarations: ModuleDeclarations::default(),
161             functions: SecondaryMap::new(),
162             data_objects: SecondaryMap::new(),
163             relocs: Vec::new(),
164             libcalls: HashMap::new(),
165             libcall_names: builder.libcall_names,
166             known_symbols: HashMap::new(),
167             known_labels: HashMap::new(),
168             per_function_section: builder.per_function_section,
169         }
170     }
171 }
172 
173 fn validate_symbol(name: &str) -> ModuleResult<()> {
174     // null bytes are not allowed in symbol names and will cause the `object`
175     // crate to panic. Let's return a clean error instead.
176     if name.contains("\0") {
177         return Err(ModuleError::Backend(anyhow::anyhow!(
178             "Symbol {:?} has a null byte, which is disallowed",
179             name
180         )));
181     }
182     Ok(())
183 }
184 
185 impl Module for ObjectModule {
186     fn isa(&self) -> &dyn TargetIsa {
187         &*self.isa
188     }
189 
190     fn declarations(&self) -> &ModuleDeclarations {
191         &self.declarations
192     }
193 
194     fn declare_function(
195         &mut self,
196         name: &str,
197         linkage: Linkage,
198         signature: &ir::Signature,
199     ) -> ModuleResult<FuncId> {
200         validate_symbol(name)?;
201 
202         let (id, linkage) = self
203             .declarations
204             .declare_function(name, linkage, signature)?;
205 
206         let (scope, weak) = translate_linkage(linkage);
207 
208         if let Some((function, _defined)) = self.functions[id] {
209             let symbol = self.object.symbol_mut(function);
210             symbol.scope = scope;
211             symbol.weak = weak;
212         } else {
213             let symbol_id = self.object.add_symbol(Symbol {
214                 name: name.as_bytes().to_vec(),
215                 value: 0,
216                 size: 0,
217                 kind: SymbolKind::Text,
218                 scope,
219                 weak,
220                 section: SymbolSection::Undefined,
221                 flags: SymbolFlags::None,
222             });
223             self.functions[id] = Some((symbol_id, false));
224         }
225 
226         Ok(id)
227     }
228 
229     fn declare_anonymous_function(&mut self, signature: &ir::Signature) -> ModuleResult<FuncId> {
230         let id = self.declarations.declare_anonymous_function(signature)?;
231 
232         let symbol_id = self.object.add_symbol(Symbol {
233             name: self
234                 .declarations
235                 .get_function_decl(id)
236                 .linkage_name(id)
237                 .into_owned()
238                 .into_bytes(),
239             value: 0,
240             size: 0,
241             kind: SymbolKind::Text,
242             scope: SymbolScope::Compilation,
243             weak: false,
244             section: SymbolSection::Undefined,
245             flags: SymbolFlags::None,
246         });
247         self.functions[id] = Some((symbol_id, false));
248 
249         Ok(id)
250     }
251 
252     fn declare_data(
253         &mut self,
254         name: &str,
255         linkage: Linkage,
256         writable: bool,
257         tls: bool,
258     ) -> ModuleResult<DataId> {
259         validate_symbol(name)?;
260 
261         let (id, linkage) = self
262             .declarations
263             .declare_data(name, linkage, writable, tls)?;
264 
265         // Merging declarations with conflicting values for tls is not allowed, so it is safe to use
266         // the passed in tls value here.
267         let kind = if tls {
268             SymbolKind::Tls
269         } else {
270             SymbolKind::Data
271         };
272         let (scope, weak) = translate_linkage(linkage);
273 
274         if let Some((data, _defined)) = self.data_objects[id] {
275             let symbol = self.object.symbol_mut(data);
276             symbol.kind = kind;
277             symbol.scope = scope;
278             symbol.weak = weak;
279         } else {
280             let symbol_id = self.object.add_symbol(Symbol {
281                 name: name.as_bytes().to_vec(),
282                 value: 0,
283                 size: 0,
284                 kind,
285                 scope,
286                 weak,
287                 section: SymbolSection::Undefined,
288                 flags: SymbolFlags::None,
289             });
290             self.data_objects[id] = Some((symbol_id, false));
291         }
292 
293         Ok(id)
294     }
295 
296     fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> {
297         let id = self.declarations.declare_anonymous_data(writable, tls)?;
298 
299         let kind = if tls {
300             SymbolKind::Tls
301         } else {
302             SymbolKind::Data
303         };
304 
305         let symbol_id = self.object.add_symbol(Symbol {
306             name: self
307                 .declarations
308                 .get_data_decl(id)
309                 .linkage_name(id)
310                 .into_owned()
311                 .into_bytes(),
312             value: 0,
313             size: 0,
314             kind,
315             scope: SymbolScope::Compilation,
316             weak: false,
317             section: SymbolSection::Undefined,
318             flags: SymbolFlags::None,
319         });
320         self.data_objects[id] = Some((symbol_id, false));
321 
322         Ok(id)
323     }
324 
325     fn define_function_with_control_plane(
326         &mut self,
327         func_id: FuncId,
328         ctx: &mut cranelift_codegen::Context,
329         ctrl_plane: &mut ControlPlane,
330     ) -> ModuleResult<()> {
331         info!("defining function {}: {}", func_id, ctx.func.display());
332         let mut code: Vec<u8> = Vec::new();
333 
334         let res = ctx.compile_and_emit(self.isa(), &mut code, ctrl_plane)?;
335         let alignment = res.buffer.alignment as u64;
336 
337         self.define_function_bytes(
338             func_id,
339             &ctx.func,
340             alignment,
341             &code,
342             ctx.compiled_code().unwrap().buffer.relocs(),
343         )
344     }
345 
346     fn define_function_bytes(
347         &mut self,
348         func_id: FuncId,
349         func: &ir::Function,
350         alignment: u64,
351         bytes: &[u8],
352         relocs: &[FinalizedMachReloc],
353     ) -> ModuleResult<()> {
354         info!("defining function {} with bytes", func_id);
355         let decl = self.declarations.get_function_decl(func_id);
356         let decl_name = decl.linkage_name(func_id);
357         if !decl.linkage.is_definable() {
358             return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned()));
359         }
360 
361         let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();
362         if *defined {
363             return Err(ModuleError::DuplicateDefinition(decl_name.into_owned()));
364         }
365         *defined = true;
366 
367         let align = alignment
368             .max(self.isa.function_alignment().minimum.into())
369             .max(self.isa.symbol_alignment());
370         let (section, offset) = if self.per_function_section {
371             let symbol_name = self.object.symbol(symbol).name.clone();
372             let (section, offset) =
373                 self.object
374                     .add_subsection(StandardSection::Text, &symbol_name, bytes, align);
375             self.object.symbol_mut(symbol).section = SymbolSection::Section(section);
376             self.object.symbol_mut(symbol).value = offset;
377             (section, offset)
378         } else {
379             let section = self.object.section_id(StandardSection::Text);
380             let offset = self.object.add_symbol_data(symbol, section, bytes, align);
381             (section, offset)
382         };
383 
384         if !relocs.is_empty() {
385             let relocs = relocs
386                 .iter()
387                 .map(|record| {
388                     self.process_reloc(&ModuleReloc::from_mach_reloc(&record, func, func_id))
389                 })
390                 .collect();
391             self.relocs.push(SymbolRelocs {
392                 section,
393                 offset,
394                 relocs,
395             });
396         }
397 
398         Ok(())
399     }
400 
401     fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> {
402         let decl = self.declarations.get_data_decl(data_id);
403         if !decl.linkage.is_definable() {
404             return Err(ModuleError::InvalidImportDefinition(
405                 decl.linkage_name(data_id).into_owned(),
406             ));
407         }
408 
409         let &mut (symbol, ref mut defined) = self.data_objects[data_id].as_mut().unwrap();
410         if *defined {
411             return Err(ModuleError::DuplicateDefinition(
412                 decl.linkage_name(data_id).into_owned(),
413             ));
414         }
415         *defined = true;
416 
417         let &DataDescription {
418             ref init,
419             function_decls: _,
420             data_decls: _,
421             function_relocs: _,
422             data_relocs: _,
423             ref custom_segment_section,
424             align,
425         } = data;
426 
427         let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
428             PointerWidth::U16 => unimplemented!("16bit pointers"),
429             PointerWidth::U32 => Reloc::Abs4,
430             PointerWidth::U64 => Reloc::Abs8,
431         };
432         let relocs = data
433             .all_relocs(pointer_reloc)
434             .map(|record| self.process_reloc(&record))
435             .collect::<Vec<_>>();
436 
437         let section = if custom_segment_section.is_none() {
438             let section_kind = if let Init::Zeros { .. } = *init {
439                 if decl.tls {
440                     StandardSection::UninitializedTls
441                 } else {
442                     StandardSection::UninitializedData
443                 }
444             } else if decl.tls {
445                 StandardSection::Tls
446             } else if decl.writable {
447                 StandardSection::Data
448             } else if relocs.is_empty() {
449                 StandardSection::ReadOnlyData
450             } else {
451                 StandardSection::ReadOnlyDataWithRel
452             };
453             self.object.section_id(section_kind)
454         } else {
455             if decl.tls {
456                 return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!(
457                     "Custom section not supported for TLS"
458                 )));
459             }
460             let (seg, sec) = &custom_segment_section.as_ref().unwrap();
461             self.object.add_section(
462                 seg.clone().into_bytes(),
463                 sec.clone().into_bytes(),
464                 if decl.writable {
465                     SectionKind::Data
466                 } else if relocs.is_empty() {
467                     SectionKind::ReadOnlyData
468                 } else {
469                     SectionKind::ReadOnlyDataWithRel
470                 },
471             )
472         };
473 
474         let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
475         let offset = match *init {
476             Init::Uninitialized => {
477                 panic!("data is not initialized yet");
478             }
479             Init::Zeros { size } => self
480                 .object
481                 .add_symbol_bss(symbol, section, size as u64, align),
482             Init::Bytes { ref contents } => self
483                 .object
484                 .add_symbol_data(symbol, section, &contents, align),
485         };
486         if !relocs.is_empty() {
487             self.relocs.push(SymbolRelocs {
488                 section,
489                 offset,
490                 relocs,
491             });
492         }
493         Ok(())
494     }
495 }
496 
497 impl ObjectModule {
498     /// Finalize all relocations and output an object.
499     pub fn finish(mut self) -> ObjectProduct {
500         let symbol_relocs = mem::take(&mut self.relocs);
501         for symbol in symbol_relocs {
502             for &ObjectRelocRecord {
503                 offset,
504                 ref name,
505                 kind,
506                 encoding,
507                 size,
508                 addend,
509             } in &symbol.relocs
510             {
511                 let target_symbol = self.get_symbol(name);
512                 self.object
513                     .add_relocation(
514                         symbol.section,
515                         Relocation {
516                             offset: symbol.offset + u64::from(offset),
517                             size,
518                             kind,
519                             encoding,
520                             symbol: target_symbol,
521                             addend,
522                         },
523                     )
524                     .unwrap();
525             }
526         }
527 
528         // Indicate that this object has a non-executable stack.
529         if self.object.format() == object::BinaryFormat::Elf {
530             self.object.add_section(
531                 vec![],
532                 ".note.GNU-stack".as_bytes().to_vec(),
533                 SectionKind::Linker,
534             );
535         }
536 
537         ObjectProduct {
538             object: self.object,
539             functions: self.functions,
540             data_objects: self.data_objects,
541         }
542     }
543 
544     /// This should only be called during finish because it creates
545     /// symbols for missing libcalls.
546     fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId {
547         match *name {
548             ModuleRelocTarget::User { .. } => {
549                 if ModuleDeclarations::is_function(name) {
550                     let id = FuncId::from_name(name);
551                     self.functions[id].unwrap().0
552                 } else {
553                     let id = DataId::from_name(name);
554                     self.data_objects[id].unwrap().0
555                 }
556             }
557             ModuleRelocTarget::LibCall(ref libcall) => {
558                 let name = (self.libcall_names)(*libcall);
559                 if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {
560                     symbol
561                 } else if let Some(symbol) = self.libcalls.get(libcall) {
562                     *symbol
563                 } else {
564                     let symbol = self.object.add_symbol(Symbol {
565                         name: name.as_bytes().to_vec(),
566                         value: 0,
567                         size: 0,
568                         kind: SymbolKind::Text,
569                         scope: SymbolScope::Unknown,
570                         weak: false,
571                         section: SymbolSection::Undefined,
572                         flags: SymbolFlags::None,
573                     });
574                     self.libcalls.insert(*libcall, symbol);
575                     symbol
576                 }
577             }
578             // These are "magic" names well-known to the linker.
579             // They require special treatment.
580             ModuleRelocTarget::KnownSymbol(ref known_symbol) => {
581                 if let Some(symbol) = self.known_symbols.get(known_symbol) {
582                     *symbol
583                 } else {
584                     let symbol = self.object.add_symbol(match known_symbol {
585                         ir::KnownSymbol::ElfGlobalOffsetTable => Symbol {
586                             name: b"_GLOBAL_OFFSET_TABLE_".to_vec(),
587                             value: 0,
588                             size: 0,
589                             kind: SymbolKind::Data,
590                             scope: SymbolScope::Unknown,
591                             weak: false,
592                             section: SymbolSection::Undefined,
593                             flags: SymbolFlags::None,
594                         },
595                         ir::KnownSymbol::CoffTlsIndex => Symbol {
596                             name: b"_tls_index".to_vec(),
597                             value: 0,
598                             size: 32,
599                             kind: SymbolKind::Tls,
600                             scope: SymbolScope::Unknown,
601                             weak: false,
602                             section: SymbolSection::Undefined,
603                             flags: SymbolFlags::None,
604                         },
605                     });
606                     self.known_symbols.insert(*known_symbol, symbol);
607                     symbol
608                 }
609             }
610 
611             ModuleRelocTarget::FunctionOffset(func_id, offset) => {
612                 match self.known_labels.entry((func_id, offset)) {
613                     Entry::Occupied(o) => *o.get(),
614                     Entry::Vacant(v) => {
615                         let func_symbol_id = self.functions[func_id].unwrap().0;
616                         let func_symbol = self.object.symbol(func_symbol_id);
617 
618                         let name = format!(".L{}_{}", func_id.as_u32(), offset);
619                         let symbol_id = self.object.add_symbol(Symbol {
620                             name: name.as_bytes().to_vec(),
621                             value: func_symbol.value + offset as u64,
622                             size: 0,
623                             kind: SymbolKind::Label,
624                             scope: SymbolScope::Compilation,
625                             weak: false,
626                             section: SymbolSection::Section(func_symbol.section.id().unwrap()),
627                             flags: SymbolFlags::None,
628                         });
629 
630                         v.insert(symbol_id);
631                         symbol_id
632                     }
633                 }
634             }
635         }
636     }
637 
638     fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord {
639         let mut addend = record.addend;
640         let (kind, encoding, size) = match record.kind {
641             Reloc::Abs4 => (RelocationKind::Absolute, RelocationEncoding::Generic, 32),
642             Reloc::Abs8 => (RelocationKind::Absolute, RelocationEncoding::Generic, 64),
643             Reloc::X86PCRel4 => (RelocationKind::Relative, RelocationEncoding::Generic, 32),
644             Reloc::X86CallPCRel4 => (RelocationKind::Relative, RelocationEncoding::X86Branch, 32),
645             // TODO: Get Cranelift to tell us when we can use
646             // R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.
647             Reloc::X86CallPLTRel4 => (
648                 RelocationKind::PltRelative,
649                 RelocationEncoding::X86Branch,
650                 32,
651             ),
652             Reloc::X86SecRel => (
653                 RelocationKind::SectionOffset,
654                 RelocationEncoding::Generic,
655                 32,
656             ),
657             Reloc::X86GOTPCRel4 => (RelocationKind::GotRelative, RelocationEncoding::Generic, 32),
658             Reloc::Arm64Call => (
659                 RelocationKind::Relative,
660                 RelocationEncoding::AArch64Call,
661                 26,
662             ),
663             Reloc::ElfX86_64TlsGd => {
664                 assert_eq!(
665                     self.object.format(),
666                     object::BinaryFormat::Elf,
667                     "ElfX86_64TlsGd is not supported for this file format"
668                 );
669                 (
670                     RelocationKind::Elf(object::elf::R_X86_64_TLSGD),
671                     RelocationEncoding::Generic,
672                     32,
673                 )
674             }
675             Reloc::MachOX86_64Tlv => {
676                 assert_eq!(
677                     self.object.format(),
678                     object::BinaryFormat::MachO,
679                     "MachOX86_64Tlv is not supported for this file format"
680                 );
681                 addend += 4; // X86_64_RELOC_TLV has an implicit addend of -4
682                 (
683                     RelocationKind::MachO {
684                         value: object::macho::X86_64_RELOC_TLV,
685                         relative: true,
686                     },
687                     RelocationEncoding::Generic,
688                     32,
689                 )
690             }
691             Reloc::MachOAarch64TlsAdrPage21 => {
692                 assert_eq!(
693                     self.object.format(),
694                     object::BinaryFormat::MachO,
695                     "MachOAarch64TlsAdrPage21 is not supported for this file format"
696                 );
697                 (
698                     RelocationKind::MachO {
699                         value: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
700                         relative: true,
701                     },
702                     RelocationEncoding::Generic,
703                     21,
704                 )
705             }
706             Reloc::MachOAarch64TlsAdrPageOff12 => {
707                 assert_eq!(
708                     self.object.format(),
709                     object::BinaryFormat::MachO,
710                     "MachOAarch64TlsAdrPageOff12 is not supported for this file format"
711                 );
712                 (
713                     RelocationKind::MachO {
714                         value: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
715                         relative: false,
716                     },
717                     RelocationEncoding::Generic,
718                     12,
719                 )
720             }
721             Reloc::Aarch64TlsDescAdrPage21 => {
722                 assert_eq!(
723                     self.object.format(),
724                     object::BinaryFormat::Elf,
725                     "Aarch64TlsDescAdrPage21 is not supported for this file format"
726                 );
727                 (
728                     RelocationKind::Elf(object::elf::R_AARCH64_TLSDESC_ADR_PAGE21),
729                     RelocationEncoding::Generic,
730                     21,
731                 )
732             }
733             Reloc::Aarch64TlsDescLd64Lo12 => {
734                 assert_eq!(
735                     self.object.format(),
736                     object::BinaryFormat::Elf,
737                     "Aarch64TlsDescLd64Lo12 is not supported for this file format"
738                 );
739                 (
740                     RelocationKind::Elf(object::elf::R_AARCH64_TLSDESC_LD64_LO12),
741                     RelocationEncoding::Generic,
742                     12,
743                 )
744             }
745             Reloc::Aarch64TlsDescAddLo12 => {
746                 assert_eq!(
747                     self.object.format(),
748                     object::BinaryFormat::Elf,
749                     "Aarch64TlsDescAddLo12 is not supported for this file format"
750                 );
751                 (
752                     RelocationKind::Elf(object::elf::R_AARCH64_TLSDESC_ADD_LO12),
753                     RelocationEncoding::Generic,
754                     12,
755                 )
756             }
757             Reloc::Aarch64TlsDescCall => {
758                 assert_eq!(
759                     self.object.format(),
760                     object::BinaryFormat::Elf,
761                     "Aarch64TlsDescCall is not supported for this file format"
762                 );
763                 (
764                     RelocationKind::Elf(object::elf::R_AARCH64_TLSDESC_CALL),
765                     RelocationEncoding::Generic,
766                     0,
767                 )
768             }
769 
770             Reloc::Aarch64AdrGotPage21 => match self.object.format() {
771                 object::BinaryFormat::Elf => (
772                     RelocationKind::Elf(object::elf::R_AARCH64_ADR_GOT_PAGE),
773                     RelocationEncoding::Generic,
774                     21,
775                 ),
776                 object::BinaryFormat::MachO => (
777                     RelocationKind::MachO {
778                         value: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
779                         relative: true,
780                     },
781                     RelocationEncoding::Generic,
782                     21,
783                 ),
784                 _ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"),
785             },
786             Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() {
787                 object::BinaryFormat::Elf => (
788                     RelocationKind::Elf(object::elf::R_AARCH64_LD64_GOT_LO12_NC),
789                     RelocationEncoding::Generic,
790                     12,
791                 ),
792                 object::BinaryFormat::MachO => (
793                     RelocationKind::MachO {
794                         value: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
795                         relative: false,
796                     },
797                     RelocationEncoding::Generic,
798                     12,
799                 ),
800                 _ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"),
801             },
802             Reloc::S390xPCRel32Dbl => (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32),
803             Reloc::S390xPLTRel32Dbl => (
804                 RelocationKind::PltRelative,
805                 RelocationEncoding::S390xDbl,
806                 32,
807             ),
808             Reloc::S390xTlsGd64 => {
809                 assert_eq!(
810                     self.object.format(),
811                     object::BinaryFormat::Elf,
812                     "S390xTlsGd64 is not supported for this file format"
813                 );
814                 (
815                     RelocationKind::Elf(object::elf::R_390_TLS_GD64),
816                     RelocationEncoding::Generic,
817                     64,
818                 )
819             }
820             Reloc::S390xTlsGdCall => {
821                 assert_eq!(
822                     self.object.format(),
823                     object::BinaryFormat::Elf,
824                     "S390xTlsGdCall is not supported for this file format"
825                 );
826                 (
827                     RelocationKind::Elf(object::elf::R_390_TLS_GDCALL),
828                     RelocationEncoding::Generic,
829                     0,
830                 )
831             }
832             Reloc::RiscvCallPlt => {
833                 assert_eq!(
834                     self.object.format(),
835                     object::BinaryFormat::Elf,
836                     "RiscvCallPlt is not supported for this file format"
837                 );
838                 (
839                     RelocationKind::Elf(object::elf::R_RISCV_CALL_PLT),
840                     RelocationEncoding::Generic,
841                     0,
842                 )
843             }
844             Reloc::RiscvTlsGdHi20 => {
845                 assert_eq!(
846                     self.object.format(),
847                     object::BinaryFormat::Elf,
848                     "RiscvTlsGdHi20 is not supported for this file format"
849                 );
850                 (
851                     RelocationKind::Elf(object::elf::R_RISCV_TLS_GD_HI20),
852                     RelocationEncoding::Generic,
853                     0,
854                 )
855             }
856             Reloc::RiscvPCRelLo12I => {
857                 assert_eq!(
858                     self.object.format(),
859                     object::BinaryFormat::Elf,
860                     "RiscvPCRelLo12I is not supported for this file format"
861                 );
862                 (
863                     RelocationKind::Elf(object::elf::R_RISCV_PCREL_LO12_I),
864                     RelocationEncoding::Generic,
865                     0,
866                 )
867             }
868             Reloc::RiscvGotHi20 => {
869                 assert_eq!(
870                     self.object.format(),
871                     object::BinaryFormat::Elf,
872                     "RiscvGotHi20 is not supported for this file format"
873                 );
874                 (
875                     RelocationKind::Elf(object::elf::R_RISCV_GOT_HI20),
876                     RelocationEncoding::Generic,
877                     0,
878                 )
879             }
880             // FIXME
881             reloc => unimplemented!("{:?}", reloc),
882         };
883 
884         ObjectRelocRecord {
885             offset: record.offset,
886             name: record.name.clone(),
887             kind,
888             encoding,
889             size,
890             addend,
891         }
892     }
893 }
894 
895 fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
896     let scope = match linkage {
897         Linkage::Import => SymbolScope::Unknown,
898         Linkage::Local => SymbolScope::Compilation,
899         Linkage::Hidden => SymbolScope::Linkage,
900         Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,
901     };
902     // TODO: this matches rustc_codegen_cranelift, but may be wrong.
903     let weak = linkage == Linkage::Preemptible;
904     (scope, weak)
905 }
906 
907 /// This is the output of `ObjectModule`'s
908 /// [`finish`](../struct.ObjectModule.html#method.finish) function.
909 /// It contains the generated `Object` and other information produced during
910 /// compilation.
911 pub struct ObjectProduct {
912     /// Object artifact with all functions and data from the module defined.
913     pub object: Object<'static>,
914     /// Symbol IDs for functions (both declared and defined).
915     pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
916     /// Symbol IDs for data objects (both declared and defined).
917     pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
918 }
919 
920 impl ObjectProduct {
921     /// Return the `SymbolId` for the given function.
922     #[inline]
923     pub fn function_symbol(&self, id: FuncId) -> SymbolId {
924         self.functions[id].unwrap().0
925     }
926 
927     /// Return the `SymbolId` for the given data object.
928     #[inline]
929     pub fn data_symbol(&self, id: DataId) -> SymbolId {
930         self.data_objects[id].unwrap().0
931     }
932 
933     /// Write the object bytes in memory.
934     #[inline]
935     pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {
936         self.object.write()
937     }
938 }
939 
940 #[derive(Clone)]
941 struct SymbolRelocs {
942     section: SectionId,
943     offset: u64,
944     relocs: Vec<ObjectRelocRecord>,
945 }
946 
947 #[derive(Clone)]
948 struct ObjectRelocRecord {
949     offset: CodeOffset,
950     name: ModuleRelocTarget,
951     kind: RelocationKind,
952     encoding: RelocationEncoding,
953     size: u8,
954     addend: Addend,
955 }
956