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