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