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