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