1use anyhow::anyhow;
4use cranelift_codegen::binemit::{Addend, CodeOffset, Reloc};
5use cranelift_codegen::entity::SecondaryMap;
6use cranelift_codegen::ir;
7use cranelift_codegen::isa::{OwnedTargetIsa, TargetIsa};
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, SectionFlags, SectionKind, SymbolFlags,
19 SymbolKind, SymbolScope, elf,
20};
21use std::collections::HashMap;
22use std::collections::hash_map::Entry;
23use std::mem;
24use target_lexicon::PointerWidth;
25
26pub 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
39impl ObjectBuilder {
40 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 let mut eflags = object::elf::EF_RISCV_FLOAT_ABI_DOUBLE;
85
86 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 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 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
140pub 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
158impl ObjectModule {
159 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
182fn validate_symbol(name: &str) -> ModuleResult<()> {
183 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
193impl Module for ObjectModule {
194 fn isa(&self) -> &dyn TargetIsa {
195 &*self.isa
196 }
197
198 fn declarations(&self) -> &ModuleDeclarations {
199 &self.declarations
200 }
201
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
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
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 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
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
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
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
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 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
489impl ObjectModule {
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 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 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 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 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 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
697 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 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::S390xPCRel32Dbl => RelocationFlags::Generic {
851 kind: RelocationKind::Relative,
852 encoding: RelocationEncoding::S390xDbl,
853 size: 32,
854 },
855 Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic {
856 kind: RelocationKind::PltRelative,
857 encoding: RelocationEncoding::S390xDbl,
858 size: 32,
859 },
860 Reloc::S390xTlsGd64 => {
861 assert_eq!(
862 self.object.format(),
863 object::BinaryFormat::Elf,
864 "S390xTlsGd64 is not supported for this file format"
865 );
866 RelocationFlags::Elf {
867 r_type: object::elf::R_390_TLS_GD64,
868 }
869 }
870 Reloc::S390xTlsGdCall => {
871 assert_eq!(
872 self.object.format(),
873 object::BinaryFormat::Elf,
874 "S390xTlsGdCall is not supported for this file format"
875 );
876 RelocationFlags::Elf {
877 r_type: object::elf::R_390_TLS_GDCALL,
878 }
879 }
880 Reloc::RiscvCallPlt => {
881 assert_eq!(
882 self.object.format(),
883 object::BinaryFormat::Elf,
884 "RiscvCallPlt is not supported for this file format"
885 );
886 RelocationFlags::Elf {
887 r_type: object::elf::R_RISCV_CALL_PLT,
888 }
889 }
890 Reloc::RiscvTlsGdHi20 => {
891 assert_eq!(
892 self.object.format(),
893 object::BinaryFormat::Elf,
894 "RiscvTlsGdHi20 is not supported for this file format"
895 );
896 RelocationFlags::Elf {
897 r_type: object::elf::R_RISCV_TLS_GD_HI20,
898 }
899 }
900 Reloc::RiscvPCRelLo12I => {
901 assert_eq!(
902 self.object.format(),
903 object::BinaryFormat::Elf,
904 "RiscvPCRelLo12I is not supported for this file format"
905 );
906 RelocationFlags::Elf {
907 r_type: object::elf::R_RISCV_PCREL_LO12_I,
908 }
909 }
910 Reloc::RiscvGotHi20 => {
911 assert_eq!(
912 self.object.format(),
913 object::BinaryFormat::Elf,
914 "RiscvGotHi20 is not supported for this file format"
915 );
916 RelocationFlags::Elf {
917 r_type: object::elf::R_RISCV_GOT_HI20,
918 }
919 }
920 reloc => unimplemented!("{:?}", reloc),
922 };
923
924 ObjectRelocRecord {
925 offset: record.offset,
926 name: record.name.clone(),
927 flags,
928 addend: record.addend,
929 }
930 }
931}
932
933fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
934 let scope = match linkage {
935 Linkage::Import => SymbolScope::Unknown,
936 Linkage::Local => SymbolScope::Compilation,
937 Linkage::Hidden => SymbolScope::Linkage,
938 Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,
939 };
940 let weak = linkage == Linkage::Preemptible;
942 (scope, weak)
943}
944
945pub struct ObjectProduct {
950 pub object: Object<'static>,
952 pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
954 pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
956}
957
958impl ObjectProduct {
959 #[inline]
961 pub fn function_symbol(&self, id: FuncId) -> SymbolId {
962 self.functions[id].unwrap().0
963 }
964
965 #[inline]
967 pub fn data_symbol(&self, id: DataId) -> SymbolId {
968 self.data_objects[id].unwrap().0
969 }
970
971 #[inline]
973 pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {
974 self.object.write()
975 }
976}
977
978#[derive(Clone)]
979struct SymbolRelocs {
980 section: SectionId,
981 offset: u64,
982 relocs: Vec<ObjectRelocRecord>,
983}
984
985#[derive(Clone)]
986struct ObjectRelocRecord {
987 offset: CodeOffset,
988 name: ModuleRelocTarget,
989 flags: RelocationFlags,
990 addend: Addend,
991}