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