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 => {
458 let section = self.object.section_mut(section);
459 match &mut section.flags {
460 SectionFlags::None => {
461 let sh_flags = if decl.tls {
463 elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS
464 } else if decl.writable || !relocs.is_empty() {
465 elf::SHF_ALLOC | elf::SHF_WRITE
466 } else {
467 elf::SHF_ALLOC
468 };
469 section.flags = SectionFlags::Elf {
470 sh_flags: u64::from(sh_flags | elf::SHF_GNU_RETAIN),
471 }
472 }
473 SectionFlags::Elf { sh_flags } => {
474 *sh_flags |= u64::from(elf::SHF_GNU_RETAIN)
475 }
476 _ => unreachable!(),
477 }
478 }
479 object::BinaryFormat::Coff => {}
480 object::BinaryFormat::MachO => {
481 let symbol = self.object.symbol_mut(symbol);
482 assert!(matches!(symbol.flags, SymbolFlags::None));
483 let n_desc = if decl.linkage == Linkage::Preemptible {
484 object::macho::N_WEAK_DEF
485 } else {
486 0
487 };
488 symbol.flags = SymbolFlags::MachO {
489 n_desc: n_desc | object::macho::N_NO_DEAD_STRIP,
490 }
491 }
492 _ => unreachable!(),
493 }
494 }
495
496 let align = std::cmp::max(align.unwrap_or(1), self.isa.symbol_alignment());
497 let offset = match *init {
498 Init::Uninitialized => {
499 panic!("data is not initialized yet");
500 }
501 Init::Zeros { size } => self
502 .object
503 .add_symbol_bss(symbol, section, size as u64, align),
504 Init::Bytes { ref contents } => self
505 .object
506 .add_symbol_data(symbol, section, &contents, align),
507 };
508 if !relocs.is_empty() {
509 self.relocs.push(SymbolRelocs {
510 section,
511 offset,
512 relocs,
513 });
514 }
515 Ok(())
516 }
517}
518
519impl ObjectModule {
520 fn define_function_inner(
521 &mut self,
522 func_id: FuncId,
523 alignment: u64,
524 bytes: &[u8],
525 relocs: Vec<ObjectRelocRecord>,
526 ) -> Result<(), ModuleError> {
527 info!("defining function {func_id} with bytes");
528 let decl = self.declarations.get_function_decl(func_id);
529 let decl_name = decl.linkage_name(func_id);
530 if !decl.linkage.is_definable() {
531 return Err(ModuleError::InvalidImportDefinition(decl_name.into_owned()));
532 }
533
534 let &mut (symbol, ref mut defined) = self.functions[func_id].as_mut().unwrap();
535 if *defined {
536 return Err(ModuleError::DuplicateDefinition(decl_name.into_owned()));
537 }
538 *defined = true;
539
540 let align = alignment.max(self.isa.symbol_alignment());
541 let section = if self.per_function_section {
542 self.object
546 .add_subsection(StandardSection::Text, b"subsection")
547 } else {
548 self.object.section_id(StandardSection::Text)
549 };
550 let offset = self.object.add_symbol_data(symbol, section, bytes, align);
551
552 if !relocs.is_empty() {
553 self.relocs.push(SymbolRelocs {
554 section,
555 offset,
556 relocs,
557 });
558 }
559
560 Ok(())
561 }
562
563 pub fn finish(mut self) -> ObjectProduct {
565 let symbol_relocs = mem::take(&mut self.relocs);
566 for symbol in symbol_relocs {
567 for &ObjectRelocRecord {
568 offset,
569 ref name,
570 flags,
571 addend,
572 } in &symbol.relocs
573 {
574 let target_symbol = self.get_symbol(name);
575 self.object
576 .add_relocation(
577 symbol.section,
578 Relocation {
579 offset: symbol.offset + u64::from(offset),
580 flags,
581 symbol: target_symbol,
582 addend,
583 },
584 )
585 .unwrap();
586 }
587 }
588
589 if self.object.format() == object::BinaryFormat::Elf {
591 self.object.add_section(
592 vec![],
593 ".note.GNU-stack".as_bytes().to_vec(),
594 SectionKind::Linker,
595 );
596 }
597
598 ObjectProduct {
599 object: self.object,
600 functions: self.functions,
601 data_objects: self.data_objects,
602 }
603 }
604
605 fn get_symbol(&mut self, name: &ModuleRelocTarget) -> SymbolId {
608 match *name {
609 ModuleRelocTarget::User { .. } => {
610 if ModuleDeclarations::is_function(name) {
611 let id = FuncId::from_name(name);
612 self.functions[id].unwrap().0
613 } else {
614 let id = DataId::from_name(name);
615 self.data_objects[id].unwrap().0
616 }
617 }
618 ModuleRelocTarget::LibCall(ref libcall) => {
619 let name = (self.libcall_names)(*libcall);
620 if let Some(symbol) = self.object.symbol_id(name.as_bytes()) {
621 symbol
622 } else if let Some(symbol) = self.libcalls.get(libcall) {
623 *symbol
624 } else {
625 let symbol = self.object.add_symbol(Symbol {
626 name: name.as_bytes().to_vec(),
627 value: 0,
628 size: 0,
629 kind: SymbolKind::Text,
630 scope: SymbolScope::Unknown,
631 weak: false,
632 section: SymbolSection::Undefined,
633 flags: SymbolFlags::None,
634 });
635 self.libcalls.insert(*libcall, symbol);
636 symbol
637 }
638 }
639 ModuleRelocTarget::KnownSymbol(ref known_symbol) => {
642 if let Some(symbol) = self.known_symbols.get(known_symbol) {
643 *symbol
644 } else {
645 let symbol = self.object.add_symbol(match known_symbol {
646 ir::KnownSymbol::ElfGlobalOffsetTable => Symbol {
647 name: b"_GLOBAL_OFFSET_TABLE_".to_vec(),
648 value: 0,
649 size: 0,
650 kind: SymbolKind::Data,
651 scope: SymbolScope::Unknown,
652 weak: false,
653 section: SymbolSection::Undefined,
654 flags: SymbolFlags::None,
655 },
656 ir::KnownSymbol::CoffTlsIndex => Symbol {
657 name: b"_tls_index".to_vec(),
658 value: 0,
659 size: 32,
660 kind: SymbolKind::Tls,
661 scope: SymbolScope::Unknown,
662 weak: false,
663 section: SymbolSection::Undefined,
664 flags: SymbolFlags::None,
665 },
666 });
667 self.known_symbols.insert(*known_symbol, symbol);
668 symbol
669 }
670 }
671
672 ModuleRelocTarget::FunctionOffset(func_id, offset) => {
673 match self.known_labels.entry((func_id, offset)) {
674 Entry::Occupied(o) => *o.get(),
675 Entry::Vacant(v) => {
676 let func_symbol_id = self.functions[func_id].unwrap().0;
677 let func_symbol = self.object.symbol(func_symbol_id);
678
679 let name = format!(".L{}_{}", func_id.as_u32(), offset);
680 let symbol_id = self.object.add_symbol(Symbol {
681 name: name.as_bytes().to_vec(),
682 value: func_symbol.value + offset as u64,
683 size: 0,
684 kind: SymbolKind::Label,
685 scope: SymbolScope::Compilation,
686 weak: false,
687 section: SymbolSection::Section(func_symbol.section.id().unwrap()),
688 flags: SymbolFlags::None,
689 });
690
691 v.insert(symbol_id);
692 symbol_id
693 }
694 }
695 }
696 }
697 }
698
699 fn process_reloc(&self, record: &ModuleReloc) -> ObjectRelocRecord {
700 let flags = match record.kind {
701 Reloc::Abs4 => RelocationFlags::Generic {
702 kind: RelocationKind::Absolute,
703 encoding: RelocationEncoding::Generic,
704 size: 32,
705 },
706 Reloc::Abs8 => RelocationFlags::Generic {
707 kind: RelocationKind::Absolute,
708 encoding: RelocationEncoding::Generic,
709 size: 64,
710 },
711 Reloc::X86PCRel4 => RelocationFlags::Generic {
712 kind: RelocationKind::Relative,
713 encoding: RelocationEncoding::Generic,
714 size: 32,
715 },
716 Reloc::X86CallPCRel4 => RelocationFlags::Generic {
717 kind: RelocationKind::Relative,
718 encoding: RelocationEncoding::X86Branch,
719 size: 32,
720 },
721 Reloc::X86CallPLTRel4 => RelocationFlags::Generic {
724 kind: RelocationKind::PltRelative,
725 encoding: RelocationEncoding::X86Branch,
726 size: 32,
727 },
728 Reloc::X86SecRel => RelocationFlags::Generic {
729 kind: RelocationKind::SectionOffset,
730 encoding: RelocationEncoding::Generic,
731 size: 32,
732 },
733 Reloc::X86GOTPCRel4 => RelocationFlags::Generic {
734 kind: RelocationKind::GotRelative,
735 encoding: RelocationEncoding::Generic,
736 size: 32,
737 },
738 Reloc::Arm64Call => RelocationFlags::Generic {
739 kind: RelocationKind::Relative,
740 encoding: RelocationEncoding::AArch64Call,
741 size: 26,
742 },
743 Reloc::ElfX86_64TlsGd => {
744 assert_eq!(
745 self.object.format(),
746 object::BinaryFormat::Elf,
747 "ElfX86_64TlsGd is not supported for this file format"
748 );
749 RelocationFlags::Elf {
750 r_type: object::elf::R_X86_64_TLSGD,
751 }
752 }
753 Reloc::MachOX86_64Tlv => {
754 assert_eq!(
755 self.object.format(),
756 object::BinaryFormat::MachO,
757 "MachOX86_64Tlv is not supported for this file format"
758 );
759 RelocationFlags::MachO {
760 r_type: object::macho::X86_64_RELOC_TLV,
761 r_pcrel: true,
762 r_length: 2,
763 }
764 }
765 Reloc::MachOAarch64TlsAdrPage21 => {
766 assert_eq!(
767 self.object.format(),
768 object::BinaryFormat::MachO,
769 "MachOAarch64TlsAdrPage21 is not supported for this file format"
770 );
771 RelocationFlags::MachO {
772 r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21,
773 r_pcrel: true,
774 r_length: 2,
775 }
776 }
777 Reloc::MachOAarch64TlsAdrPageOff12 => {
778 assert_eq!(
779 self.object.format(),
780 object::BinaryFormat::MachO,
781 "MachOAarch64TlsAdrPageOff12 is not supported for this file format"
782 );
783 RelocationFlags::MachO {
784 r_type: object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12,
785 r_pcrel: false,
786 r_length: 2,
787 }
788 }
789 Reloc::Aarch64TlsDescAdrPage21 => {
790 assert_eq!(
791 self.object.format(),
792 object::BinaryFormat::Elf,
793 "Aarch64TlsDescAdrPage21 is not supported for this file format"
794 );
795 RelocationFlags::Elf {
796 r_type: object::elf::R_AARCH64_TLSDESC_ADR_PAGE21,
797 }
798 }
799 Reloc::Aarch64TlsDescLd64Lo12 => {
800 assert_eq!(
801 self.object.format(),
802 object::BinaryFormat::Elf,
803 "Aarch64TlsDescLd64Lo12 is not supported for this file format"
804 );
805 RelocationFlags::Elf {
806 r_type: object::elf::R_AARCH64_TLSDESC_LD64_LO12,
807 }
808 }
809 Reloc::Aarch64TlsDescAddLo12 => {
810 assert_eq!(
811 self.object.format(),
812 object::BinaryFormat::Elf,
813 "Aarch64TlsDescAddLo12 is not supported for this file format"
814 );
815 RelocationFlags::Elf {
816 r_type: object::elf::R_AARCH64_TLSDESC_ADD_LO12,
817 }
818 }
819 Reloc::Aarch64TlsDescCall => {
820 assert_eq!(
821 self.object.format(),
822 object::BinaryFormat::Elf,
823 "Aarch64TlsDescCall is not supported for this file format"
824 );
825 RelocationFlags::Elf {
826 r_type: object::elf::R_AARCH64_TLSDESC_CALL,
827 }
828 }
829
830 Reloc::Aarch64AdrGotPage21 => match self.object.format() {
831 object::BinaryFormat::Elf => RelocationFlags::Elf {
832 r_type: object::elf::R_AARCH64_ADR_GOT_PAGE,
833 },
834 object::BinaryFormat::MachO => RelocationFlags::MachO {
835 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
836 r_pcrel: true,
837 r_length: 2,
838 },
839 _ => unimplemented!("Aarch64AdrGotPage21 is not supported for this file format"),
840 },
841 Reloc::Aarch64Ld64GotLo12Nc => match self.object.format() {
842 object::BinaryFormat::Elf => RelocationFlags::Elf {
843 r_type: object::elf::R_AARCH64_LD64_GOT_LO12_NC,
844 },
845 object::BinaryFormat::MachO => RelocationFlags::MachO {
846 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
847 r_pcrel: false,
848 r_length: 2,
849 },
850 _ => unimplemented!("Aarch64Ld64GotLo12Nc is not supported for this file format"),
851 },
852 Reloc::S390xPCRel32Dbl => RelocationFlags::Generic {
853 kind: RelocationKind::Relative,
854 encoding: RelocationEncoding::S390xDbl,
855 size: 32,
856 },
857 Reloc::S390xPLTRel32Dbl => RelocationFlags::Generic {
858 kind: RelocationKind::PltRelative,
859 encoding: RelocationEncoding::S390xDbl,
860 size: 32,
861 },
862 Reloc::S390xTlsGd64 => {
863 assert_eq!(
864 self.object.format(),
865 object::BinaryFormat::Elf,
866 "S390xTlsGd64 is not supported for this file format"
867 );
868 RelocationFlags::Elf {
869 r_type: object::elf::R_390_TLS_GD64,
870 }
871 }
872 Reloc::S390xTlsGdCall => {
873 assert_eq!(
874 self.object.format(),
875 object::BinaryFormat::Elf,
876 "S390xTlsGdCall is not supported for this file format"
877 );
878 RelocationFlags::Elf {
879 r_type: object::elf::R_390_TLS_GDCALL,
880 }
881 }
882 Reloc::RiscvCallPlt => {
883 assert_eq!(
884 self.object.format(),
885 object::BinaryFormat::Elf,
886 "RiscvCallPlt is not supported for this file format"
887 );
888 RelocationFlags::Elf {
889 r_type: object::elf::R_RISCV_CALL_PLT,
890 }
891 }
892 Reloc::RiscvTlsGdHi20 => {
893 assert_eq!(
894 self.object.format(),
895 object::BinaryFormat::Elf,
896 "RiscvTlsGdHi20 is not supported for this file format"
897 );
898 RelocationFlags::Elf {
899 r_type: object::elf::R_RISCV_TLS_GD_HI20,
900 }
901 }
902 Reloc::RiscvPCRelLo12I => {
903 assert_eq!(
904 self.object.format(),
905 object::BinaryFormat::Elf,
906 "RiscvPCRelLo12I is not supported for this file format"
907 );
908 RelocationFlags::Elf {
909 r_type: object::elf::R_RISCV_PCREL_LO12_I,
910 }
911 }
912 Reloc::RiscvGotHi20 => {
913 assert_eq!(
914 self.object.format(),
915 object::BinaryFormat::Elf,
916 "RiscvGotHi20 is not supported for this file format"
917 );
918 RelocationFlags::Elf {
919 r_type: object::elf::R_RISCV_GOT_HI20,
920 }
921 }
922 reloc => unimplemented!("{:?}", reloc),
924 };
925
926 ObjectRelocRecord {
927 offset: record.offset,
928 name: record.name.clone(),
929 flags,
930 addend: record.addend,
931 }
932 }
933}
934
935fn translate_linkage(linkage: Linkage) -> (SymbolScope, bool) {
936 let scope = match linkage {
937 Linkage::Import => SymbolScope::Unknown,
938 Linkage::Local => SymbolScope::Compilation,
939 Linkage::Hidden => SymbolScope::Linkage,
940 Linkage::Export | Linkage::Preemptible => SymbolScope::Dynamic,
941 };
942 let weak = linkage == Linkage::Preemptible;
944 (scope, weak)
945}
946
947pub struct ObjectProduct {
952 pub object: Object<'static>,
954 pub functions: SecondaryMap<FuncId, Option<(SymbolId, bool)>>,
956 pub data_objects: SecondaryMap<DataId, Option<(SymbolId, bool)>>,
958}
959
960impl ObjectProduct {
961 #[inline]
963 pub fn function_symbol(&self, id: FuncId) -> SymbolId {
964 self.functions[id].unwrap().0
965 }
966
967 #[inline]
969 pub fn data_symbol(&self, id: DataId) -> SymbolId {
970 self.data_objects[id].unwrap().0
971 }
972
973 #[inline]
975 pub fn emit(self) -> Result<Vec<u8>, object::write::Error> {
976 self.object.write()
977 }
978}
979
980#[derive(Clone)]
981struct SymbolRelocs {
982 section: SectionId,
983 offset: u64,
984 relocs: Vec<ObjectRelocRecord>,
985}
986
987#[derive(Clone)]
988struct ObjectRelocRecord {
989 offset: CodeOffset,
990 name: ModuleRelocTarget,
991 flags: RelocationFlags,
992 addend: Addend,
993}