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