cranelift_object/
backend.rs

1//! Defines `ObjectModule`.
2
3use anyhow::anyhow;
4use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
5use cranelift_codegen::entity::SecondaryMap;
6use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
7use cranelift_codegen::{ir, FinalizedMachReloc};
8use cranelift_control::ControlPlane;
9use cranelift_module::{
10    DataDescription, DataId, FuncId, Init, Linkage, Module, ModuleDeclarations, ModuleError,
11    ModuleReloc, ModuleRelocTarget, ModuleResult,
12};
13use log::info;
14use object::write::{
15    Object, Relocation, SectionId, StandardSection, Symbol, SymbolId, SymbolSection,
16};
17use object::{
18    RelocationEncoding, RelocationFlags, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
19    SymbolScope,
20};
21use std::collections::hash_map::Entry;
22use std::collections::HashMap;
23use std::mem;
24use target_lexicon::PointerWidth;
25
26/// A builder for `ObjectModule`.
27pub 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
38impl 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.
138pub 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
152impl 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
175fn 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
187impl 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
494impl 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
867fn 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.
883pub 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
892impl 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)]
913struct SymbolRelocs {
914    section: SectionId,
915    offset: u64,
916    relocs: Vec<ObjectRelocRecord>,
917}
918
919#[derive(Clone)]
920struct ObjectRelocRecord {
921    offset: CodeOffset,
922    name: ModuleRelocTarget,
923    flags: RelocationFlags,
924    addend: Addend,
925}