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, SectionKind, SymbolFlags, SymbolKind,
19     SymbolScope,
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         } = data;
398 
399         let pointer_reloc = match self.isa.triple().pointer_width().unwrap() {
400             PointerWidth::U16 => unimplemented!("16bit pointers"),
401             PointerWidth::U32 => Reloc::Abs4,
402             PointerWidth::U64 => Reloc::Abs8,
403         };
404         let relocs = data
405             .all_relocs(pointer_reloc)
406             .map(|record| self.process_reloc(&record))
407             .collect::<Vec<_>>();
408 
409         let section = if custom_segment_section.is_none() {
410             let section_kind = if let Init::Zeros { .. } = *init {
411                 if decl.tls {
412                     StandardSection::UninitializedTls
413                 } else {
414                     StandardSection::UninitializedData
415                 }
416             } else if decl.tls {
417                 StandardSection::Tls
418             } else if decl.writable {
419                 StandardSection::Data
420             } else if relocs.is_empty() {
421                 StandardSection::ReadOnlyData
422             } else {
423                 StandardSection::ReadOnlyDataWithRel
424             };
425             if self.per_data_object_section {
426                 // FIXME pass empty symbol name once add_subsection produces `.text` as section name
427                 // instead of `.text.` when passed an empty symbol name. (object#748) Until then
428                 // pass `subsection` to produce `.text.subsection` as section name to reduce
429                 // confusion.
430                 self.object.add_subsection(section_kind, b"subsection")
431             } else {
432                 self.object.section_id(section_kind)
433             }
434         } else {
435             if decl.tls {
436                 return Err(cranelift_module::ModuleError::Backend(anyhow::anyhow!(
437                     "Custom section not supported for TLS"
438                 )));
439             }
440             let (seg, sec) = &custom_segment_section.as_ref().unwrap();
441             self.object.add_section(
442                 seg.clone().into_bytes(),
443                 sec.clone().into_bytes(),
444                 if decl.writable {
445                     SectionKind::Data
446                 } else if relocs.is_empty() {
447                     SectionKind::ReadOnlyData
448                 } else {
449                     SectionKind::ReadOnlyDataWithRel
450                 },
451             )
452         };
453 
454         let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
455         let offset = match *init {
456             Init::Uninitialized => {
457                 panic!("data is not initialized yet");
458             }
459             Init::Zeros { size } => self
460                 .object
461                 .add_symbol_bss(symbol, section, size as u64, align),
462             Init::Bytes { ref contents } => self
463                 .object
464                 .add_symbol_data(symbol, section, &contents, align),
465         };
466         if !relocs.is_empty() {
467             self.relocs.push(SymbolRelocs {
468                 section,
469                 offset,
470                 relocs,
471             });
472         }
473         Ok(())
474     }
475 }
476 
477 impl ObjectModule {
478     fn define_function_inner(
479         &mut self,
480         func_id: FuncId,
481         alignment: u64,
482         bytes: &[u8],
483         relocs: Vec<ObjectRelocRecord>,
484     ) -> Result<(), ModuleError> {
485         info!("defining function {} with bytes", func_id);
486         let decl = self.declarations.get_function_decl(func_id);
487         let decl_name = decl.linkage_name(func_id);
488         if !decl.linkage.is_definable() {
489             return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned()));
490         }
491 
492         let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();
493         if *defined {
494             return Err(ModuleError::DuplicateDefinition(decl_name.into_owned()));
495         }
496         *defined = true;
497 
498         let align = alignment.max(self.isa.symbol_alignment());
499         let section = if self.per_function_section {
500             // FIXME pass empty symbol name once add_subsection produces `.text` as section name
501             // instead of `.text.` when passed an empty symbol name. (object#748) Until then pass
502             // `subsection` to produce `.text.subsection` as section name to reduce confusion.
503             self.object
504                 .add_subsection(StandardSection::Text, b"subsection")
505         } else {
506             self.object.section_id(StandardSection::Text)
507         };
508         let offset = self.object.add_symbol_data(symbol, section, bytes, align);
509 
510         if !relocs.is_empty() {
511             self.relocs.push(SymbolRelocs {
512                 section,
513                 offset,
514                 relocs,
515             });
516         }
517 
518         Ok(())
519     }
520 
521     /// Finalize all relocations and output an object.
522     pub fn finish(mut self) -> ObjectProduct {
523         let symbol_relocs = mem::take(&mut self.relocs);
524         for symbol in symbol_relocs {
525             for &ObjectRelocRecord {
526                 offset,
527                 ref name,
528                 flags,
529                 addend,
530             } in &symbol.relocs
531             {
532                 let target_symbol = self.get_symbol(name);
533                 self.object
534                     .add_relocation(
535                         symbol.section,
536                         Relocation {
537                             offset: symbol.offset + u64::from(offset),
538                             flags,
539                             symbol: target_symbol,
540                             addend,
541                         },
542                     )
543                     .unwrap();
544             }
545         }
546 
547         // Indicate that this object has a non-executable stack.
548         if self.object.format() == object::BinaryFormat::Elf {
549             self.object.add_section(
550                 vec![],
551                 ".note.GNU-stack".as_bytes().to_vec(),
552                 SectionKind::Linker,
553             );
554         }
555 
556         ObjectProduct {
557             object: self.object,
558             functions: self.functions,
559             data_objects: self.data_objects,
560         }
561     }
562 
563     /// This should only be called during finish because it creates
564     /// symbols for missing libcalls.
565     fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId {
566         match *name {
567             ModuleRelocTarget::User { .. } => {
568                 if ModuleDeclarations::is_function(name) {
569                     let id = FuncId::from_name(name);
570                     self.functions[id].unwrap().0
571                 } else {
572                     let id = DataId::from_name(name);
573                     self.data_objects[id].unwrap().0
574                 }
575             }
576             ModuleRelocTarget::LibCall(ref libcall) => {
577                 let name = (self.libcall_names)(*libcall);
578                 if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {
579                     symbol
580                 } else if let Some(symbol) = self.libcalls.get(libcall) {
581                     *symbol
582                 } else {
583                     let symbol = self.object.add_symbol(Symbol {
584                         name: name.as_bytes().to_vec(),
585                         value: 0,
586                         size: 0,
587                         kind: SymbolKind::Text,
588                         scope: SymbolScope::Unknown,
589                         weak: false,
590                         section: SymbolSection::Undefined,
591                         flags: SymbolFlags::None,
592                     });
593                     self.libcalls.insert(*libcall, symbol);
594                     symbol
595                 }
596             }
597             // These are "magic" names well-known to the linker.
598             // They require special treatment.
599             ModuleRelocTarget::KnownSymbol(ref known_symbol) => {
600                 if let Some(symbol) = self.known_symbols.get(known_symbol) {
601                     *symbol
602                 } else {
603                     let symbol = self.object.add_symbol(match known_symbol {
604                         ir::KnownSymbol::ElfGlobalOffsetTable => Symbol {
605                             name: b"_GLOBAL_OFFSET_TABLE_".to_vec(),
606                             value: 0,
607                             size: 0,
608                             kind: SymbolKind::Data,
609                             scope: SymbolScope::Unknown,
610                             weak: false,
611                             section: SymbolSection::Undefined,
612                             flags: SymbolFlags::None,
613                         },
614                         ir::KnownSymbol::CoffTlsIndex => Symbol {
615                             name: b"_tls_index".to_vec(),
616                             value: 0,
617                             size: 32,
618                             kind: SymbolKind::Tls,
619                             scope: SymbolScope::Unknown,
620                             weak: false,
621                             section: SymbolSection::Undefined,
622                             flags: SymbolFlags::None,
623                         },
624                     });
625                     self.known_symbols.insert(*known_symbol, symbol);
626                     symbol
627                 }
628             }
629 
630             ModuleRelocTarget::FunctionOffset(func_id, offset) => {
631                 match self.known_labels.entry((func_id, offset)) {
632                     Entry::Occupied(o) => *o.get(),
633                     Entry::Vacant(v) => {
634                         let func_symbol_id = self.functions[func_id].unwrap().0;
635                         let func_symbol = self.object.symbol(func_symbol_id);
636 
637                         let name = format!(".L{}_{}", func_id.as_u32(), offset);
638                         let symbol_id = self.object.add_symbol(Symbol {
639                             name: name.as_bytes().to_vec(),
640                             value: func_symbol.value + offset as u64,
641                             size: 0,
642                             kind: SymbolKind::Label,
643                             scope: SymbolScope::Compilation,
644                             weak: false,
645                             section: SymbolSection::Section(func_symbol.section.id().unwrap()),
646                             flags: SymbolFlags::None,
647                         });
648 
649                         v.insert(symbol_id);
650                         symbol_id
651                     }
652                 }
653             }
654         }
655     }
656 
657     fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord {
658         let flags = match record.kind {
659             Reloc::Abs4 => RelocationFlags::Generic {
660                 kind: RelocationKind::Absolute,
661                 encoding: RelocationEncoding::Generic,
662                 size: 32,
663             },
664             Reloc::Abs8 => RelocationFlags::Generic {
665                 kind: RelocationKind::Absolute,
666                 encoding: RelocationEncoding::Generic,
667                 size: 64,
668             },
669             Reloc::X86PCRel4 => RelocationFlags::Generic {
670                 kind: RelocationKind::Relative,
671                 encoding: RelocationEncoding::Generic,
672                 size: 32,
673             },
674             Reloc::X86CallPCRel4 => RelocationFlags::Generic {
675                 kind: RelocationKind::Relative,
676                 encoding: RelocationEncoding::X86Branch,
677                 size: 32,
678             },
679             // TODO: Get Cranelift to tell us when we can use
680             // R_X86_64_GOTPCRELX/R_X86_64_REX_GOTPCRELX.
681             Reloc::X86CallPLTRel4 => RelocationFlags::Generic {
682                 kind: RelocationKind::PltRelative,
683                 encoding: RelocationEncoding::X86Branch,
684                 size: 32,
685             },
686             Reloc::X86SecRel => RelocationFlags::Generic {
687                 kind: RelocationKind::SectionOffset,
688                 encoding: RelocationEncoding::Generic,
689                 size: 32,
690             },
691             Reloc::X86GOTPCRel4 => RelocationFlags::Generic {
692                 kind: RelocationKind::GotRelative,
693                 encoding: RelocationEncoding::Generic,
694                 size: 32,
695             },
696             Reloc::Arm64Call => RelocationFlags::Generic {
697                 kind: RelocationKind::Relative,
698                 encoding: RelocationEncoding::AArch64Call,
699                 size: 26,
700             },
701             Reloc::ElfX86_64TlsGd => {
702                 assert_eq!(
703                     self.object.format(),
704                     object::BinaryFormat::Elf,
705                     "ElfX86_64TlsGd is not supported for this file format"
706                 );
707                 RelocationFlags::Elf {
708                     r_type: object::elf::R_X86_64_TLSGD,
709                 }
710             }
711             Reloc::MachOX86_64Tlv => {
712                 assert_eq!(
713                     self.object.format(),
714                     object::BinaryFormat::MachO,
715                     "MachOX86_64Tlv is not supported for this file format"
716                 );
717                 RelocationFlags::MachO {
718                     r_type: object::macho::X86_64_RELOC_TLV,
719                     r_pcrel: true,
720                     r_length: 2,
721                 }
722             }
723             Reloc::MachOAarch64TlsAdrPage21 => {
724                 assert_eq!(
725                     self.object.format(),
726                     object::BinaryFormat::MachO,
727                     "MachOAarch64TlsAdrPage21 is not supported for this file format"
728                 );
729                 RelocationFlags::MachO {
730                     r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
731                     r_pcrel: true,
732                     r_length: 2,
733                 }
734             }
735             Reloc::MachOAarch64TlsAdrPageOff12 => {
736                 assert_eq!(
737                     self.object.format(),
738                     object::BinaryFormat::MachO,
739                     "MachOAarch64TlsAdrPageOff12 is not supported for this file format"
740                 );
741                 RelocationFlags::MachO {
742                     r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
743                     r_pcrel: false,
744                     r_length: 2,
745                 }
746             }
747             Reloc::Aarch64TlsDescAdrPage21 => {
748                 assert_eq!(
749                     self.object.format(),
750                     object::BinaryFormat::Elf,
751                     "Aarch64TlsDescAdrPage21 is not supported for this file format"
752                 );
753                 RelocationFlags::Elf {
754                     r_type: object::elf::R_AARCH64_TLSDESC_ADR_PAGE21,
755                 }
756             }
757             Reloc::Aarch64TlsDescLd64Lo12 => {
758                 assert_eq!(
759                     self.object.format(),
760                     object::BinaryFormat::Elf,
761                     "Aarch64TlsDescLd64Lo12 is not supported for this file format"
762                 );
763                 RelocationFlags::Elf {
764                     r_type: object::elf::R_AARCH64_TLSDESC_LD64_LO12,
765                 }
766             }
767             Reloc::Aarch64TlsDescAddLo12 => {
768                 assert_eq!(
769                     self.object.format(),
770                     object::BinaryFormat::Elf,
771                     "Aarch64TlsDescAddLo12 is not supported for this file format"
772                 );
773                 RelocationFlags::Elf {
774                     r_type: object::elf::R_AARCH64_TLSDESC_ADD_LO12,
775                 }
776             }
777             Reloc::Aarch64TlsDescCall => {
778                 assert_eq!(
779                     self.object.format(),
780                     object::BinaryFormat::Elf,
781                     "Aarch64TlsDescCall is not supported for this file format"
782                 );
783                 RelocationFlags::Elf {
784                     r_type: object::elf::R_AARCH64_TLSDESC_CALL,
785                 }
786             }
787 
788             Reloc::Aarch64AdrGotPage21 => match self.object.format() {
789                 object::BinaryFormat::Elf => RelocationFlags::Elf {
790                     r_type: object::elf::R_AARCH64_ADR_GOT_PAGE,
791                 },
792                 object::BinaryFormat::MachO => RelocationFlags::MachO {
793                     r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
794                     r_pcrel: true,
795                     r_length: 2,
796                 },
797                 _ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"),
798             },
799             Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() {
800                 object::BinaryFormat::Elf => RelocationFlags::Elf {
801                     r_type: object::elf::R_AARCH64_LD64_GOT_LO12_NC,
802                 },
803                 object::BinaryFormat::MachO => RelocationFlags::MachO {
804                     r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
805                     r_pcrel: false,
806                     r_length: 2,
807                 },
808                 _ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"),
809             },
810             Reloc::S390xPCRel32Dbl => RelocationFlags::Generic {
811                 kind: RelocationKind::Relative,
812                 encoding: RelocationEncoding::S390xDbl,
813                 size: 32,
814             },
815             Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic {
816                 kind: RelocationKind::PltRelative,
817                 encoding: RelocationEncoding::S390xDbl,
818                 size: 32,
819             },
820             Reloc::S390xTlsGd64 => {
821                 assert_eq!(
822                     self.object.format(),
823                     object::BinaryFormat::Elf,
824                     "S390xTlsGd64 is not supported for this file format"
825                 );
826                 RelocationFlags::Elf {
827                     r_type: object::elf::R_390_TLS_GD64,
828                 }
829             }
830             Reloc::S390xTlsGdCall => {
831                 assert_eq!(
832                     self.object.format(),
833                     object::BinaryFormat::Elf,
834                     "S390xTlsGdCall is not supported for this file format"
835                 );
836                 RelocationFlags::Elf {
837                     r_type: object::elf::R_390_TLS_GDCALL,
838                 }
839             }
840             Reloc::RiscvCallPlt => {
841                 assert_eq!(
842                     self.object.format(),
843                     object::BinaryFormat::Elf,
844                     "RiscvCallPlt is not supported for this file format"
845                 );
846                 RelocationFlags::Elf {
847                     r_type: object::elf::R_RISCV_CALL_PLT,
848                 }
849             }
850             Reloc::RiscvTlsGdHi20 => {
851                 assert_eq!(
852                     self.object.format(),
853                     object::BinaryFormat::Elf,
854                     "RiscvTlsGdHi20 is not supported for this file format"
855                 );
856                 RelocationFlags::Elf {
857                     r_type: object::elf::R_RISCV_TLS_GD_HI20,
858                 }
859             }
860             Reloc::RiscvPCRelLo12I => {
861                 assert_eq!(
862                     self.object.format(),
863                     object::BinaryFormat::Elf,
864                     "RiscvPCRelLo12I is not supported for this file format"
865                 );
866                 RelocationFlags::Elf {
867                     r_type: object::elf::R_RISCV_PCREL_LO12_I,
868                 }
869             }
870             Reloc::RiscvGotHi20 => {
871                 assert_eq!(
872                     self.object.format(),
873                     object::BinaryFormat::Elf,
874                     "RiscvGotHi20 is not supported for this file format"
875                 );
876                 RelocationFlags::Elf {
877                     r_type: object::elf::R_RISCV_GOT_HI20,
878                 }
879             }
880             // FIXME
881             reloc => unimplemented!("{:?}", reloc),
882         };
883 
884         ObjectRelocRecord {
885             offset: record.offset,
886             name: record.name.clone(),
887             flags,
888             addend: record.addend,
889         }
890     }
891 }
892 
893 fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
894     let scope = match linkage {
895         Linkage::Import => SymbolScope::Unknown,
896         Linkage::Local => SymbolScope::Compilation,
897         Linkage::Hidden => SymbolScope::Linkage,
898         Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,
899     };
900     // TODO: this matches rustc_codegen_cranelift, but may be wrong.
901     let weak = linkage == Linkage::Preemptible;
902     (scope, weak)
903 }
904 
905 /// This is the output of `ObjectModule`'s
906 /// [`finish`](../struct.ObjectModule.html#method.finish) function.
907 /// It contains the generated `Object` and other information produced during
908 /// compilation.
909 pub struct ObjectProduct {
910     /// Object artifact with all functions and data from the module defined.
911     pub object: Object<'static>,
912     /// Symbol IDs for functions (both declared and defined).
913     pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
914     /// Symbol IDs for data objects (both declared and defined).
915     pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
916 }
917 
918 impl ObjectProduct {
919     /// Return the `SymbolId` for the given function.
920     #[inline]
921     pub fn function_symbol(&self, id: FuncId) -> SymbolId {
922         self.functions[id].unwrap().0
923     }
924 
925     /// Return the `SymbolId` for the given data object.
926     #[inline]
927     pub fn data_symbol(&self, id: DataId) -> SymbolId {
928         self.data_objects[id].unwrap().0
929     }
930 
931     /// Write the object bytes in memory.
932     #[inline]
933     pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {
934         self.object.write()
935     }
936 }
937 
938 #[derive(Clone)]
939 struct SymbolRelocs {
940     section: SectionId,
941     offset: u64,
942     relocs: Vec<ObjectRelocRecord>,
943 }
944 
945 #[derive(Clone)]
946 struct ObjectRelocRecord {
947     offset: CodeOffset,
948     name: ModuleRelocTarget,
949     flags: RelocationFlags,
950     addend: Addend,
951 }
952