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