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::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 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
955fn 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 let weak = linkage == Linkage::Preemptible;
964 (scope, weak)
965}
966
967pub struct ObjectProduct {
972 pub object: Object<'static>,
974 pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
976 pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
978}
979
980impl ObjectProduct {
981 #[inline]
983 pub fn function_symbol(&self, id: FuncId) -> SymbolId {
984 self.functions[id].unwrap().0
985 }
986
987 #[inline]
989 pub fn data_symbol(&self, id: DataId) -> SymbolId {
990 self.data_objects[id].unwrap().0
991 }
992
993 #[inline]
995 pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {
996 self.object.write()
997 }
998}
999
1000#[derive(Clone)]
1001struct SymbolRelocs {
1002 section: SectionId,
1003 offset: u64,
1004 relocs: Vec<ObjectRelocRecord>,
1005}
1006
1007#[derive(Clone)]
1008struct ObjectRelocRecord {
1009 offset: CodeOffset,
1010 name: ModuleRelocTarget,
1011 flags: RelocationFlags,
1012 addend: Addend,
1013}